From 2e275faf5fcd1eed20acb7c19831772c37a1ae2d Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 10 May 2018 18:29:46 +0200 Subject: [PATCH 01/40] added wifi-driver (not working yet) --- arch/arm/boot/dts/mt7623.dtsi | 99 +- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 70 +- arch/arm/configs/mt7623n_evb_fwu_defconfig | 32 +- build.log | 11 + build.sh | 2 +- drivers/misc/Kconfig | 1 + drivers/misc/Makefile | 2 + drivers/misc/mediatek/Kconfig | 11 + drivers/misc/mediatek/Makefile | 19 + drivers/misc/mediatek/btif/Kconfig | 4 + drivers/misc/mediatek/btif/Makefile | 33 + drivers/misc/mediatek/btif/common/Makefile | 31 + .../misc/mediatek/btif/common/btif_dma_plat.c | 1436 ++ drivers/misc/mediatek/btif/common/btif_plat.c | 1396 ++ .../misc/mediatek/btif/common/inc/mtk_btif.h | 370 + .../mediatek/btif/common/inc/mtk_btif_exp.h | 280 + drivers/misc/mediatek/btif/common/mtk_btif.c | 3472 +++++ .../misc/mediatek/btif/common/mtk_btif_exp.c | 786 ++ .../btif/common/plat_inc/btif_dma_priv.h | 164 + .../btif/common/plat_inc/btif_dma_pub.h | 197 + .../mediatek/btif/common/plat_inc/btif_priv.h | 105 + .../mediatek/btif/common/plat_inc/btif_pub.h | 237 + .../btif/common/plat_inc/plat_common.h | 307 + drivers/misc/mediatek/connectivity/Kconfig | 299 + drivers/misc/mediatek/connectivity/Makefile | 41 + .../mediatek/connectivity/common/Makefile | 23 + .../common/common_detect/Makefile | 47 + .../common/common_detect/drv_init/Makefile | 22 + .../common_detect/drv_init/ant_drv_init.c | 38 + .../drv_init/bluetooth_drv_init.c | 35 + .../common_detect/drv_init/common_drv_init.c | 103 + .../common_detect/drv_init/conn_drv_init.c | 80 + .../common_detect/drv_init/fm_drv_init.c | 33 + .../common_detect/drv_init/gps_drv_init.c | 35 + .../common_detect/drv_init/inc/ant_drv_init.h | 20 + .../drv_init/inc/bluetooth_drv_init.h | 20 + .../drv_init/inc/common_drv_init.h | 31 + .../drv_init/inc/conn_drv_init.h | 18 + .../common_detect/drv_init/inc/fm_drv_init.h | 20 + .../common_detect/drv_init/inc/gps_drv_init.h | 19 + .../drv_init/inc/wlan_drv_init.h | 30 + .../common_detect/drv_init/wlan_drv_init.c | 74 + .../common/common_detect/mtk_wcn_stub_alps.c | 605 + .../common/common_detect/sdio_detect.c | 269 + .../common/common_detect/sdio_detect.h | 43 + .../common/common_detect/wmt_detect.c | 380 + .../common/common_detect/wmt_detect.h | 114 + .../common/common_detect/wmt_detect_pwr.c | 232 + .../common/common_detect/wmt_detect_pwr.h | 29 + .../common/common_detect/wmt_gpio.c | 371 + .../common/common_detect/wmt_gpio.h | 103 + .../common/common_detect/wmt_stp_exp.c | 480 + .../common/common_detect/wmt_stp_exp.h | 610 + .../connectivity/common/conn_soc/Makefile | 65 + .../common/conn_soc/core/Makefile | 22 + .../common/conn_soc/core/btm_core.c | 1376 ++ .../common/conn_soc/core/dbg_core.c | 13 + .../common/conn_soc/core/include/btm_core.h | 133 + .../common/conn_soc/core/include/dbg_core.h | 69 + .../common/conn_soc/core/include/psm_core.h | 251 + .../common/conn_soc/core/include/stp_core.h | 629 + .../common/conn_soc/core/include/stp_wmt.h | 89 + .../common/conn_soc/core/include/wmt_conf.h | 74 + .../common/conn_soc/core/include/wmt_core.h | 428 + .../common/conn_soc/core/include/wmt_ctrl.h | 120 + .../common/conn_soc/core/include/wmt_func.h | 140 + .../common/conn_soc/core/include/wmt_ic.h | 122 + .../common/conn_soc/core/include/wmt_lib.h | 300 + .../common/conn_soc/core/psm_core.c | 1890 +++ .../common/conn_soc/core/stp_core.c | 3358 +++++ .../common/conn_soc/core/wmt_conf.c | 529 + .../common/conn_soc/core/wmt_core.c | 2521 ++++ .../common/conn_soc/core/wmt_ctrl.c | 1019 ++ .../common/conn_soc/core/wmt_func.c | 713 + .../common/conn_soc/core/wmt_ic_soc.c | 2452 ++++ .../common/conn_soc/core/wmt_lib.c | 1938 +++ .../common/conn_soc/include/stp_exp.h | 252 + .../common/conn_soc/include/wmt.h | 19 + .../common/conn_soc/include/wmt_exp.h | 329 + .../common/conn_soc/include/wmt_plat.h | 295 + .../common/conn_soc/linux/Makefile | 6 + .../conn_soc/linux/include/bgw_desense.h | 74 + .../common/conn_soc/linux/include/osal.h | 349 + .../conn_soc/linux/include/osal_typedef.h | 90 + .../common/conn_soc/linux/include/wmt_idc.h | 97 + .../common/conn_soc/linux/pri/Makefile | 21 + .../conn_soc/linux/pri/include/stp_btif.h | 31 + .../conn_soc/linux/pri/include/stp_dbg.h | 316 + .../conn_soc/linux/pri/include/wmt_dev.h | 71 + .../common/conn_soc/linux/pri/stp_btif.c | 279 + .../common/conn_soc/linux/pri/stp_dbg.c | 2061 +++ .../common/conn_soc/linux/pri/stp_exp.c | 279 + .../common/conn_soc/linux/pri/wmt_dev.c | 2566 ++++ .../common/conn_soc/linux/pri/wmt_exp.c | 610 + .../common/conn_soc/linux/pub/Makefile | 27 + .../common/conn_soc/linux/pub/bgw_desense.c | 153 + .../common/conn_soc/linux/pub/osal.c | 1211 ++ .../common/conn_soc/linux/pub/stp_chrdev_bt.c | 899 ++ .../conn_soc/linux/pub/wmt_chrdev_wifi.c | 668 + .../common/conn_soc/linux/pub/wmt_idc.c | 307 + .../common/conn_soc/mt7623/Makefile | 25 + .../mt7623/include/mtk_wcn_consys_hw.h | 287 + .../conn_soc/mt7623/mtk_wcn_consys_hw.c | 738 ++ .../common/conn_soc/mt7623/wmt_plat_alps.c | 1071 ++ .../misc/mediatek/connectivity/wlan/Makefile | 8 + .../mediatek/connectivity/wlan/gen2/Makefile | 237 + .../connectivity/wlan/gen2/common/debug.c | 165 + .../connectivity/wlan/gen2/common/dump.c | 345 + .../connectivity/wlan/gen2/common/wlan_bow.c | 3442 +++++ .../connectivity/wlan/gen2/common/wlan_lib.c | 6240 +++++++++ .../connectivity/wlan/gen2/common/wlan_oid.c | 11050 ++++++++++++++++ .../connectivity/wlan/gen2/common/wlan_p2p.c | 1654 +++ .../wlan/gen2/include/CFG_Wifi_File.h | 238 + .../connectivity/wlan/gen2/include/config.h | 1628 +++ .../connectivity/wlan/gen2/include/debug.h | 466 + .../connectivity/wlan/gen2/include/link.h | 368 + .../wlan/gen2/include/mgmt/aa_fsm.h | 188 + .../wlan/gen2/include/mgmt/ais_fsm.h | 573 + .../wlan/gen2/include/mgmt/assoc.h | 112 + .../wlan/gen2/include/mgmt/auth.h | 125 + .../wlan/gen2/include/mgmt/bow_fsm.h | 184 + .../connectivity/wlan/gen2/include/mgmt/bss.h | 265 + .../connectivity/wlan/gen2/include/mgmt/cnm.h | 258 + .../wlan/gen2/include/mgmt/cnm_mem.h | 1164 ++ .../wlan/gen2/include/mgmt/cnm_scan.h | 169 + .../wlan/gen2/include/mgmt/cnm_timer.h | 235 + .../wlan/gen2/include/mgmt/hem_mbox.h | 446 + .../wlan/gen2/include/mgmt/hs20.h | 148 + .../connectivity/wlan/gen2/include/mgmt/mib.h | 153 + .../wlan/gen2/include/mgmt/p2p_assoc.h | 55 + .../wlan/gen2/include/mgmt/p2p_bss.h | 56 + .../wlan/gen2/include/mgmt/p2p_fsm.h | 2190 +++ .../wlan/gen2/include/mgmt/p2p_func.h | 155 + .../wlan/gen2/include/mgmt/p2p_ie.h | 156 + .../wlan/gen2/include/mgmt/p2p_rlm.h | 74 + .../wlan/gen2/include/mgmt/p2p_rlm_obss.h | 64 + .../wlan/gen2/include/mgmt/p2p_scan.h | 81 + .../wlan/gen2/include/mgmt/p2p_state.h | 43 + .../wlan/gen2/include/mgmt/privacy.h | 230 + .../wlan/gen2/include/mgmt/rate.h | 93 + .../connectivity/wlan/gen2/include/mgmt/rlm.h | 396 + .../wlan/gen2/include/mgmt/rlm_domain.h | 557 + .../wlan/gen2/include/mgmt/rlm_obss.h | 150 + .../wlan/gen2/include/mgmt/rlm_protection.h | 122 + .../wlan/gen2/include/mgmt/rlm_txpwr_init.h | 1213 ++ .../wlan/gen2/include/mgmt/roaming_fsm.h | 171 + .../connectivity/wlan/gen2/include/mgmt/rsn.h | 271 + .../wlan/gen2/include/mgmt/scan.h | 988 ++ .../wlan/gen2/include/mgmt/sec_fsm.h | 233 + .../wlan/gen2/include/mgmt/stats.h | 368 + .../wlan/gen2/include/mgmt/swcr.h | 187 + .../wlan/gen2/include/mgmt/tdls.h | 262 + .../wlan/gen2/include/mgmt/wapi.h | 104 + .../wlan/gen2/include/mgmt/wlan_typedef.h | 87 + .../connectivity/wlan/gen2/include/mgmt/wnm.h | 95 + .../wlan/gen2/include/nic/adapter.h | 1506 +++ .../connectivity/wlan/gen2/include/nic/bow.h | 322 + .../wlan/gen2/include/nic/cmd_buf.h | 150 + .../connectivity/wlan/gen2/include/nic/hal.h | 618 + .../wlan/gen2/include/nic/hif_rx.h | 220 + .../wlan/gen2/include/nic/hif_tx.h | 214 + .../connectivity/wlan/gen2/include/nic/mac.h | 2323 ++++ .../wlan/gen2/include/nic/mtreg.h | 272 + .../connectivity/wlan/gen2/include/nic/nic.h | 498 + .../wlan/gen2/include/nic/nic_rx.h | 420 + .../wlan/gen2/include/nic/nic_tx.h | 642 + .../connectivity/wlan/gen2/include/nic/p2p.h | 192 + .../wlan/gen2/include/nic/p2p_cmd_buf.h | 83 + .../wlan/gen2/include/nic/p2p_mac.h | 207 + .../wlan/gen2/include/nic/p2p_nic.h | 62 + .../wlan/gen2/include/nic/p2p_nic_cmd_event.h | 70 + .../wlan/gen2/include/nic/que_mgt.h | 971 ++ .../wlan/gen2/include/nic/wlan_def.h | 1010 ++ .../wlan/gen2/include/nic_cmd_event.h | 2290 ++++ .../wlan/gen2/include/nic_init_cmd_event.h | 177 + .../wlan/gen2/include/p2p_precomp.h | 201 + .../wlan/gen2/include/p2p_typedef.h | 165 + .../connectivity/wlan/gen2/include/precomp.h | 388 + .../connectivity/wlan/gen2/include/pwr_mgt.h | 141 + .../connectivity/wlan/gen2/include/queue.h | 195 + .../connectivity/wlan/gen2/include/rftest.h | 294 + .../wlan/gen2/include/tdls_extr.h | 427 + .../connectivity/wlan/gen2/include/typedef.h | 244 + .../connectivity/wlan/gen2/include/wlan_bow.h | 352 + .../connectivity/wlan/gen2/include/wlan_lib.h | 1001 ++ .../connectivity/wlan/gen2/include/wlan_oid.h | 1715 +++ .../connectivity/wlan/gen2/include/wlan_p2p.h | 307 + .../connectivity/wlan/gen2/mgmt/aaa_fsm.c | 1303 ++ .../connectivity/wlan/gen2/mgmt/ais_fsm.c | 5039 +++++++ .../connectivity/wlan/gen2/mgmt/assoc.c | 1932 +++ .../connectivity/wlan/gen2/mgmt/auth.c | 1211 ++ .../connectivity/wlan/gen2/mgmt/bss.c | 2521 ++++ .../connectivity/wlan/gen2/mgmt/cnm.c | 738 ++ .../connectivity/wlan/gen2/mgmt/cnm_mem.c | 1236 ++ .../connectivity/wlan/gen2/mgmt/cnm_timer.c | 482 + .../connectivity/wlan/gen2/mgmt/hem_mbox.c | 816 ++ .../connectivity/wlan/gen2/mgmt/hs20.c | 498 + .../connectivity/wlan/gen2/mgmt/mib.c | 111 + .../connectivity/wlan/gen2/mgmt/p2p_assoc.c | 87 + .../connectivity/wlan/gen2/mgmt/p2p_bss.c | 58 + .../connectivity/wlan/gen2/mgmt/p2p_fsm.c | 3139 +++++ .../connectivity/wlan/gen2/mgmt/p2p_func.c | 3796 ++++++ .../connectivity/wlan/gen2/mgmt/p2p_ie.c | 612 + .../connectivity/wlan/gen2/mgmt/p2p_rlm.c | 905 ++ .../wlan/gen2/mgmt/p2p_rlm_obss.c | 313 + .../connectivity/wlan/gen2/mgmt/p2p_scan.c | 756 ++ .../connectivity/wlan/gen2/mgmt/p2p_state.c | 466 + .../connectivity/wlan/gen2/mgmt/privacy.c | 915 ++ .../connectivity/wlan/gen2/mgmt/rate.c | 497 + .../connectivity/wlan/gen2/mgmt/rlm.c | 1858 +++ .../connectivity/wlan/gen2/mgmt/rlm_domain.c | 1791 +++ .../connectivity/wlan/gen2/mgmt/rlm_obss.c | 436 + .../wlan/gen2/mgmt/rlm_protection.c | 105 + .../connectivity/wlan/gen2/mgmt/roaming_fsm.c | 539 + .../connectivity/wlan/gen2/mgmt/rsn.c | 2533 ++++ .../connectivity/wlan/gen2/mgmt/saa_fsm.c | 1788 +++ .../connectivity/wlan/gen2/mgmt/scan.c | 3103 +++++ .../connectivity/wlan/gen2/mgmt/scan_fsm.c | 2136 +++ .../connectivity/wlan/gen2/mgmt/sec_fsm.c | 1112 ++ .../connectivity/wlan/gen2/mgmt/stats.c | 1342 ++ .../connectivity/wlan/gen2/mgmt/swcr.c | 1170 ++ .../connectivity/wlan/gen2/mgmt/tdls.c | 5199 ++++++++ .../connectivity/wlan/gen2/mgmt/tdls_com.c | 741 ++ .../connectivity/wlan/gen2/mgmt/wapi.c | 491 + .../connectivity/wlan/gen2/mgmt/wnm.c | 301 + .../connectivity/wlan/gen2/nic/cmd_buf.c | 254 + .../mediatek/connectivity/wlan/gen2/nic/nic.c | 4062 ++++++ .../wlan/gen2/nic/nic_cmd_event.c | 1636 +++ .../connectivity/wlan/gen2/nic/nic_pwr_mgt.c | 669 + .../connectivity/wlan/gen2/nic/nic_rx.c | 3782 ++++++ .../connectivity/wlan/gen2/nic/nic_tx.c | 2350 ++++ .../connectivity/wlan/gen2/nic/p2p_nic.c | 192 + .../connectivity/wlan/gen2/nic/que_mgt.c | 5038 +++++++ .../connectivity/wlan/gen2/os/linux/gl_bow.c | 1177 ++ .../wlan/gen2/os/linux/gl_cfg80211.c | 3110 +++++ .../connectivity/wlan/gen2/os/linux/gl_init.c | 3501 +++++ .../connectivity/wlan/gen2/os/linux/gl_kal.c | 4799 +++++++ .../connectivity/wlan/gen2/os/linux/gl_p2p.c | 4671 +++++++ .../wlan/gen2/os/linux/gl_p2p_cfg80211.c | 1935 +++ .../wlan/gen2/os/linux/gl_p2p_init.c | 433 + .../wlan/gen2/os/linux/gl_p2p_kal.c | 1314 ++ .../connectivity/wlan/gen2/os/linux/gl_proc.c | 1020 ++ .../connectivity/wlan/gen2/os/linux/gl_rst.c | 228 + .../wlan/gen2/os/linux/gl_vendor.c | 1220 ++ .../connectivity/wlan/gen2/os/linux/gl_wext.c | 4158 ++++++ .../wlan/gen2/os/linux/gl_wext_priv.c | 3142 +++++ .../wlan/gen2/os/linux/hif/ahb/ahb.c | 1643 +++ .../wlan/gen2/os/linux/hif/ahb/arm.c | 31 + .../wlan/gen2/os/linux/hif/ahb/include/hif.h | 340 + .../gen2/os/linux/hif/ahb/include/hif_gdma.h | 154 + .../gen2/os/linux/hif/ahb/include/hif_pdma.h | 141 + .../os/linux/hif/ahb/include/mtk_porting.h | 91 + .../gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c | 480 + .../wlan/gen2/os/linux/include/gl_cfg80211.h | 341 + .../wlan/gen2/os/linux/include/gl_kal.h | 1565 +++ .../wlan/gen2/os/linux/include/gl_os.h | 1270 ++ .../wlan/gen2/os/linux/include/gl_p2p_ioctl.h | 743 ++ .../wlan/gen2/os/linux/include/gl_p2p_kal.h | 243 + .../wlan/gen2/os/linux/include/gl_p2p_os.h | 242 + .../wlan/gen2/os/linux/include/gl_rst.h | 133 + .../wlan/gen2/os/linux/include/gl_sec.h | 21 + .../wlan/gen2/os/linux/include/gl_typedef.h | 298 + .../wlan/gen2/os/linux/include/gl_vendor.h | 619 + .../wlan/gen2/os/linux/include/gl_wext.h | 357 + .../wlan/gen2/os/linux/include/gl_wext_priv.h | 402 + .../wlan/gen2/os/linux/platform.c | 542 + .../connectivity/wlan/gen2/os/version.h | 190 + drivers/misc/mediatek/include/mt-plat/aee.h | 284 + .../misc/mediatek/include/mt-plat/mrdump.h | 204 + .../mt-plat/mt7622/include/mach/mtk_thermal.h | 295 + .../mt8127/include/mach/mt_freqhopping.h | 159 + .../mt8127/include/mach/mt_spm_mtcmos.h | 37 + .../mt8127/include/mach/mtk_boot_share_page.h | 40 + .../mt-plat/mt8127/include/mach/mtk_thermal.h | 301 + .../misc/mediatek/include/mt-plat/mt_sched.h | 34 + .../misc/mediatek/include/mt-plat/mtk_io.h | 23 + .../misc/mediatek/include/mt-plat/mtk_lpae.h | 62 + .../include/mt-plat/mtk_mdm_monitor.h | 42 + .../include/mt-plat/mtk_platform_debug.h | 28 + .../include/mt-plat/mtk_ram_console.h | 162 + .../misc/mediatek/include/mt-plat/mtk_rtc.h | 85 + .../include/mt-plat/mtk_thermal_ext_control.h | 69 + .../include/mt-plat/mtk_thermal_monitor.h | 102 + .../include/mt-plat/mtk_thermal_platform.h | 114 + .../include/mt-plat/mtk_thermal_trace.h | 47 + .../include/mt-plat/mtk_thermal_typedefs.h | 241 + .../include/mt-plat/mtk_wcn_cmb_stub.h | 185 + .../misc/mediatek/include/mt-plat/rt-regmap.h | 291 + .../mediatek/include/mt-plat/sync_write.h | 88 + .../misc/mediatek/include/mt-plat/wakelock.h | 67 + drivers/soc/mediatek/mtk-pmic-wrap.c | 16 + include/linux/soc/mediatek/pmic_wrap.h | 19 + include/linux/wakelock.h | 67 + include/net/genetlink.h | 46 + include/uapi/linux/genetlink.h | 1 + 295 files changed, 214260 insertions(+), 72 deletions(-) create mode 100644 build.log create mode 100644 drivers/misc/mediatek/Kconfig create mode 100644 drivers/misc/mediatek/Makefile create mode 100644 drivers/misc/mediatek/btif/Kconfig create mode 100644 drivers/misc/mediatek/btif/Makefile create mode 100644 drivers/misc/mediatek/btif/common/Makefile create mode 100644 drivers/misc/mediatek/btif/common/btif_dma_plat.c create mode 100644 drivers/misc/mediatek/btif/common/btif_plat.c create mode 100644 drivers/misc/mediatek/btif/common/inc/mtk_btif.h create mode 100644 drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h create mode 100644 drivers/misc/mediatek/btif/common/mtk_btif.c create mode 100644 drivers/misc/mediatek/btif/common/mtk_btif_exp.c create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h create mode 100644 drivers/misc/mediatek/btif/common/plat_inc/plat_common.h create mode 100644 drivers/misc/mediatek/connectivity/Kconfig create mode 100644 drivers/misc/mediatek/connectivity/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c create mode 100644 drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c create mode 100644 drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/Makefile create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c create mode 100644 drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h create mode 100644 drivers/misc/mediatek/include/mt-plat/aee.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mrdump.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mt_sched.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_io.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_lpae.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_rtc.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h create mode 100644 drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h create mode 100644 drivers/misc/mediatek/include/mt-plat/rt-regmap.h create mode 100644 drivers/misc/mediatek/include/mt-plat/sync_write.h create mode 100644 drivers/misc/mediatek/include/mt-plat/wakelock.h create mode 100644 include/linux/soc/mediatek/pmic_wrap.h create mode 100644 include/linux/wakelock.h diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index bb0c5c1bfaf7d..13d60589b3899 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 MediaTek Inc. + * Copyright (c) 2017-2018 MediaTek Inc. * Author: John Crispin * Sean Wang * @@ -28,7 +28,7 @@ compatible = "mediatek,mt7623"; interrupt-parent = <&sysirq>; - cpu_opp_table: opp_table { + cpu_opp_table: opp-table { compatible = "operating-points-v2"; opp-shared; @@ -96,6 +96,9 @@ device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x1>; + clocks = <&infracfg CLK_INFRA_CPUSEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; operating-points-v2 = <&cpu_opp_table>; clock-frequency = <1300000000>; }; @@ -104,6 +107,9 @@ device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x2>; + clocks = <&infracfg CLK_INFRA_CPUSEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; operating-points-v2 = <&cpu_opp_table>; clock-frequency = <1300000000>; }; @@ -112,6 +118,9 @@ device_type = "cpu"; compatible = "arm,cortex-a7"; reg = <0x3>; + clocks = <&infracfg CLK_INFRA_CPUSEL>, + <&apmixedsys CLK_APMIXED_MAINPLL>; + clock-names = "cpu", "intermediate"; operating-points-v2 = <&cpu_opp_table>; clock-frequency = <1300000000>; }; @@ -138,32 +147,32 @@ }; thermal-zones { - cpu_thermal: cpu_thermal { + cpu_thermal: cpu-thermal { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&thermal 0>; trips { - cpu_passive: cpu_passive { + cpu_passive: cpu-passive { temperature = <47000>; hysteresis = <2000>; type = "passive"; }; - cpu_active: cpu_active { + cpu_active: cpu-active { temperature = <67000>; hysteresis = <2000>; type = "active"; }; - cpu_hot: cpu_hot { + cpu_hot: cpu-hot { temperature = <87000>; hysteresis = <2000>; type = "hot"; }; - cpu_crit { + cpu-crit { temperature = <107000>; hysteresis = <2000>; type = "critical"; @@ -350,17 +359,6 @@ #io-channel-cells = <1>; }; - uart2: serial@11004000 { - compatible = "mediatek,mt7623-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11004000 0 0x400>; - interrupts = ; - clocks = <&pericfg CLK_PERI_UART2_SEL>, - <&pericfg CLK_PERI_UART2>; - clock-names = "baud", "bus"; - status = "disabled"; - }; - uart0: serial@11002000 { compatible = "mediatek,mt7623-uart", "mediatek,mt6577-uart"; @@ -383,6 +381,17 @@ status = "disabled"; }; + uart2: serial@11004000 { + compatible = "mediatek,mt7623-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&pericfg CLK_PERI_UART2_SEL>, + <&pericfg CLK_PERI_UART2>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + uart3: serial@11005000 { compatible = "mediatek,mt7623-uart", "mediatek,mt6577-uart"; @@ -485,6 +494,18 @@ nvmem-cell-names = "calibration-data"; }; + btif: serial@1100c000 { + compatible = "mediatek,mt7623-btif", + "mediatek,mtk-btif"; + reg = <0 0x1100c000 0 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI_BTIF>; + clock-names = "main"; + reg-shift = <2>; + reg-io-width = <4>; + status = "disabled"; + }; + nandc: nfi@1100d000 { compatible = "mediatek,mt7623-nfc", "mediatek,mt2701-nfc"; @@ -510,6 +531,18 @@ status = "disabled"; }; + nor_flash: spi@11014000 { + compatible = "mediatek,mt7623-nor", + "mediatek,mt8173-nor"; + reg = <0 0x11014000 0 0x1000>; + clocks = <&pericfg CLK_PERI_FLASH>, + <&topckgen CLK_TOP_FLASH_SEL>; + clock-names = "spi", "sf"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + spi1: spi@11016000 { compatible = "mediatek,mt7623-spi", "mediatek,mt2701-spi"; @@ -639,24 +672,24 @@ "top_syspll_d5"; }; - mmc1: mmc@11240000 { + mmc0: mmc@11230000 { compatible = "mediatek,mt7623-mmc", "mediatek,mt2701-mmc"; - reg = <0 0x11240000 0 0x1000>; - interrupts = ; - clocks = <&pericfg CLK_PERI_MSDC30_1>, - <&topckgen CLK_TOP_MSDC30_1_SEL>; + reg = <0 0x11230000 0 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI_MSDC30_0>, + <&topckgen CLK_TOP_MSDC30_0_SEL>; clock-names = "source", "hclk"; status = "disabled"; }; - mmc0: mmc@11230000 { + mmc1: mmc@11240000 { compatible = "mediatek,mt7623-mmc", "mediatek,mt2701-mmc"; - reg = <0 0x11230000 0 0x1000>; - interrupts = ; - clocks = <&pericfg CLK_PERI_MSDC30_0>, - <&topckgen CLK_TOP_MSDC30_0_SEL>; + reg = <0 0x11240000 0 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI_MSDC30_1>, + <&topckgen CLK_TOP_MSDC30_1_SEL>; clock-names = "source", "hclk"; status = "disabled"; }; @@ -761,6 +794,16 @@ #reset-cells = <1>; }; + hsdma: dma-controller@1b007000 { + compatible = "mediatek,mt7623-hsdma"; + reg = <0 0x1b007000 0 0x1000>; + interrupts = ; + clocks = <ðsys CLK_ETHSYS_HSDMA>; + clock-names = "hsdma"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; + #dma-cells = <1>; + }; + eth: ethernet@1b100000 { compatible = "mediatek,mt7623-eth", "mediatek,mt2701-eth", diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 024bdb7d6cca5..40f5b1213e76e 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -1,5 +1,5 @@ /* - * Copyright 2017 Sean Wang + * Copyright 2017-2018 Sean Wang * * SPDX-License-Identifier: (GPL-2.0+ OR MIT) */ @@ -57,7 +57,7 @@ regulator-always-on; }; - gpio_keys { + gpio-keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&key_pins_a>; @@ -104,6 +104,10 @@ }; }; +&btif { + status = "okay"; +}; + &cir { pinctrl-names = "default"; pinctrl-0 = <&cir_pins_a>; @@ -138,7 +142,6 @@ #address-cells = <1>; #size-cells = <0>; reg = <0>; - pinctrl-names = "default"; reset-gpios = <&pio 33 0>; core-supply = <&mt6323_vpa_reg>; io-supply = <&mt6323_vemc3v3_reg>; @@ -229,14 +232,14 @@ &pio { cir_pins_a:cir@0 { - pins_cir { + pins-cir { pinmux = ; bias-disable; }; }; i2c0_pins_a: i2c@0 { - pins_i2c0 { + pins-i2c0 { pinmux = , ; bias-disable; @@ -244,7 +247,7 @@ }; i2c1_pins_a: i2c@1 { - pin_i2c1 { + pin-i2c1 { pinmux = , ; bias-disable; @@ -252,7 +255,7 @@ }; i2s0_pins_a: i2s@0 { - pin_i2s0 { + pin-i2s0 { pinmux = , , , @@ -264,7 +267,7 @@ }; i2s1_pins_a: i2s@1 { - pin_i2s1 { + pin-i2s1 { pinmux = , , , @@ -276,7 +279,7 @@ }; key_pins_a: keys@0 { - pins_keys { + pins-keys { pinmux = , ; input-enable; @@ -284,7 +287,7 @@ }; led_pins_a: leds@0 { - pins_leds { + pins-leds { pinmux = , , ; @@ -292,7 +295,7 @@ }; mmc0_pins_default: mmc0default { - pins_cmd_dat { + pins-cmd-dat { pinmux = , , , @@ -306,19 +309,19 @@ bias-pull-up; }; - pins_clk { + pins-clk { pinmux = ; bias-pull-down; }; - pins_rst { + pins-rst { pinmux = ; bias-pull-up; }; }; mmc0_pins_uhs: mmc0 { - pins_cmd_dat { + pins-cmd-dat { pinmux = , , , @@ -333,20 +336,20 @@ bias-pull-up = ; }; - pins_clk { + pins-clk { pinmux = ; drive-strength = ; bias-pull-down = ; }; - pins_rst { + pins-rst { pinmux = ; bias-pull-up; }; }; mmc1_pins_default: mmc1default { - pins_cmd_dat { + pins-cmd-dat { pinmux = , , , @@ -357,26 +360,26 @@ bias-pull-up = ; }; - pins_clk { + pins-clk { pinmux = ; bias-pull-down; drive-strength = ; }; - pins_wp { + pins-wp { pinmux = ; input-enable; bias-pull-up; }; - pins_insert { + pins-insert { pinmux = ; bias-pull-up; }; }; mmc1_pins_uhs: mmc1 { - pins_cmd_dat { + pins-cmd-dat { pinmux = , , , @@ -387,7 +390,7 @@ bias-pull-up = ; }; - pins_clk { + pins-clk { pinmux = ; drive-strength = ; bias-pull-down = ; @@ -395,7 +398,7 @@ }; pwm_pins_a: pwm@0 { - pins_pwm { + pins-pwm { pinmux = , , , @@ -405,7 +408,7 @@ }; spi0_pins_a: spi@0 { - pins_spi { + pins-spi { pinmux = , , , @@ -415,25 +418,32 @@ }; uart0_pins_a: uart@0 { - pins_dat { + pins-dat { pinmux = , ; }; }; uart1_pins_a: uart@1 { - pins_dat { + pins-dat { pinmux = , ; }; }; uart2_pins_a: uart@2 { - pins_dat { + pins-dat { pinmux = , ; }; }; + + uart3_pins_a: uart@3 { + pins_dat { + pinmux = , + ; + }; + }; }; &pwm { @@ -494,6 +504,12 @@ status = "okay"; }; +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&uart3_pins_a>; + status = "okay"; +}; + &usb1 { vusb33-supply = <®_3p3v>; vbus-supply = <®_5v>; diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 5406772115853..33903633e4c43 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -259,33 +259,33 @@ CONFIG_CFG80211=y #internal wlan (not working yet) # CONFIG_MTK_CONN_LTE_IDC_SUPPORT is not set -#CONFIG_MTK_COMBO=y -#CONFIG_MTK_COMBO_CHIP_CONSYS_7623=y +CONFIG_MTK_COMBO=y +CONFIG_MTK_COMBO_CHIP_CONSYS_7623=y #used in 4.4, but should be set in Kconfig by selecting mt7623 COMBO -#CONFIG_MTK_PLATFORM="mt7623" +CONFIG_MTK_PLATFORM="mt7623" -#CONFIG_MTK_COMBO_COMM=y -#CONFIG_MTK_COMBO_WIFI=y -#CONFIG_NL80211_TESTMODE=y +CONFIG_MTK_COMBO_COMM=y +CONFIG_MTK_COMBO_WIFI=y +CONFIG_NL80211_TESTMODE=y #internal Bluetooth (also not working yet) -#CONFIG_BT=y -#CONFIG_MTK_COMBO_BT=y -#CONFIG_MTK_COMBO_BT_HCI=y +CONFIG_BT=y +CONFIG_MTK_COMBO_BT=y +CONFIG_MTK_COMBO_BT_HCI=y #needed for BT? #Bluetooth Classic (BR/EDR) features -#CONFIG_BT_BREDR=y +CONFIG_BT_BREDR=y #Bluetooth High Speed (HS) features -#CONFIG_BT_HS=y +CONFIG_BT_HS=y #Bluetooth Low Energy (LE) features -#CONFIG_BT_LE=y +CONFIG_BT_LE=y #Export Bluetooth internals in debugfs -#CONFIG_BT_DEBUGFS=y +CONFIG_BT_DEBUGFS=y #to run bluetoothd rfkill needed -#CONFIG_RFKILL_LEDS=y -#CONFIG_RFKILL_INPUT=y -#CONFIG_RFKILL_GPIO=y +CONFIG_RFKILL_LEDS=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_GPIO=y #if you use a mt76x2 or mt76x3 pcie-card diff --git a/build.log b/build.log new file mode 100644 index 0000000000000..36f9622df99d2 --- /dev/null +++ b/build.log @@ -0,0 +1,11 @@ +drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c:32:36: fatal error: soc/mediatek/pmic_wrap.h: No such file or directory +compilation terminated. +make[7]: *** [drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.o] Error 1 +make[6]: *** [drivers/misc/mediatek/connectivity/common/conn_soc/mt7623] Error 2 +make[5]: *** [drivers/misc/mediatek/connectivity/common/conn_soc] Error 2 +make[4]: *** [drivers/misc/mediatek/connectivity/common] Error 2 +make[3]: *** [drivers/misc/mediatek/connectivity] Error 2 +make[2]: *** [drivers/misc/mediatek] Error 2 +make[1]: *** [drivers/misc] Error 2 +make[1]: *** Waiting for unfinished jobs.... +make: *** [drivers] Error 2 diff --git a/build.sh b/build.sh index dde379a25c2f9..ab2cd5d6c88fe 100755 --- a/build.sh +++ b/build.sh @@ -261,7 +261,7 @@ if [ -n "$kernver" ]; then exit 1; fi; $0 build - $0 cryptodev +# $0 cryptodev if [ -e "./uImage" ]; then echo "===========================================" echo "1) pack" diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 03605f8fc0dc9..e997b9334cd5b 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -514,4 +514,5 @@ source "drivers/misc/echo/Kconfig" source "drivers/misc/cxl/Kconfig" source "drivers/misc/ocxl/Kconfig" source "drivers/misc/cardreader/Kconfig" +source "drivers/misc/mediatek/Kconfig" endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index c3c8624f4d950..baa6d40550dce 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -75,3 +75,5 @@ OBJCOPYFLAGS_lkdtm_rodata_objcopy.o := \ targets += lkdtm_rodata.o lkdtm_rodata_objcopy.o $(obj)/lkdtm_rodata_objcopy.o: $(obj)/lkdtm_rodata.o FORCE $(call if_changed,objcopy) + +obj-$(CONFIG_MTK_COMBO) += mediatek/ diff --git a/drivers/misc/mediatek/Kconfig b/drivers/misc/mediatek/Kconfig new file mode 100644 index 0000000000000..4829a6598c7aa --- /dev/null +++ b/drivers/misc/mediatek/Kconfig @@ -0,0 +1,11 @@ +menu "Mediatek Peripherals " + +config MTK_PLATFORM + string "MTK platform name" +source "drivers/misc/mediatek/btif/Kconfig" + +menu "Modem & Connectivity related configs" +source "drivers/misc/mediatek/connectivity/Kconfig" +endmenu + +endmenu # CONN diff --git a/drivers/misc/mediatek/Makefile b/drivers/misc/mediatek/Makefile new file mode 100644 index 0000000000000..5e7f06db38f28 --- /dev/null +++ b/drivers/misc/mediatek/Makefile @@ -0,0 +1,19 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# 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. +# + +#$(call all-subdir-src-or-makefile) +subdir-ccflags-y += -Werror +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/ + +obj-$(CONFIG_MTK_COMBO) += connectivity/ +obj-$(CONFIG_MTK_BTIF) += btif/ diff --git a/drivers/misc/mediatek/btif/Kconfig b/drivers/misc/mediatek/btif/Kconfig new file mode 100644 index 0000000000000..908898bd95c3d --- /dev/null +++ b/drivers/misc/mediatek/btif/Kconfig @@ -0,0 +1,4 @@ +config MTK_BTIF + tristate"MediaTek BTIF Driver" + help + MTK connectivity BTIF driver for A/D die diff --git a/drivers/misc/mediatek/btif/Makefile b/drivers/misc/mediatek/btif/Makefile new file mode 100644 index 0000000000000..2be3ab66f4268 --- /dev/null +++ b/drivers/misc/mediatek/btif/Makefile @@ -0,0 +1,33 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# 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. +# + +# BTIF driver for AD DIE +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) + #subdir-ccflags-y can be used in 2.6.34 in the future + MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM)) + subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include + subdir-ccflags-y += -I$(srctree)/arch/arm/mach-$(MTK_PLATFORM)/include/mach + subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat + + obj-y += common/ + +# Otherwise we were called directly from the command +# line; invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif diff --git a/drivers/misc/mediatek/btif/common/Makefile b/drivers/misc/mediatek/btif/common/Makefile new file mode 100644 index 0000000000000..61e9d4ea9e890 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/Makefile @@ -0,0 +1,31 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# 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. +# + +# BTIF driver for AD DIE +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) + ccflags-y += -I$(src)/inc + ccflags-y += -I$(src)/plat_inc + + obj-y += btif.o + btif-y := mtk_btif.o mtk_btif_exp.o btif_dma_plat.o btif_plat.o + +# Otherwise we were called directly from the command +# line; invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif diff --git a/drivers/misc/mediatek/btif/common/btif_dma_plat.c b/drivers/misc/mediatek/btif/common/btif_dma_plat.c new file mode 100644 index 0000000000000..58be46927953b --- /dev/null +++ b/drivers/misc/mediatek/btif/common/btif_dma_plat.c @@ -0,0 +1,1436 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 +#include + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "MTK-BTIF-DMA" + +#include "btif_dma_priv.h" + +#define DMA_USER_ID "btif_driver" + +/************************************Global variable***********************************/ + +static MTK_BTIF_DMA_VFIFO mtk_tx_dma_vfifo = { + .vfifo = { + .p_vir_addr = NULL, + .phy_addr = 0, + .vfifo_size = TX_DMA_VFF_SIZE, + .thre = DMA_TX_THRE(TX_DMA_VFF_SIZE), + }, + .wpt = 0, + .last_wpt_wrap = 0, + .rpt = 0, + .last_rpt_wrap = 0, +}; + +static MTK_BTIF_IRQ_STR mtk_btif_tx_dma_irq = { + .name = "mtk btif tx dma irq", + .is_irq_sup = true, + .reg_flag = false, +#ifdef CONFIG_OF + .irq_flags = IRQF_TRIGGER_NONE, +#else + .irq_id = MT_DMA_BTIF_TX_IRQ_ID, + .sens_type = IRQ_SENS_LVL, + .lvl_type = IRQ_LVL_LOW, +#endif + .p_irq_handler = NULL, +}; + +static MTK_BTIF_DMA_VFIFO mtk_rx_dma_vfifo = { + .vfifo = { + .p_vir_addr = NULL, + .phy_addr = 0, + .vfifo_size = RX_DMA_VFF_SIZE, + .thre = DMA_RX_THRE(RX_DMA_VFF_SIZE), + }, + + .wpt = 0, + .last_wpt_wrap = 0, + .rpt = 0, + .last_rpt_wrap = 0, +}; + +static MTK_BTIF_IRQ_STR mtk_btif_rx_dma_irq = { + .name = "mtk btif rx dma irq", + .is_irq_sup = true, + .reg_flag = false, +#ifdef CONFIG_OF + .irq_flags = IRQF_TRIGGER_NONE, +#else + .irq_id = MT_DMA_BTIF_RX_IRQ_ID, + .sens_type = IRQ_SENS_LVL, + .lvl_type = IRQ_LVL_LOW, +#endif + .p_irq_handler = NULL, +}; + +static MTK_DMA_INFO_STR mtk_btif_tx_dma = { +#ifndef CONFIG_OF + .base = AP_DMA_BASE + BTIF_TX_DMA_OFFSET, +#endif + .dir = DMA_DIR_TX, + .p_irq = &mtk_btif_tx_dma_irq, + .p_vfifo = &(mtk_tx_dma_vfifo.vfifo), +}; + +static MTK_DMA_INFO_STR mtk_btif_rx_dma = { +#ifndef CONFIG_OF + .base = AP_DMA_BASE + BTIF_RX_DMA_OFFSET, +#endif + .dir = DMA_DIR_RX, + .p_irq = &mtk_btif_rx_dma_irq, + .p_vfifo = &(mtk_rx_dma_vfifo.vfifo), +}; + +static spinlock_t g_clk_cg_spinlock; /*dma clock's spinlock */ + +/************************************Function declearation***********************************/ +static int _is_tx_dma_in_flush(P_MTK_DMA_INFO_STR p_dma_info); +static int _tx_dma_flush(P_MTK_DMA_INFO_STR p_dma_info); +static int btif_rx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_DMA_CTRL ctrl_id); +static int btif_tx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_DMA_CTRL ctrl_id); +static int btif_rx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); +static int btif_tx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); +static int hal_rx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_BTIF_REG_ID flag); +static int hal_tx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_BTIF_REG_ID flag); +static int is_tx_dma_irq_finish_done(P_MTK_DMA_INFO_STR p_dma_info); +static int _btif_dma_dump_dbg_reg(void); +static void hal_btif_tx_dma_vff_set_for_4g(void); +static void hal_btif_rx_dma_vff_set_for_4g(void); + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_ier_ctrl +* DESCRIPTION +* BTIF Tx DMA's interrupt enable/disable +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* enable [IN] control if tx interrupt enabled or not +* dma_dir [IN] DMA's direction +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int hal_btif_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en); + +/***************************************************************************** +* FUNCTION +* hal_dma_receive_data +* DESCRIPTION +* receive data from btif module in DMA polling mode +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* positive means data is available, 0 means no data available +*****************************************************************************/ +#ifndef MTK_BTIF_MARK_UNUSED_API +static int hal_dma_receive_data(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, + const unsigned int max_len); + +/************************************Function***********************************/ +#endif + +#ifdef CONFIG_OF +static void hal_dma_set_default_setting(ENUM_DMA_DIR dma_dir) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = {0, 0, 0}; + unsigned int phy_base; + + if (dma_dir == DMA_DIR_RX) { + node = of_find_compatible_node(NULL, NULL, "mediatek,btif_rx"); + if (node) { + mtk_btif_rx_dma.p_irq->irq_id = irq_of_parse_and_map(node, 0); + /*fixme, be compitable arch 64bits*/ + mtk_btif_rx_dma.base = (unsigned long)of_iomap(node, 0); + BTIF_INFO_FUNC("get rx_dma irq(%d),register base(0x%lx)\n", + mtk_btif_rx_dma.p_irq->irq_id, mtk_btif_rx_dma.base); + } else { + BTIF_ERR_FUNC("get rx_dma device node fail\n"); + } + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); + } else { + mtk_btif_rx_dma.p_irq->irq_flags = irq_info[2]; + BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", + mtk_btif_rx_dma.p_irq->irq_flags); + } + if (of_property_read_u32_index(node, "reg", 1, &phy_base)) { + BTIF_ERR_FUNC("get register phy base from DTS fail,dma_dir(%d)\n", + dma_dir); + } else { + BTIF_INFO_FUNC("get register phy base dma_dir(%d)(0x%x)\n", + dma_dir, (unsigned int)phy_base); + } + } else if (dma_dir == DMA_DIR_TX) { + node = of_find_compatible_node(NULL, NULL, "mediatek,btif_tx"); + if (node) { + mtk_btif_tx_dma.p_irq->irq_id = irq_of_parse_and_map(node, 0); + /*fixme, be compitable arch 64bits*/ + mtk_btif_tx_dma.base = (unsigned long)of_iomap(node, 0); + BTIF_INFO_FUNC("get tx_dma irq(%d),register base(0x%lx)\n", + mtk_btif_tx_dma.p_irq->irq_id, mtk_btif_tx_dma.base); + } else { + BTIF_ERR_FUNC("get tx_dma device node fail\n"); + } + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); + } else { + mtk_btif_tx_dma.p_irq->irq_flags = irq_info[2]; + BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", + mtk_btif_tx_dma.p_irq->irq_flags); + } + + if (of_property_read_u32_index(node, "reg", 1, &phy_base)) { + BTIF_ERR_FUNC("get register phy base from DTS fail,dma_dir(%d)\n", + dma_dir); + } else { + BTIF_INFO_FUNC("get register phy base dma_dir(%d)(0x%x)\n", + dma_dir, (unsigned int)phy_base); + } + } + +} +#endif + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_info_get +* DESCRIPTION +* get btif tx dma channel's information +* PARAMETERS +* dma_dir [IN] DMA's direction +* RETURNS +* pointer to btif dma's information structure +*****************************************************************************/ +P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir) +{ + P_MTK_DMA_INFO_STR p_dma_info = NULL; + + BTIF_TRC_FUNC(); +#ifdef CONFIG_OF + hal_dma_set_default_setting(dma_dir); +#endif + if (dma_dir == DMA_DIR_RX) + /*Rx DMA*/ + p_dma_info = &mtk_btif_rx_dma; + else if (dma_dir == DMA_DIR_TX) + /*Tx DMA*/ + p_dma_info = &mtk_btif_tx_dma; + else + /*print error log*/ + BTIF_ERR_FUNC("invalid DMA dir (%d)\n", dma_dir); + spin_lock_init(&g_clk_cg_spinlock); + BTIF_TRC_FUNC(); + return p_dma_info; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_clk_ctrl +* DESCRIPTION +* control clock output enable/disable of DMA module +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dma_clk_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_CLOCK_CTRL flag) +{ +/*In MTK DMA BTIF channel, there's only one global CG on AP_DMA, no sub channel's CG bit*/ +/*according to Artis's comment, clock of DMA and BTIF is default off, so we assume it to be off by default*/ + int i_ret = 0; + unsigned long irq_flag = 0; + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + static atomic_t s_clk_ref = ATOMIC_INIT(0); +#else + static ENUM_CLOCK_CTRL status = CLK_OUT_DISABLE; +#endif + + spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); + +#if MTK_BTIF_ENABLE_CLK_CTL + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + + if (flag == CLK_OUT_ENABLE) { + if (atomic_inc_return(&s_clk_ref) == 1) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = enable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); +#else + BTIF_DBG_FUNC("[CCF]enable clk_btif_apdma\n"); + i_ret = clk_enable(clk_btif_apdma); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + if (i_ret) { + BTIF_WARN_FUNC + ("enable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", + i_ret); + } + } + } else if (flag == CLK_OUT_DISABLE) { + if (atomic_dec_return(&s_clk_ref) == 0) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = disable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); + if (i_ret) { + BTIF_WARN_FUNC + ("disable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", + i_ret); + } +#else + BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif_apdma) calling\n"); + clk_disable(clk_btif_apdma); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + } + } else { + i_ret = ERR_INVALID_PAR; + BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); + } + +#else + + if (status == flag) { + i_ret = 0; + BTIF_DBG_FUNC("dma clock already %s\n", + CLK_OUT_ENABLE == + status ? "enabled" : "disabled"); + } else { + if (flag == CLK_OUT_ENABLE) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = enable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); +#else + BTIF_DBG_FUNC("[CCF]enable clk_btif_apdma\n"); + i_ret = clk_enable(clk_btif_apdma); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + status = (i_ret == 0) ? flag : status; + if (i_ret) { + BTIF_WARN_FUNC + ("enable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", + i_ret); + } + } else if (flag == CLK_OUT_DISABLE) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = disable_clock(MTK_BTIF_APDMA_CLK_CG, DMA_USER_ID); + status = (i_ret == 0) ? flag : status; + if (i_ret) { + BTIF_WARN_FUNC + ("disable_clock for MTK_BTIF_APDMA_CLK_CG failed, ret:%d", + i_ret); + } +#else + BTIF_DBG_FUNC("[CCF] clk_disable_unprepare(clk_btif_apdma) calling\n"); + clk_disable(clk_btif_apdma); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + } else { + i_ret = ERR_INVALID_PAR; + BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); + } + } +#endif + +#else + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + +#else + + status = flag; +#endif + + i_ret = 0; +#endif + + spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + if (i_ret == 0) { + BTIF_DBG_FUNC("dma clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); + } else { + BTIF_ERR_FUNC("%s dma clock failed, ret(%d)\n", + flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); + } +#else + + if (i_ret == 0) { + BTIF_DBG_FUNC("dma clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); + } else { + BTIF_ERR_FUNC("%s dma clock failed, ret(%d)\n", + flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); + } +#endif +#if defined(CONFIG_MTK_CLKMGR) + BTIF_DBG_FUNC("DMA's clock is %s\n", (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) ? "off" : "on"); +#endif + return i_ret; +} + +int hal_btif_dma_hw_init(P_MTK_DMA_INFO_STR p_dma_info) +{ + int i_ret = 0; + unsigned int dat = 0; + unsigned long base = p_dma_info->base; + unsigned long addr_h = 0; + P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; + P_MTK_BTIF_DMA_VFIFO p_mtk_dma_vfifo = container_of(p_vfifo, + MTK_BTIF_DMA_VFIFO, + vfifo); + + if (p_dma_info->dir == DMA_DIR_RX) { + /*Rx DMA*/ + /*do hardware reset*/ + /* BTIF_SET_BIT(RX_DMA_RST(base), DMA_HARD_RST);*/ + /* BTIF_CLR_BIT(RX_DMA_RST(base), DMA_HARD_RST);*/ + BTIF_SET_BIT(RX_DMA_RST(base), DMA_WARM_RST); + do { + dat = BTIF_READ32(RX_DMA_EN(base)); + } while (0x01 & dat); + /*write vfifo base address to VFF_ADDR*/ + btif_reg_sync_writel(p_vfifo->phy_addr, RX_DMA_VFF_ADDR(base)); + if (enable_4G()) + hal_btif_rx_dma_vff_set_for_4g(); + else { + addr_h = p_vfifo->phy_addr >> 16; + addr_h = addr_h >> 16; + btif_reg_sync_writel(addr_h, RX_DMA_VFF_ADDR_H(base)); + } + /*write vfifo length to VFF_LEN*/ + btif_reg_sync_writel(p_vfifo->vfifo_size, RX_DMA_VFF_LEN(base)); + /*write wpt to VFF_WPT*/ + btif_reg_sync_writel(p_mtk_dma_vfifo->wpt, + RX_DMA_VFF_WPT(base)); + btif_reg_sync_writel(p_mtk_dma_vfifo->rpt, + RX_DMA_VFF_RPT(base)); + /*write vff_thre to VFF_THRESHOLD*/ + btif_reg_sync_writel(p_vfifo->thre, RX_DMA_VFF_THRE(base)); + /*clear Rx DMA's interrupt status*/ + BTIF_SET_BIT(RX_DMA_INT_FLAG(base), + RX_DMA_INT_DONE | RX_DMA_INT_THRE); + + /*enable Rx IER by default*/ + btif_rx_dma_ier_ctrl(p_dma_info, true); + } else { +/*Tx DMA*/ +/*do hardware reset*/ +/* BTIF_SET_BIT(TX_DMA_RST(base), DMA_HARD_RST);*/ +/* BTIF_CLR_BIT(TX_DMA_RST(base), DMA_HARD_RST);*/ + BTIF_SET_BIT(TX_DMA_RST(base), DMA_WARM_RST); + do { + dat = BTIF_READ32(TX_DMA_EN(base)); + } while (0x01 & dat); +/*write vfifo base address to VFF_ADDR*/ + btif_reg_sync_writel(p_vfifo->phy_addr, TX_DMA_VFF_ADDR(base)); + if (enable_4G()) + hal_btif_tx_dma_vff_set_for_4g(); + else { + addr_h = p_vfifo->phy_addr >> 16; + addr_h = addr_h >> 16; + btif_reg_sync_writel(addr_h, TX_DMA_VFF_ADDR_H(base)); + } +/*write vfifo length to VFF_LEN*/ + btif_reg_sync_writel(p_vfifo->vfifo_size, TX_DMA_VFF_LEN(base)); +/*write wpt to VFF_WPT*/ + btif_reg_sync_writel(p_mtk_dma_vfifo->wpt, + TX_DMA_VFF_WPT(base)); + btif_reg_sync_writel(p_mtk_dma_vfifo->rpt, + TX_DMA_VFF_RPT(base)); +/*write vff_thre to VFF_THRESHOLD*/ + btif_reg_sync_writel(p_vfifo->thre, TX_DMA_VFF_THRE(base)); + + BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), TX_DMA_INT_FLAG_MASK); + + hal_btif_dma_ier_ctrl(p_dma_info, false); + } + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_ctrl +* DESCRIPTION +* enable/disable Tx DMA channel +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* ctrl_id [IN] enable/disable ID +* RETURNS +* 0 means success; negative means fail +*****************************************************************************/ +int hal_btif_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) +{ + unsigned int i_ret = -1; + ENUM_DMA_DIR dir = p_dma_info->dir; + + if (dir == DMA_DIR_RX) + i_ret = btif_rx_dma_ctrl(p_dma_info, ctrl_id); + else if (dir == DMA_DIR_TX) + i_ret = btif_tx_dma_ctrl(p_dma_info, ctrl_id); + else { + /*TODO: print error log*/ + BTIF_ERR_FUNC("invalid dma ctrl id (%d)\n", ctrl_id); + i_ret = ERR_INVALID_PAR; + } + return i_ret; +} + +int hal_btif_dma_rx_cb_reg(P_MTK_DMA_INFO_STR p_dma_info, + dma_rx_buf_write rx_cb) +{ + if (p_dma_info->rx_cb != NULL) { + BTIF_DBG_FUNC + ("rx_cb already registered, replace (0x%p) with (0x%p)\n", + p_dma_info->rx_cb, rx_cb); + } + p_dma_info->rx_cb = rx_cb; + return 0; +} + +int btif_tx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int dat; + + BTIF_TRC_FUNC(); + if (ctrl_id == DMA_CTRL_DISABLE) { + /*if write 0 to EN bit, DMA will be stopped imediately*/ + /*if write 1 to STOP bit, DMA will be stopped after current transaction finished*/ + /*BTIF_CLR_BIT(TX_DMA_EN(base), DMA_EN_BIT);*/ + BTIF_SET_BIT(TX_DMA_STOP(base), DMA_STOP_BIT); + do { + dat = BTIF_READ32(TX_DMA_STOP(base)); + } while (0x1 & dat); + BTIF_DBG_FUNC("BTIF Tx DMA disabled,EN(0x%x),STOP(0x%x)\n", + BTIF_READ32(TX_DMA_EN(base)), BTIF_READ32(TX_DMA_STOP(base))); + i_ret = 0; + } else if (ctrl_id == DMA_CTRL_ENABLE) { + BTIF_SET_BIT(TX_DMA_EN(base), DMA_EN_BIT); + BTIF_DBG_FUNC("BTIF Tx DMA enabled\n"); + i_ret = 0; + } else { +/*TODO: print error log*/ + BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id); + i_ret = ERR_INVALID_PAR; + } + BTIF_TRC_FUNC(); + return i_ret; +} + +int btif_rx_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int dat; + + BTIF_TRC_FUNC(); + + if (ctrl_id == DMA_CTRL_DISABLE) { + /*if write 0 to EN bit, DMA will be stopped imediately*/ + /*if write 1 to STOP bit, DMA will be stopped after current transaction finished*/ + /*BTIF_CLR_BIT(RX_DMA_EN(base), DMA_EN_BIT);*/ + BTIF_SET_BIT(RX_DMA_STOP(base), DMA_STOP_BIT); + do { + dat = BTIF_READ32(RX_DMA_STOP(base)); + } while (0x1 & dat); + BTIF_DBG_FUNC("BTIF Rx DMA disabled,EN(0x%x),STOP(0x%x)\n", + BTIF_READ32(RX_DMA_EN(base)), BTIF_READ32(RX_DMA_STOP(base))); + i_ret = 0; + } else if (ctrl_id == DMA_CTRL_ENABLE) { + BTIF_SET_BIT(RX_DMA_EN(base), DMA_EN_BIT); + BTIF_DBG_FUNC("BTIF Rx DMA enabled\n"); + i_ret = 0; + } else { +/*TODO: print error log*/ + BTIF_ERR_FUNC("invalid DMA ctrl_id (%d)\n", ctrl_id); + i_ret = ERR_INVALID_PAR; + } + BTIF_TRC_FUNC(); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_tx_vfifo_reset +* DESCRIPTION +* reset tx virtual fifo information, except memory information +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_vfifo_reset(P_MTK_DMA_INFO_STR p_dma_info) +{ + unsigned int i_ret = -1; + P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; + P_MTK_BTIF_DMA_VFIFO p_mtk_dma_vfifo = container_of(p_vfifo, + MTK_BTIF_DMA_VFIFO, + vfifo); + + BTIF_TRC_FUNC(); + p_mtk_dma_vfifo->rpt = 0; + p_mtk_dma_vfifo->last_rpt_wrap = 0; + p_mtk_dma_vfifo->wpt = 0; + p_mtk_dma_vfifo->last_wpt_wrap = 0; + BTIF_TRC_FUNC(); + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_ier_ctrl +* DESCRIPTION +* BTIF Tx DMA's interrupt enable/disable +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* enable [IN] control if tx interrupt enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) +{ + unsigned int i_ret = -1; + ENUM_DMA_DIR dir = p_dma_info->dir; + + if (dir == DMA_DIR_RX) { + i_ret = btif_rx_dma_ier_ctrl(p_dma_info, en); + } else if (dir == DMA_DIR_TX) { + i_ret = btif_tx_dma_ier_ctrl(p_dma_info, en); + } else { +/*TODO: print error log*/ + BTIF_ERR_FUNC("invalid DMA dma dir (%d)\n", dir); + i_ret = ERR_INVALID_PAR; + } + + return i_ret; +} + +int btif_rx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + + BTIF_TRC_FUNC(); + if (!en) { + BTIF_CLR_BIT(RX_DMA_INT_EN(base), + (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN)); + } else { + BTIF_SET_BIT(RX_DMA_INT_EN(base), + (RX_DMA_INT_THRE_EN | RX_DMA_INT_DONE_EN)); + } + i_ret = 0; + BTIF_TRC_FUNC(); + + return i_ret; +} + +int btif_tx_dma_ier_ctrl(P_MTK_DMA_INFO_STR p_dma_info, bool en) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + + BTIF_TRC_FUNC(); + if (!en) + BTIF_CLR_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT); + else + BTIF_SET_BIT(TX_DMA_INT_EN(base), TX_DMA_INTEN_BIT); + i_ret = 0; + BTIF_TRC_FUNC(); + + return i_ret; +} + +static int is_tx_dma_irq_finish_done(P_MTK_DMA_INFO_STR p_dma_info) +{ + int tx_irq_done = 0; +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER +/*if we enable this clock reference couner, just return , because when enter IRQ handler, DMA's clock will be opened*/ + tx_irq_done = 1; +#else + unsigned long flag = 0; + unsigned long base = p_dma_info->base; + + spin_lock_irqsave(&(g_clk_cg_spinlock), flag); + tx_irq_done = ((BTIF_READ32(TX_DMA_INT_FLAG(base)) & TX_DMA_INT_FLAG_MASK) == 0) ? 1 : 0; + spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); +#endif + return tx_irq_done; +} + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_irq_handler +* DESCRIPTION +* lower level tx interrupt handler +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_tx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info) +{ +#define MAX_CONTINIOUS_TIMES 512 + unsigned int i_ret = -1; + unsigned int valid_size = 0; + unsigned int vff_len = 0; + unsigned int left_len = 0; + unsigned long base = p_dma_info->base; + static int flush_irq_counter; + static struct timeval start_timer; + static struct timeval end_timer; + unsigned long flag = 0; + + spin_lock_irqsave(&(g_clk_cg_spinlock), flag); + +#if defined(CONFIG_MTK_CLKMGR) + if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { + spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); + BTIF_ERR_FUNC + ("%s: clock is off before irq status clear done!!!\n", + __FILE__); + return i_ret; + } +#endif +/*check if Tx VFF Left Size equal to VFIFO size or not*/ + vff_len = BTIF_READ32(TX_DMA_VFF_LEN(base)); + valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); + left_len = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); + if (flush_irq_counter == 0) + do_gettimeofday(&start_timer); + if ((valid_size > 0) && (valid_size < 8)) { + i_ret = _tx_dma_flush(p_dma_info); + flush_irq_counter++; + if (flush_irq_counter >= MAX_CONTINIOUS_TIMES) { + do_gettimeofday(&end_timer); +/* + * when btif tx fifo cannot accept any data and counts of bytes left in tx vfifo < 8 for a while + * we assume that btif cannot send data for a long time + * in order not to generate interrupt continiously, which may effect system's performance. + * we clear tx flag and disable btif tx interrupt + */ +/*clear interrupt flag*/ + BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), + TX_DMA_INT_FLAG_MASK); +/*vFIFO data has been read by DMA controller, just disable tx dma's irq*/ + i_ret = hal_btif_dma_ier_ctrl(p_dma_info, false); + BTIF_ERR_FUNC + ("**********************ERROR, ERROR, ERROR**************************\n"); + BTIF_ERR_FUNC + ("BTIF Tx IRQ happened %d times (continiously), between %d.%d and %d.%d\n", + MAX_CONTINIOUS_TIMES, start_timer.tv_sec, + start_timer.tv_usec, end_timer.tv_usec, + end_timer.tv_usec); + } + } else if (vff_len == left_len) { + flush_irq_counter = 0; +/*clear interrupt flag*/ + BTIF_CLR_BIT(TX_DMA_INT_FLAG(base), TX_DMA_INT_FLAG_MASK); +/*vFIFO data has been read by DMA controller, just disable tx dma's irq*/ + i_ret = hal_btif_dma_ier_ctrl(p_dma_info, false); + } else { +#if 0 + BTIF_ERR_FUNC + ("**********************WARNING**************************\n"); + BTIF_ERR_FUNC("invalid irq condition, dump register\n"); + hal_dma_dump_reg(p_dma_info, REG_TX_DMA_ALL); +#endif + BTIF_DBG_FUNC + ("superious IRQ occurs, vff_len(%d), valid_size(%d), left_len(%d)\n", + vff_len, valid_size, left_len); + } + + spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_send_data +* DESCRIPTION +* send data through btif in DMA mode +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN] pointer to rx data buffer +* max_len [IN] tx buffer length +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_dma_send_data(P_MTK_DMA_INFO_STR p_dma_info, + const unsigned char *p_buf, const unsigned int buf_len) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; + unsigned int len_to_send = buf_len; + unsigned int ava_len = 0; + unsigned int wpt = 0; + unsigned int last_wpt_wrap = 0; + unsigned int vff_size = 0; + unsigned char *p_data = (unsigned char *)p_buf; + P_MTK_BTIF_DMA_VFIFO p_mtk_vfifo = container_of(p_vfifo, + MTK_BTIF_DMA_VFIFO, + vfifo); + + BTIF_TRC_FUNC(); + if ((p_buf == NULL) || (buf_len == 0)) { + i_ret = ERR_INVALID_PAR; + BTIF_ERR_FUNC("invalid parameters, p_buf:0x%p, buf_len:%d\n", + p_buf, buf_len); + return i_ret; + } +/*check if tx dma in flush operation? if yes, should wait until DMA finish flush operation*/ +/*currently uplayer logic will make sure this pre-condition*/ +/*disable Tx IER, in case Tx irq happens, flush bit may be set in irq handler*/ + btif_tx_dma_ier_ctrl(p_dma_info, false); + + vff_size = p_mtk_vfifo->vfifo.vfifo_size; + ava_len = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); + wpt = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_MASK; + last_wpt_wrap = BTIF_READ32(TX_DMA_VFF_WPT(base)) & DMA_WPT_WRAP; + +/* + * copy data to vFIFO, Note: ava_len should always large than buf_len, + * otherwise common logic layer will not call hal_dma_send_data + */ + if (buf_len > ava_len) { + BTIF_ERR_FUNC + ("length to send:(%d) < length available(%d), abnormal!!!---!!!\n", + buf_len, ava_len); + WARN_ON(buf_len > ava_len); /* this will cause kernel panic */ + } + + len_to_send = buf_len < ava_len ? buf_len : ava_len; + if (len_to_send + wpt >= vff_size) { + unsigned int tail_len = vff_size - wpt; + + memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt), p_data, tail_len); + p_data += tail_len; + memcpy(p_mtk_vfifo->vfifo.p_vir_addr, + p_data, len_to_send - tail_len); +/*make sure all data write to memory area tx vfifo locates*/ + mb(); + +/*calculate WPT*/ + wpt = wpt + len_to_send - vff_size; + last_wpt_wrap ^= DMA_WPT_WRAP; + } else { + memcpy((p_mtk_vfifo->vfifo.p_vir_addr + wpt), + p_data, len_to_send); +/*make sure all data write to memory area tx vfifo locates*/ + mb(); + +/*calculate WPT*/ + wpt += len_to_send; + } + p_mtk_vfifo->wpt = wpt; + p_mtk_vfifo->last_wpt_wrap = last_wpt_wrap; + +/*make sure tx dma is allowed(tx flush bit is not set) to use before update WPT*/ + if (hal_dma_is_tx_allow(p_dma_info)) { + /*make sure tx dma enabled*/ + hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); + + /*update WTP to Tx DMA controller's control register*/ + btif_reg_sync_writel(wpt | last_wpt_wrap, TX_DMA_VFF_WPT(base)); + + if ((BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)) < 8) && + (BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)) > 0)) { + /* + * 0 < valid size in Tx vFIFO < 8 && TX Flush is not in process? + * if yes, set flush bit to DMA + */ + _tx_dma_flush(p_dma_info); + } + i_ret = len_to_send; + } else { +/*TODO: print error log*/ + BTIF_ERR_FUNC("Tx DMA flush operation is in process, this case should never happen,", + "please check if tx operation is allowed before call this API\n"); +/*if flush operation is in process , we will return 0*/ + i_ret = 0; + } + +/*Enable Tx IER*/ + btif_tx_dma_ier_ctrl(p_dma_info, true); + + BTIF_TRC_FUNC(); + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_is_tx_complete +* DESCRIPTION +* get tx complete flag +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* true means tx complete, false means tx in process +*****************************************************************************/ +bool hal_dma_is_tx_complete(P_MTK_DMA_INFO_STR p_dma_info) +{ + bool b_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); + unsigned int inter_size = BTIF_READ32(TX_DMA_INT_BUF_SIZE(base)); + unsigned int tx_done = is_tx_dma_irq_finish_done(p_dma_info); + +/* + * only when virtual FIFO valid size and Tx channel internal buffer size are both becomes to be 0, + * we can identify tx operation finished + * confirmed with DE. + */ + if ((valid_size == 0) && (inter_size == 0) && (tx_done == 1)) { + b_ret = true; + BTIF_DBG_FUNC("DMA tx finished.\n"); + } else { + BTIF_DBG_FUNC + ("DMA tx is in process. vfifo valid size(%d), dma internal size (%d), tx_done(%d)\n", + valid_size, inter_size, tx_done); + b_ret = false; + } + + return b_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_get_ava_room +* DESCRIPTION +* get tx available room +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* available room size +*****************************************************************************/ +int hal_dma_get_ava_room(P_MTK_DMA_INFO_STR p_dma_info) +{ + int i_ret = -1; + unsigned long base = p_dma_info->base; + +/*read vFIFO's left size*/ + i_ret = BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base)); + BTIF_DBG_FUNC("DMA tx ava room (%d).\n", i_ret); + if (i_ret == 0) + BTIF_INFO_FUNC("DMA tx vfifo is full.\n"); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_is_tx_allow +* DESCRIPTION +* is tx operation allowed by DMA +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* true if tx operation is allowed; false if tx is not allowed +*****************************************************************************/ +bool hal_dma_is_tx_allow(P_MTK_DMA_INFO_STR p_dma_info) +{ +#define MIN_TX_MB ((26 * 1000000 / 13) / 1000000) +#define AVE_TX_MB ((26 * 1000000 / 8) / 1000000) + + bool b_ret = false; + unsigned int wait_us = 8 / MIN_TX_MB; /*only ava length */ +/*see if flush operation is in process*/ + b_ret = _is_tx_dma_in_flush(p_dma_info) ? false : true; + if (!b_ret) { + usleep_range(wait_us, 2 * wait_us); + b_ret = _is_tx_dma_in_flush(p_dma_info) ? false : true; + } + if (!b_ret) + BTIF_WARN_FUNC("btif tx dma is not allowed\n"); +/*after Tx flush operation finished, HW will set DMA_EN back to 0 and stop DMA*/ + return b_ret; +} + + +/***************************************************************************** +* FUNCTION +* hal_rx_dma_irq_handler +* DESCRIPTION +* lower level rx interrupt handler +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_rx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, const unsigned int max_len) +{ + int i_ret = -1; + unsigned int valid_len = 0; + unsigned int wpt_wrap = 0; + unsigned int rpt_wrap = 0; + unsigned int wpt = 0; + unsigned int rpt = 0; + unsigned int tail_len = 0; + unsigned int real_len = 0; + unsigned long base = p_dma_info->base; + P_DMA_VFIFO p_vfifo = p_dma_info->p_vfifo; + dma_rx_buf_write rx_cb = p_dma_info->rx_cb; + unsigned char *p_vff_buf = NULL; + unsigned char *vff_base = p_vfifo->p_vir_addr; + unsigned int vff_size = p_vfifo->vfifo_size; + P_MTK_BTIF_DMA_VFIFO p_mtk_vfifo = container_of(p_vfifo, + MTK_BTIF_DMA_VFIFO, + vfifo); + unsigned long flag = 0; + + spin_lock_irqsave(&(g_clk_cg_spinlock), flag); +#if defined(CONFIG_MTK_CLKMGR) + if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { + spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); + BTIF_ERR_FUNC("%s: clock is off before irq handle done!!!\n", + __FILE__); + return i_ret; + } +#endif +/*disable DMA Rx IER*/ + hal_btif_dma_ier_ctrl(p_dma_info, false); + +/*clear Rx DMA's interrupt status*/ + BTIF_SET_BIT(RX_DMA_INT_FLAG(base), RX_DMA_INT_DONE | RX_DMA_INT_THRE); + + valid_len = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); + rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); + wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); + if ((valid_len == 0) && (rpt == wpt)) { + BTIF_DBG_FUNC + ("rx interrupt, no data available in Rx DMA, wpt(0x%08x), rpt(0x%08x)\n", + rpt, wpt); + } + + i_ret = 0; + + while ((valid_len > 0) || (rpt != wpt)) { + rpt_wrap = rpt & DMA_RPT_WRAP; + wpt_wrap = wpt & DMA_WPT_WRAP; + rpt &= DMA_RPT_MASK; + wpt &= DMA_WPT_MASK; + +/*calcaute length of available data in vFIFO*/ + if (wpt_wrap != p_mtk_vfifo->last_wpt_wrap) + real_len = wpt + vff_size - rpt; + else + real_len = wpt - rpt; + + if (rx_cb != NULL) { + tail_len = vff_size - rpt; + p_vff_buf = vff_base + rpt; + if (tail_len >= real_len) { + (*rx_cb) (p_dma_info, p_vff_buf, real_len); + } else { + (*rx_cb) (p_dma_info, p_vff_buf, tail_len); + p_vff_buf = vff_base; + (*rx_cb) (p_dma_info, p_vff_buf, real_len - + tail_len); + } + i_ret += real_len; + } else + BTIF_ERR_FUNC("no rx_cb found, please check your init process\n"); + mb(); + rpt += real_len; + if (rpt >= vff_size) { + /*read wrap bit should be revert*/ + rpt_wrap ^= DMA_RPT_WRAP; + rpt %= vff_size; + } + rpt |= rpt_wrap; +/*record wpt, last_wpt_wrap, rpt, last_rpt_wrap*/ + p_mtk_vfifo->wpt = wpt; + p_mtk_vfifo->last_wpt_wrap = wpt_wrap; + + p_mtk_vfifo->rpt = rpt; + p_mtk_vfifo->last_rpt_wrap = rpt_wrap; + +/*update rpt information to DMA controller*/ + btif_reg_sync_writel(rpt, RX_DMA_VFF_RPT(base)); + +/*get vff valid size again and check if rx data is processed completely*/ + valid_len = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); + + rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); + wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); + } + +/*enable DMA Rx IER*/ + hal_btif_dma_ier_ctrl(p_dma_info, true); + + spin_unlock_irqrestore(&(g_clk_cg_spinlock), flag); + + return i_ret; +} + +static int hal_tx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_BTIF_REG_ID flag) +{ + int i_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int int_flag = 0; + unsigned int enable = 0; + unsigned int stop = 0; + unsigned int flush = 0; + unsigned int wpt = 0; + unsigned int rpt = 0; + unsigned int int_buf = 0; + unsigned int valid_size = 0; + /*unsigned long irq_flag = 0;*/ + +#if defined(CONFIG_MTK_CLKMGR) + /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ + if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", + __FILE__); + return i_ret; + } +#endif + int_flag = BTIF_READ32(TX_DMA_INT_FLAG(base)); + enable = BTIF_READ32(TX_DMA_EN(base)); + stop = BTIF_READ32(TX_DMA_STOP(base)); + flush = BTIF_READ32(TX_DMA_FLUSH(base)); + wpt = BTIF_READ32(TX_DMA_VFF_WPT(base)); + rpt = BTIF_READ32(TX_DMA_VFF_RPT(base)); + int_buf = BTIF_READ32(TX_DMA_INT_BUF_SIZE(base)); + valid_size = BTIF_READ32(TX_DMA_VFF_VALID_SIZE(base)); + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + + BTIF_INFO_FUNC("DMA's clock is on\n"); + BTIF_INFO_FUNC("Tx DMA's base address: 0x%lx\n", base); + + if (flag == REG_TX_DMA_ALL) { + BTIF_INFO_FUNC("TX_EN(:0x%x\n", enable); + BTIF_INFO_FUNC("INT_FLAG:0x%x\n", int_flag); + BTIF_INFO_FUNC("TX_STOP:0x%x\n", stop); + BTIF_INFO_FUNC("TX_FLUSH:0x%x\n", flush); + BTIF_INFO_FUNC("TX_WPT:0x%x\n", wpt); + BTIF_INFO_FUNC("TX_RPT:0x%x\n", rpt); + BTIF_INFO_FUNC("INT_BUF_SIZE:0x%x\n", int_buf); + BTIF_INFO_FUNC("VALID_SIZE:0x%x\n", valid_size); + BTIF_INFO_FUNC("INT_EN:0x%x\n", + BTIF_READ32(TX_DMA_INT_EN(base))); + BTIF_INFO_FUNC("TX_RST:0x%x\n", BTIF_READ32(TX_DMA_RST(base))); + BTIF_INFO_FUNC("VFF_ADDR:0x%x\n", + BTIF_READ32(TX_DMA_VFF_ADDR(base))); + BTIF_INFO_FUNC("VFF_LEN:0x%x\n", + BTIF_READ32(TX_DMA_VFF_LEN(base))); + BTIF_INFO_FUNC("TX_THRE:0x%x\n", + BTIF_READ32(TX_DMA_VFF_THRE(base))); + BTIF_INFO_FUNC("W_INT_BUF_SIZE:0x%x\n", + BTIF_READ32(TX_DMA_W_INT_BUF_SIZE(base))); + BTIF_INFO_FUNC("LEFT_SIZE:0x%x\n", + BTIF_READ32(TX_DMA_VFF_LEFT_SIZE(base))); + BTIF_INFO_FUNC("DBG_STATUS:0x%x\n", + BTIF_READ32(TX_DMA_DEBUG_STATUS(base))); + i_ret = 0; + } else { + BTIF_WARN_FUNC("unknown flag:%d\n", flag); + } + BTIF_INFO_FUNC("tx dma %s\n", (enable & DMA_EN_BIT) && + (!(stop && DMA_STOP_BIT)) ? "enabled" : "stopped"); + BTIF_INFO_FUNC("data in tx dma is %s sent by HW\n", + ((wpt == rpt) && + (int_buf == 0)) ? "completely" : "not completely"); + + return i_ret; +} + +static int hal_rx_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, + ENUM_BTIF_REG_ID flag) +{ + int i_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int int_flag = 0; + unsigned int enable = 0; + unsigned int stop = 0; + unsigned int flush = 0; + unsigned int wpt = 0; + unsigned int rpt = 0; + unsigned int int_buf = 0; + unsigned int valid_size = 0; + /*unsigned long irq_flag = 0;*/ +#if defined(CONFIG_MTK_CLKMGR) + /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ + if (clock_is_on(MTK_BTIF_APDMA_CLK_CG) == 0) { + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", + __FILE__); + return i_ret; + } +#endif + BTIF_INFO_FUNC("dump DMA status register\n"); + _btif_dma_dump_dbg_reg(); + + int_flag = BTIF_READ32(RX_DMA_INT_FLAG(base)); + enable = BTIF_READ32(RX_DMA_EN(base)); + stop = BTIF_READ32(RX_DMA_STOP(base)); + flush = BTIF_READ32(RX_DMA_FLUSH(base)); + wpt = BTIF_READ32(RX_DMA_VFF_WPT(base)); + rpt = BTIF_READ32(RX_DMA_VFF_RPT(base)); + int_buf = BTIF_READ32(RX_DMA_INT_BUF_SIZE(base)); + valid_size = BTIF_READ32(RX_DMA_VFF_VALID_SIZE(base)); + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + + BTIF_INFO_FUNC("DMA's clock is on\n"); + BTIF_INFO_FUNC("Rx DMA's base address: 0x%lx\n", base); + + if (flag == REG_RX_DMA_ALL) { + BTIF_INFO_FUNC("RX_EN(:0x%x\n", enable); + BTIF_INFO_FUNC("RX_STOP:0x%x\n", stop); + BTIF_INFO_FUNC("RX_FLUSH:0x%x\n", flush); + BTIF_INFO_FUNC("INT_FLAG:0x%x\n", int_flag); + BTIF_INFO_FUNC("RX_WPT:0x%x\n", wpt); + BTIF_INFO_FUNC("RX_RPT:0x%x\n", rpt); + BTIF_INFO_FUNC("INT_BUF_SIZE:0x%x\n", int_buf); + BTIF_INFO_FUNC("VALID_SIZE:0x%x\n", valid_size); + BTIF_INFO_FUNC("INT_EN:0x%x\n", + BTIF_READ32(RX_DMA_INT_EN(base))); + BTIF_INFO_FUNC("RX_RST:0x%x\n", BTIF_READ32(RX_DMA_RST(base))); + BTIF_INFO_FUNC("VFF_ADDR:0x%x\n", + BTIF_READ32(RX_DMA_VFF_ADDR(base))); + BTIF_INFO_FUNC("VFF_LEN:0x%x\n", + BTIF_READ32(RX_DMA_VFF_LEN(base))); + BTIF_INFO_FUNC("RX_THRE:0x%x\n", + BTIF_READ32(RX_DMA_VFF_THRE(base))); + BTIF_INFO_FUNC("RX_FLOW_CTRL_THRE:0x%x\n", + BTIF_READ32(RX_DMA_FLOW_CTRL_THRE(base))); + BTIF_INFO_FUNC("LEFT_SIZE:0x%x\n", + BTIF_READ32(RX_DMA_VFF_LEFT_SIZE(base))); + BTIF_INFO_FUNC("DBG_STATUS:0x%x\n", + BTIF_READ32(RX_DMA_DEBUG_STATUS(base))); + i_ret = 0; + } else { + BTIF_WARN_FUNC("unknown flag:%d\n", flag); + } + BTIF_INFO_FUNC("rx dma %s\n", (enable & DMA_EN_BIT) && + (!(stop && DMA_STOP_BIT)) ? "enabled" : "stopped"); + BTIF_INFO_FUNC("data in rx dma is %s by driver\n", + ((wpt == rpt) && + (int_buf == 0)) ? "received" : "not received"); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_dump_reg +* DESCRIPTION +* dump BTIF module's information when needed +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* flag [IN] register id flag +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ENUM_BTIF_REG_ID flag) +{ + unsigned int i_ret = -1; + + if (p_dma_info->dir == DMA_DIR_TX) + i_ret = hal_tx_dma_dump_reg(p_dma_info, flag); + else if (p_dma_info->dir == DMA_DIR_RX) + i_ret = hal_rx_dma_dump_reg(p_dma_info, flag); + else + BTIF_WARN_FUNC("unknown dir:%d\n", p_dma_info->dir); + + return i_ret; +} + +static int _tx_dma_flush(P_MTK_DMA_INFO_STR p_dma_info) +{ + unsigned int i_ret = -1; + unsigned long base = p_dma_info->base; + unsigned int stop = BTIF_READ32(TX_DMA_STOP(base)); + +/*in MTK DMA BTIF channel we cannot set STOP and FLUSH bit at the same time*/ + if ((stop && DMA_STOP_BIT) != 0) + BTIF_ERR_FUNC("BTIF's DMA in stop state, omit flush operation\n"); + else { + BTIF_DBG_FUNC("flush tx dma\n"); + BTIF_SET_BIT(TX_DMA_FLUSH(base), DMA_FLUSH_BIT); + i_ret = 0; + } + return i_ret; +} + +static int _is_tx_dma_in_flush(P_MTK_DMA_INFO_STR p_dma_info) +{ + bool b_ret = true; + unsigned long base = p_dma_info->base; + +/*see if flush operation is in process*/ + b_ret = ((DMA_FLUSH_BIT & BTIF_READ32(TX_DMA_FLUSH(base))) != 0) ? true : false; + + return b_ret; +} + +int hal_dma_pm_ops(P_MTK_DMA_INFO_STR p_dma_info, MTK_BTIF_PM_OPID opid) +{ + int i_ret = -1; + + BTIF_INFO_FUNC("op id: %d\n", opid); + switch (opid) { + case BTIF_PM_DPIDLE_EN: + i_ret = 0; + break; + case BTIF_PM_DPIDLE_DIS: + i_ret = 0; + break; + case BTIF_PM_SUSPEND: + i_ret = 0; + break; + case BTIF_PM_RESUME: + i_ret = 0; + break; + case BTIF_PM_RESTORE_NOIRQ:{ + unsigned int flag = 0; + P_MTK_BTIF_IRQ_STR p_irq = p_dma_info->p_irq; + +#ifdef CONFIG_OF + flag = p_irq->irq_flags; +#else + switch (p_irq->sens_type) { + case IRQ_SENS_EDGE: + if (p_irq->edge_type == IRQ_EDGE_FALL) + flag = IRQF_TRIGGER_FALLING; + else if (p_irq->edge_type == IRQ_EDGE_RAISE) + flag = IRQF_TRIGGER_RISING; + else if (p_irq->edge_type == IRQ_EDGE_BOTH) + flag = IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING; + else + flag = IRQF_TRIGGER_FALLING; /*make this as default type */ + break; + case IRQ_SENS_LVL: + if (p_irq->lvl_type == IRQ_LVL_LOW) + flag = IRQF_TRIGGER_LOW; + else if (p_irq->lvl_type == IRQ_LVL_HIGH) + flag = IRQF_TRIGGER_HIGH; + else + flag = IRQF_TRIGGER_LOW; /*make this as default type */ + break; + default: + flag = IRQF_TRIGGER_LOW; /*make this as default type */ + break; + } +#endif +/* irq_set_irq_type(p_irq->irq_id, flag); */ + i_ret = 0; + } + i_ret = 0; + break; + default: + i_ret = ERR_INVALID_PAR; + break; + } + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_dma_receive_data +* DESCRIPTION +* receive data from btif module in DMA polling mode +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* positive means data is available, 0 means no data available +*****************************************************************************/ +#ifndef MTK_BTIF_MARK_UNUSED_API +int hal_dma_receive_data(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, const unsigned int max_len) +{ + unsigned int i_ret = -1; + + return i_ret; +} +#endif + +int _btif_dma_dump_dbg_reg(void) +{ +#if 0 + static MTK_BTIF_DMA_REG_DMP_DBG g_dma_dbg_regs[] = { + {0x10201180, 0x0}, + {0x10201184, 0x0}, + {0x10201188, 0x0}, + {0x1020118C, 0x0}, + {0x10201190, 0x0}, + {0x1000320C, 0x0}, + {0x10003210, 0x0}, + {0x10003214, 0x0}, + }; + + int i = 0; + char *addr1 = NULL; + char *addr2 = NULL; + + int array_num = ARRAY_SIZE(g_dma_dbg_regs) + + addr1 = ioremap(g_dma_dbg_regs[0].reg_addr, 0x20); + if (addr1) { + for (i = 0; i < 5; i++) + g_dma_dbg_regs[i].reg_val = *(volatile unsigned int*)(addr1 + i*4); + iounmap(addr1); + } + + addr2 = ioremap(g_dma_dbg_regs[5].reg_addr, 0x10); + if (addr2) { + g_dma_dbg_regs[5].reg_val = *(volatile unsigned int*)(addr2); + g_dma_dbg_regs[6].reg_val = *(volatile unsigned int*)(addr2+4); + g_dma_dbg_regs[7].reg_val = *(volatile unsigned int*)(addr2+8); + iounmap(addr2); + } + + for (i = 0; i < array_num; i++) + BTIF_INFO_FUNC("-<0x%lx, 0x%08x>\n", g_dma_dbg_regs[i].reg_addr, g_dma_dbg_regs[i].reg_val); +#endif + return 0; +} + +static void hal_btif_tx_dma_vff_set_for_4g(void) +{ + BTIF_DBG_FUNC("Set btif tx_vff_addr bit29\n"); + BTIF_SET_BIT(TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base), DMA_VFF_BIT29_OFFSET); + BTIF_DBG_FUNC("Dump value of bit29 0x%x:(0x%x)\n", TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base), + BTIF_READ32(TX_DMA_VFF_ADDR_H(mtk_btif_tx_dma.base))); +} +static void hal_btif_rx_dma_vff_set_for_4g(void) +{ + BTIF_DBG_FUNC("Set btif rx_vff_addr bit29\n"); + BTIF_SET_BIT(RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base), DMA_VFF_BIT29_OFFSET); + BTIF_DBG_FUNC("Dump value of bit29 0x%x:(0x%x)\n", RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base), + BTIF_READ32(RX_DMA_VFF_ADDR_H(mtk_btif_rx_dma.base))); +} + diff --git a/drivers/misc/mediatek/btif/common/btif_plat.c b/drivers/misc/mediatek/btif/common/btif_plat.c new file mode 100644 index 0000000000000..baf2a0b6d0c89 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/btif_plat.c @@ -0,0 +1,1396 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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. + */ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "MTK-BTIF" + +#define NEW_TX_HANDLING_SUPPORT 1 + +#include "btif_pub.h" +#include "btif_priv.h" + +#define BTIF_USER_ID "btif_driver" + +static spinlock_t g_clk_cg_spinlock; /*BTIF clock's spinlock */ + +/*-----------------------------BTIF Module Clock and Power Control Defination------------------*/ + +MTK_BTIF_IRQ_STR mtk_btif_irq = { + .name = "mtk btif irq", + .is_irq_sup = true, + .reg_flag = false, +#ifdef CONFIG_OF + .irq_flags = IRQF_TRIGGER_NONE, +#else + .irq_id = MT_BTIF_IRQ_ID, + .sens_type = IRQ_SENS_LVL, + .lvl_type = IRQ_LVL_LOW, +#endif + .p_irq_handler = NULL, +}; + +/* + * will call clock manager's API export by WCP to control BTIF's clock, + * but we may need to access these registers in case of btif clock control logic is wrong in clock manager + */ + +MTK_BTIF_INFO_STR mtk_btif = { +#ifndef CONFIG_OF + .base = MTK_BTIF_REG_BASE, +#endif + .p_irq = &mtk_btif_irq, + .tx_fifo_size = BTIF_TX_FIFO_SIZE, + .rx_fifo_size = BTIF_RX_FIFO_SIZE, + .tx_tri_lvl = BTIF_TX_FIFO_THRE, + .rx_tri_lvl = BTIF_RX_FIFO_THRE, + .rx_data_len = 0, + .p_tx_fifo = NULL, +}; +#if !(NEW_TX_HANDLING_SUPPORT) +static bool _btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif); +#endif + +static int btif_rx_irq_handler(P_MTK_BTIF_INFO_STR p_btif_info, + unsigned char *p_buf, + const unsigned int max_len); +static int btif_tx_irq_handler(P_MTK_BTIF_INFO_STR p_btif); + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_ier_ctrl +* DESCRIPTION +* BTIF Rx interrupt enable/disable +* PARAMETERS +* p_base [IN] BTIF module's base address +* enable [IN] control if rx interrupt enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int hal_btif_rx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); + +/***************************************************************************** +* FUNCTION +* hal_btif_tx_ier_ctrl +* DESCRIPTION +* BTIF Tx interrupt enable/disable +* PARAMETERS +* p_base [IN] BTIF module's base address +* enable [IN] control if tx interrupt enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int hal_btif_tx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); + +#ifndef MTK_BTIF_MARK_UNUSED_API +static int btif_sleep_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); + +/***************************************************************************** +* FUNCTION +* _btif_receive_data +* DESCRIPTION +* receive data from btif module in FIFO polling mode +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* positive means data is available, 0 means no data available +*****************************************************************************/ +static int _btif_receive_data(P_MTK_BTIF_INFO_STR p_btif, + unsigned char *p_buf, const unsigned int max_len); +static int btif_tx_thr_set(P_MTK_BTIF_INFO_STR p_btif, unsigned int thr_count); +#endif + +static int btif_dump_array(char *string, char *p_buf, int len) +{ + unsigned int idx = 0; + unsigned char str[30]; + unsigned char *p_str; + + pr_debug("========dump %s start ========\n", string, len); + p_str = &str[0]; + for (idx = 0; idx < len; idx++, p_buf++) { + sprintf(p_str, "%02x ", *p_buf); + p_str += 3; + if (7 == (idx % 8)) { + *p_str++ = '\n'; + *p_str = '\0'; + pr_debug("%s", str); + p_str = &str[0]; + } + } + if (len % 8) { + *p_str++ = '\n'; + *p_str = '\0'; + pr_debug("%s", str); + } + pr_debug("========dump %s end========\n", string); + return 0; +} + +#if NEW_TX_HANDLING_SUPPORT +static int _btif_tx_fifo_init(P_MTK_BTIF_INFO_STR p_btif_info) +{ + int i_ret = -1; + + spin_lock_init(&(p_btif_info->tx_fifo_spinlock)); + + if (p_btif_info->p_tx_fifo == NULL) { + p_btif_info->p_tx_fifo = kzalloc(sizeof(struct kfifo), + GFP_ATOMIC); + if (p_btif_info->p_tx_fifo == NULL) { + i_ret = -ENOMEM; + BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n"); + goto ret; + } + + i_ret = kfifo_alloc(p_btif_info->p_tx_fifo, + BTIF_HAL_TX_FIFO_SIZE, GFP_ATOMIC); + if (i_ret != 0) { + BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret); + i_ret = -ENOMEM; + goto ret; + } + i_ret = 0; + } else { + BTIF_WARN_FUNC + ("p_btif_info->p_tx_fifo is already init p_btif_info->p_tx_fifo(0x%p)\n", + p_btif_info->p_tx_fifo); + i_ret = 0; + } +ret: + return i_ret; +} + +static int _get_btif_tx_fifo_room(P_MTK_BTIF_INFO_STR p_btif_info) +{ + int i_ret = 0; + unsigned long flag = 0; + + spin_lock_irqsave(&(p_btif_info->tx_fifo_spinlock), flag); + if (p_btif_info->p_tx_fifo == NULL) + i_ret = 0; + else + i_ret = kfifo_avail(p_btif_info->p_tx_fifo); + spin_unlock_irqrestore(&(p_btif_info->tx_fifo_spinlock), flag); + BTIF_DBG_FUNC("tx kfifo:0x%p, available room:%d\n", p_btif_info->p_tx_fifo, i_ret); + return i_ret; +} + +static int _btif_tx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif_info) +{ + int i_ret = 0; + + if (p_btif_info->p_tx_fifo != NULL) + kfifo_reset(p_btif_info->p_tx_fifo); + return i_ret; +} + +#endif + +#ifdef CONFIG_OF +static void _btif_set_default_setting(void) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = {0, 0, 0}; + unsigned int phy_base; + + node = of_find_compatible_node(NULL, NULL, "mediatek,btif"); + if (node) { + mtk_btif.p_irq->irq_id = irq_of_parse_and_map(node, 0); + /*fixme, be compitable arch 64bits*/ + mtk_btif.base = (unsigned long)of_iomap(node, 0); + BTIF_INFO_FUNC("get btif irq(%d),register base(0x%lx)\n", + mtk_btif.p_irq->irq_id, mtk_btif.base); + } else { + BTIF_ERR_FUNC("get btif device node fail\n"); + } + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + BTIF_ERR_FUNC("get interrupt flag from DTS fail\n"); + } else { + mtk_btif.p_irq->irq_flags = irq_info[2]; + BTIF_INFO_FUNC("get interrupt flag(0x%x)\n", mtk_btif.p_irq->irq_flags); + } + + if (of_property_read_u32_index(node, "reg", 1, &phy_base)) + BTIF_ERR_FUNC("get register phy base from DTS fail\n"); + else + BTIF_INFO_FUNC("get register phy base(0x%x)\n", (unsigned int)phy_base); +} +#endif + +/***************************************************************************** +* FUNCTION +* hal_btif_info_get +* DESCRIPTION +* get btif's information included base address , irq related information +* PARAMETERS +* RETURNS +* BTIF's information +*****************************************************************************/ +P_MTK_BTIF_INFO_STR hal_btif_info_get(void) +{ +#if NEW_TX_HANDLING_SUPPORT + int i_ret = 0; +/*tx fifo and fifo lock init*/ + i_ret = _btif_tx_fifo_init(&mtk_btif); + if (i_ret == 0) + BTIF_INFO_FUNC("_btif_tx_fifo_init succeed\n"); + else + BTIF_ERR_FUNC("_btif_tx_fifo_init failed, i_ret:%d\n", i_ret); + +#endif + +#ifdef CONFIG_OF + _btif_set_default_setting(); +#endif + + spin_lock_init(&g_clk_cg_spinlock); + + return &mtk_btif; +} +/***************************************************************************** +* FUNCTION +* hal_btif_clk_get_and_prepare +* DESCRIPTION +* get clock from device tree and prepare for enable/disable control +* PARAMETERS +* pdev device pointer +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +#if !defined(CONFIG_MTK_CLKMGR) +int hal_btif_clk_get_and_prepare(struct platform_device *pdev) +{ + int i_ret = -1; + + clk_btif = devm_clk_get(&pdev->dev, "btifc"); + if (IS_ERR(clk_btif)) { + BTIF_ERR_FUNC("[CCF]cannot get clk_btif clock.\n"); + return PTR_ERR(clk_btif); + } + BTIF_ERR_FUNC("[CCF]clk_btif=%p\n", clk_btif); + clk_btif_apdma = devm_clk_get(&pdev->dev, "apdmac"); + if (IS_ERR(clk_btif_apdma)) { + BTIF_ERR_FUNC("[CCF]cannot get clk_btif_apdma clock.\n"); + return PTR_ERR(clk_btif_apdma); + } + BTIF_ERR_FUNC("[CCF]clk_btif_apdma=%p\n", clk_btif_apdma); + + i_ret = clk_prepare(clk_btif); + if (i_ret != 0) { + BTIF_ERR_FUNC("clk_prepare clk_btif failed! ret:%d\n", i_ret); + return i_ret; + } + + i_ret = clk_prepare(clk_btif_apdma); + if (i_ret != 0) { + BTIF_ERR_FUNC("clk_prepare clk_btif_apdma failed! ret:%d\n", i_ret); + return i_ret; + } + return i_ret; +} +/***************************************************************************** +* FUNCTION +* hal_btif_clk_unprepare +* DESCRIPTION +* unprepare btif clock and apdma clock +* PARAMETERS +* none +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_clk_unprepare(void) +{ + clk_unprepare(clk_btif); + clk_unprepare(clk_btif_apdma); + return 0; +} +#endif +/***************************************************************************** +* FUNCTION +* hal_btif_clk_ctrl +* DESCRIPTION +* control clock output enable/disable of BTIF module +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_clk_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_CLOCK_CTRL flag) +{ +/*In MTK BTIF, there's only one global CG on AP_DMA, no sub channel's CG bit*/ +/*according to Artis's comment, clock of DMA and BTIF is default off, so we assume it to be off by default*/ + int i_ret = 0; + unsigned long irq_flag = 0; + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + static atomic_t s_clk_ref = ATOMIC_INIT(0); +#else + static ENUM_CLOCK_CTRL status = CLK_OUT_DISABLE; +#endif + + spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); + +#if MTK_BTIF_ENABLE_CLK_CTL + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + + if (flag == CLK_OUT_ENABLE) { + if (atomic_inc_return(&s_clk_ref) == 1) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); +#else + BTIF_DBG_FUNC("[CCF]enable clk_btif\n"); + i_ret = clk_enable(clk_btif); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + if (i_ret) { + BTIF_WARN_FUNC + ("enable_clock for MTK_BTIF_CG_BIT failed, ret:%d", + i_ret); + } + } + } else if (flag == CLK_OUT_DISABLE) { + if (atomic_dec_return(&s_clk_ref) == 0) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); + if (i_ret) { + BTIF_WARN_FUNC + ("disable_clock for MTK_BTIF_CG_BIT failed, ret:%d", + i_ret); + } +#else + BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n"); + clk_disable(clk_btif); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + } + } else { + i_ret = ERR_INVALID_PAR; + BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); + } + +#else + + if (status == flag) { + i_ret = 0; + BTIF_DBG_FUNC("btif clock already %s\n", + CLK_OUT_ENABLE == + status ? "enabled" : "disabled"); + } else { + if (flag == CLK_OUT_ENABLE) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = enable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); +#else + BTIF_DBG_FUNC("[CCF]enable clk_btif\n"); + i_ret = clk_enable(clk_btif); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + status = (i_ret == 0) ? flag : status; + if (i_ret) { + BTIF_WARN_FUNC + ("enable_clock for MTK_BTIF_CG_BIT failed, ret:%d", + i_ret); + } + } else if (flag == CLK_OUT_DISABLE) { +#if defined(CONFIG_MTK_CLKMGR) + i_ret = disable_clock(MTK_BTIF_CG_BIT, BTIF_USER_ID); + status = (i_ret == 0) ? flag : status; + if (i_ret) { + BTIF_WARN_FUNC + ("disable_clock for MTK_BTIF_CG_BIT failed, ret:%d", + i_ret); + } +#else + BTIF_DBG_FUNC("[CCF] clk_disable(clk_btif) calling\n"); + clk_disable(clk_btif); +#endif /* defined(CONFIG_MTK_CLKMGR) */ + } else { + i_ret = ERR_INVALID_PAR; + BTIF_ERR_FUNC("invalid clock ctrl flag (%d)\n", flag); + } + } +#endif + +#else + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + +#else + + status = flag; +#endif + + i_ret = 0; +#endif + + spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + if (i_ret == 0) { + BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); + } else { + BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n", + flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); + } +#else + + if (i_ret == 0) { + BTIF_DBG_FUNC("btif clock %s\n", flag == CLK_OUT_ENABLE ? "enabled" : "disabled"); + } else { + BTIF_ERR_FUNC("%s btif clock failed, ret(%d)\n", + flag == CLK_OUT_ENABLE ? "enable" : "disable", i_ret); + } +#endif +#if defined(CONFIG_MTK_CLKMGR) + BTIF_DBG_FUNC("BTIF's clock is %s\n", (clock_is_on(MTK_BTIF_CG_BIT) == 0) ? "off" : "on"); +#endif + return i_ret; +} + +static int btif_new_handshake_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool enable) +{ + unsigned long base = p_btif->base; + + if (enable == true) + BTIF_SET_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE); + else + BTIF_CLR_BIT(BTIF_HANDSHAKE(base), BTIF_HANDSHAKE_EN_HANDSHAKE); + return true; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_hw_init +* DESCRIPTION +* BTIF hardware init +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_hw_init(P_MTK_BTIF_INFO_STR p_btif) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + unsigned long base = p_btif->base; + +#if NEW_TX_HANDLING_SUPPORT + _btif_tx_fifo_reset(p_btif); +#endif + +/*set to normal mode*/ + btif_reg_sync_writel(BTIF_FAKELCR_NORMAL_MODE, BTIF_FAKELCR(base)); +/*set to newhandshake mode*/ + btif_new_handshake_ctrl(p_btif, true); +/*No need to access: enable sleep mode*/ +/*No need to access: set Rx timeout count*/ +/*set Tx threshold*/ +/*set Rx threshold*/ +/*disable internal loopback test*/ + +/*set Rx FIFO clear bit to 1*/ + BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); +/*clear Rx FIFO clear bit to 0*/ + BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); +/*set Tx FIFO clear bit to 1*/ + BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); +/*clear Tx FIFO clear bit to 0*/ + BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); + + btif_reg_sync_writel(BTIF_TRI_LVL_TX(p_btif->tx_tri_lvl) + | BTIF_TRI_LVL_RX(p_btif->rx_tri_lvl) + | BTIF_TRI_LOOP_DIS, BTIF_TRI_LVL(base)); + hal_btif_loopback_ctrl(p_btif, false); +/*disable BTIF Tx DMA mode*/ + hal_btif_tx_mode_ctrl(p_btif, false); +/*disable BTIF Rx DMA mode*/ + hal_btif_rx_mode_ctrl(p_btif, false); +/*auto reset*/ + BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_AUTORST_EN); +/*disable Tx IER*/ + hal_btif_tx_ier_ctrl(p_btif, false); +/*enable Rx IER by default*/ + hal_btif_rx_ier_ctrl(p_btif, true); + + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_ier_ctrl +* DESCRIPTION +* BTIF Rx interrupt enable/disable +* PARAMETERS +* p_base [IN] BTIF module's base address +* enable [IN] control if rx interrupt enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_rx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (en == false) + BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_RXFEN); + else + BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_RXFEN); + +/*TODO:do we need to read back ? Answer: no*/ + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_tx_ier_ctrl +* DESCRIPTION +* BTIF Tx interrupt enable/disable +* PARAMETERS +* p_base [IN] BTIF module's base address +* enable [IN] control if tx interrupt enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_tx_ier_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (en == false) + BTIF_CLR_BIT(BTIF_IER(base), BTIF_IER_TXEEN); + else + BTIF_SET_BIT(BTIF_IER(base), BTIF_IER_TXEEN); + +/*TODO:do we need to read back ? Answer: no*/ + i_ret = 0; + + return i_ret; +} + +#ifndef MTK_BTIF_MARK_UNUSED_API + +/***************************************************************************** +* FUNCTION +* _btif_receive_data +* DESCRIPTION +* receive data from btif module in FIFO polling mode +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* positive means data is available, 0 means no data available +*****************************************************************************/ +int _btif_receive_data(P_MTK_BTIF_INFO_STR p_btif, + unsigned char *p_buf, const unsigned int max_len) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + +/*check parameter valid or not*/ + if ((p_buf == NULL) || (max_len == 0)) { + i_ret = ERR_INVALID_PAR; + return i_ret; + } + i_ret = btif_rx_irq_handler(p_btif, p_buf, max_len); + + return i_ret; +} + +int btif_sleep_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (en == false) + BTIF_CLR_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT); + else + BTIF_SET_BIT(BTIF_SLEEP_EN(base), BTIF_SLEEP_EN_BIT); + +/*TODO:do we need to read back ? Answer: no*/ +/*TODO:do we need to dsb?*/ + i_ret = 0; + return i_ret; +} + +static int btif_tx_thr_set(P_MTK_BTIF_INFO_STR p_btif, unsigned int thr_count) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + unsigned int value = 0; + +/*read BTIF_TRI_LVL*/ + value = BTIF_READ32(BTIF_TRI_LVL(base)); +/*clear Tx threshold bits*/ + value &= (~BTIF_TRI_LVL_TX_MASK); +/*set tx threshold bits*/ + value |= BTIF_TRI_LVL_TX(BTIF_TX_FIFO_THRE); +/*write back to BTIF_TRI_LVL*/ + btif_reg_sync_writel(value, BTIF_TRI_LVL(base)); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* btif_rx_fifo_reset +* DESCRIPTION +* reset BTIF's rx fifo +* PARAMETERS +* p_base [IN] BTIF module's base address +* ec [IN] control if loopback mode is enabled or not +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int btif_rx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + unsigned long base = p_btif->base; + +/*set Rx FIFO clear bit to 1*/ + BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); + +/*clear Rx FIFO clear bit to 0*/ + BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_RX); + +/*TODO:do we need to read back ? Answer: no*/ +/*TODO:do we need to dsb?*/ + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* btif_tx_fifo_reset +* DESCRIPTION +* reset BTIF's tx fifo +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int btif_tx_fifo_reset(P_MTK_BTIF_INFO_STR p_btif) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + +/*set Tx FIFO clear bit to 1*/ + BTIF_SET_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); + +/*clear Tx FIFO clear bit to 0*/ + BTIF_CLR_BIT(BTIF_FIFOCTRL(base), BTIF_FIFOCTRL_CLR_TX); + +/*TODO:do we need to read back ? Answer: no*/ +/*TODO:do we need to dsb?*/ + i_ret = 0; + return i_ret; +} + +#endif + +/***************************************************************************** +* FUNCTION +* hal_btif_loopback_ctrl +* DESCRIPTION +* BTIF Tx/Rx loopback mode set, this operation can only be done after set BTIF to normal mode +* PARAMETERS +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_loopback_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (en == false) + BTIF_CLR_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN); + else + BTIF_SET_BIT(BTIF_TRI_LVL(base), BTIF_TRI_LOOP_EN); + +/*TODO:do we need to read back ? Answer: no*/ +/*TODO:do we need to dsb?*/ + i_ret = 0; + return i_ret; +} + + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_handler +* DESCRIPTION +* lower level interrupt handler +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* 0 means success; negative means fail; positive means rx data length +*****************************************************************************/ +int hal_btif_irq_handler(P_MTK_BTIF_INFO_STR p_btif, + unsigned char *p_buf, const unsigned int max_len) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + unsigned int iir = 0; + unsigned int rx_len = 0; + unsigned long base = p_btif->base; + +#if 0 +/*check parameter valid or not*/ + if ((p_buf == NULL) || (max_len == 0)) { + i_ret = ERR_INVALID_PAR; + return i_ret; + } +#endif + unsigned long irq_flag = 0; + + spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag); + +#if defined(CONFIG_MTK_CLKMGR) + if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { + spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); + BTIF_ERR_FUNC("%s: clock is off before irq handle done!!!\n", + __FILE__); + return i_ret; + } +#endif +/*read interrupt identifier register*/ + iir = BTIF_READ32(BTIF_IIR(base)); + +/*is rx interrupt exist?*/ +#if 0 + while ((iir & BTIF_IIR_RX) && (rx_len < max_len)) { + rx_len += + btif_rx_irq_handler(p_btif, (p_buf + rx_len), + (max_len - rx_len)); + +/*update IIR*/ + iir = BTIF_READ32(BTIF_IIR(base)); + } +#endif + + while (iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) { + rx_len += btif_rx_irq_handler(p_btif, p_buf, max_len); + +/*update IIR*/ + iir = BTIF_READ32(BTIF_IIR(base)); + } + +/*is tx interrupt exist?*/ + if (iir & BTIF_IIR_TX_EMPTY) + i_ret = btif_tx_irq_handler(p_btif); + spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag); + + i_ret = rx_len != 0 ? rx_len : i_ret; + return i_ret; +} + +int hal_btif_rx_cb_reg(P_MTK_BTIF_INFO_STR p_btif_info, btif_rx_buf_write rx_cb) +{ + if (p_btif_info->rx_cb != NULL) + BTIF_DBG_FUNC("rx_cb already registered, replace (0x%p) with (0x%p)\n", + p_btif_info->rx_cb, rx_cb); + p_btif_info->rx_cb = rx_cb; + + return 0; +} + +/***************************************************************************** +* FUNCTION +* btif_rx_irq_handler +* DESCRIPTION +* lower level rx interrupt handler +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* positive means length of rx data , negative means fail +*****************************************************************************/ +static int btif_rx_irq_handler(P_MTK_BTIF_INFO_STR p_btif_info, + unsigned char *p_buf, const unsigned int max_len) +{ +/*Chaozhong: To be implement*/ + int i_ret = 0; + unsigned int iir = 0; + unsigned int rx_len = 0; + unsigned long base = p_btif_info->base; + unsigned char rx_buf[256]; + unsigned int local_buf_len = 256; + btif_rx_buf_write rx_cb = p_btif_info->rx_cb; + unsigned int total_len = 0; + +/*read interrupt identifier register*/ + iir = BTIF_READ32(BTIF_IIR(base)); + while ((iir & (BTIF_IIR_RX | BTIF_IIR_RX_TIMEOUT)) && + (rx_len < local_buf_len)) { + rx_buf[rx_len] = BTIF_READ8(base); + rx_len++; +/*need to consult CC Hwang for advice */ +/* + * whether we need to do memory barrier here + * Ans: no + */ +/* + * whether we need to d memory barrier when call BTIF_SET_BIT or BTIF_CLR_BIT + * Ans: no + */ + if (rx_len == local_buf_len) { + if (rx_cb) + (*rx_cb) (p_btif_info, rx_buf, rx_len); + rx_len = 0; + total_len += rx_len; + } + iir = BTIF_READ32(BTIF_IIR(base)); + } + total_len += rx_len; + if (rx_len && rx_cb) + (*rx_cb) (p_btif_info, rx_buf, rx_len); + +/* + * make sure all data write back to memory, mb or dsb? + * need to consult CC Hwang for advice + * Ans: no need here + */ + i_ret = total_len; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* btif_tx_irq_handler +* DESCRIPTION +* lower level tx interrupt handler +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +static int btif_tx_irq_handler(P_MTK_BTIF_INFO_STR p_btif) +{ + int i_ret = -1; + +#if NEW_TX_HANDLING_SUPPORT + int how_many = 0; + unsigned int lsr; + unsigned int ava_len = 0; + unsigned long base = p_btif->base; + char local_buf[BTIF_TX_FIFO_SIZE]; + char *p_data = local_buf; + unsigned long flag = 0; + + struct kfifo *p_tx_fifo = p_btif->p_tx_fifo; + +/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ + lsr = BTIF_READ32(BTIF_LSR(base)); + + if (lsr & BTIF_LSR_TEMT_BIT) + /*Tx Holding Register if empty, which means we can write tx FIFO count to BTIF*/ + ava_len = BTIF_TX_FIFO_SIZE; + else if (lsr & BTIF_LSR_THRE_BIT) + /*Tx Holding Register if empty, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/ + ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE; + else { + /*this means data size in tx FIFO is more than Tx threshold, we will not write data to THR*/ + ava_len = 0; + goto ret; + } + spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); + how_many = kfifo_out(p_tx_fifo, local_buf, ava_len); + spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); + BTIF_DBG_FUNC("BTIF tx size %d done, left:%d\n", how_many, + kfifo_avail(p_tx_fifo)); + while (how_many--) + btif_reg_sync_writeb(*(p_data++), BTIF_THR(base)); + + spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); +/*clear Tx enable flag if necessary*/ + if (kfifo_is_empty(p_tx_fifo)) { + hal_btif_tx_ier_ctrl(p_btif, false); + BTIF_DBG_FUNC("BTIF tx FIFO is empty\n"); + } + spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); +ret: +#else +/*clear Tx enable flag*/ + hal_btif_tx_ier_ctrl(p_btif, false); +#endif + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_tx_mode_ctrl +* DESCRIPTION +* set BTIF tx to corresponding mode (PIO/DMA) +* PARAMETERS +* p_base [IN] BTIF module's base address +* mode [IN] rx mode +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_tx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (mode == BTIF_MODE_DMA) + /*set to DMA mode*/ + BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX); + else + /*set to PIO mode*/ + BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_TX); + + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_mode_ctrl +* DESCRIPTION +* set BTIF rx to corresponding mode (PIO/DMA) +* PARAMETERS +* p_base [IN] BTIF module's base address +* mode [IN] rx mode +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_rx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode) +{ + int i_ret = -1; + unsigned long base = p_btif->base; + + if (mode == BTIF_MODE_DMA) + /*set to DMA mode*/ + BTIF_SET_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX); + else + /*set to PIO mode*/ + BTIF_CLR_BIT(BTIF_DMA_EN(base), BTIF_DMA_EN_RX); + + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_send_data +* DESCRIPTION +* send data through btif in FIFO mode +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN] pointer to rx data buffer +* max_len [IN] tx buffer length +* RETURNS +* positive means number of data sent; 0 means no data put to FIFO; negative means error happens +*****************************************************************************/ +int hal_btif_send_data(P_MTK_BTIF_INFO_STR p_btif, + const unsigned char *p_buf, const unsigned int buf_len) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + + unsigned int ava_len = 0; + unsigned int sent_len = 0; + +#if !(NEW_TX_HANDLING_SUPPORT) + unsigned long base = p_btif->base; + unsigned int lsr = 0; + unsigned int left_len = 0; + unsigned char *p_data = (unsigned char *)p_buf; +#endif + +/*check parameter valid or not*/ + if ((p_buf == NULL) || (buf_len == 0)) { + i_ret = ERR_INVALID_PAR; + return i_ret; + } +#if NEW_TX_HANDLING_SUPPORT + ava_len = _get_btif_tx_fifo_room(p_btif); + sent_len = buf_len <= ava_len ? buf_len : ava_len; + if (sent_len > 0) { + int enqueue_len = 0; + unsigned long flag = 0; + + spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flag); + enqueue_len = kfifo_in(p_btif->p_tx_fifo, + (unsigned char *)p_buf, sent_len); + if (sent_len != enqueue_len) { + BTIF_ERR_FUNC("target tx len:%d, len sent:%d\n", + sent_len, enqueue_len); + } + i_ret = enqueue_len; + mb(); +/*enable BTIF Tx IRQ*/ + hal_btif_tx_ier_ctrl(p_btif, true); + spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flag); + BTIF_DBG_FUNC("enqueue len:%d\n", enqueue_len); + } else { + i_ret = 0; + } +#else + while ((_btif_is_tx_allow(p_btif)) && (sent_len < buf_len)) { + /*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ + lsr = BTIF_READ32(BTIF_LSR(base)); + + if (lsr & BTIF_LSR_TEMT_BIT) + /*Tx Holding Register if empty, which means we can write tx FIFO count to BTIF*/ + ava_len = BTIF_TX_FIFO_SIZE; + else if (lsr & BTIF_LSR_THRE_BIT) + /*Tx Holding Register if empty, which means we can write (Tx FIFO count - Tx threshold)to BTIF*/ + ava_len = BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE; + else { + /*this means data size in tx FIFO is more than Tx threshold, we will not write data to THR*/ + ava_len = 0; + break; + } + + left_len = buf_len - sent_len; +/*ava_len will be real length will write to BTIF THR*/ + ava_len = ava_len > left_len ? left_len : ava_len; +/*update sent length valud after this operation*/ + sent_len += ava_len; +/* + * whether we need memory barrier here? + * Ans: No, no memory ordering issue exist, + * CPU will make sure logically right + */ + while (ava_len--) + btif_reg_sync_writeb(*(p_data++), BTIF_THR(base)); + + } +/* while ((hal_btif_is_tx_allow()) && (sent_len < buf_len)); */ + + i_ret = sent_len; + +/*enable BTIF Tx IRQ*/ + hal_btif_tx_ier_ctrl(p_btif, true); +#endif + return i_ret; +} + + +/***************************************************************************** +* FUNCTION +* hal_btif_raise_wak_sig +* DESCRIPTION +* raise wakeup signal to counterpart +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_raise_wak_sig(P_MTK_BTIF_INFO_STR p_btif) +{ + int i_ret = -1; + unsigned long base = p_btif->base; +#if defined(CONFIG_MTK_CLKMGR) + if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { + BTIF_ERR_FUNC("%s: clock is off before send wakeup signal!!!\n", + __FILE__); + return i_ret; + } +#endif +/*write 0 to BTIF_WAK to pull ap_wakeup_consyss low */ + BTIF_CLR_BIT(BTIF_WAK(base), BTIF_WAK_BIT); + +/*wait for a period for longer than 1/32k period, here we use 40us*/ + set_current_state(TASK_UNINTERRUPTIBLE); + usleep_range(128, 160); +/* + * according to linux/documentation/timers/timers-how-to, we choose usleep_range + * SLEEPING FOR ~USECS OR SMALL MSECS ( 10us - 20ms): * Use usleep_range + */ +/*write 1 to pull ap_wakeup_consyss high*/ + BTIF_SET_BIT(BTIF_WAK(base), BTIF_WAK_BIT); + i_ret = 0; + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_dump_reg +* DESCRIPTION +* dump BTIF module's information when needed +* PARAMETERS +* p_base [IN] BTIF module's base address +* flag [IN] register id flag +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dump_reg(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_REG_ID flag) +{ +/*Chaozhong: To be implement*/ + int i_ret = -1; + int idx = 0; + /*unsigned long irq_flag = 0;*/ + unsigned long base = p_btif->base; + unsigned char reg_map[0xE0 / 4] = { 0 }; + unsigned int lsr = 0x0; + unsigned int dma_en = 0; + + /*spin_lock_irqsave(&(g_clk_cg_spinlock), irq_flag);*/ +#if defined(CONFIG_MTK_CLKMGR) + if (clock_is_on(MTK_BTIF_CG_BIT) == 0) { + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + BTIF_ERR_FUNC("%s: clock is off, this should never happen!!!\n", + __FILE__); + return i_ret; + } +#endif + lsr = BTIF_READ32(BTIF_LSR(base)); + dma_en = BTIF_READ32(BTIF_DMA_EN(base)); + /* + * here we omit 1st register which is THR/RBR register to avoid + * Rx data read by this debug information accidently + */ + for (idx = 1; idx < sizeof(reg_map); idx++) + reg_map[idx] = BTIF_READ8(p_btif->base + (4 * idx)); + /*spin_unlock_irqrestore(&(g_clk_cg_spinlock), irq_flag);*/ + BTIF_INFO_FUNC("BTIF's clock is on\n"); + BTIF_INFO_FUNC("base address: 0x%lx\n", base); + switch (flag) { + case REG_BTIF_ALL: +#if 0 + BTIF_INFO_FUNC("BTIF_IER:0x%x\n", BTIF_READ32(BTIF_IER(base))); + BTIF_INFO_FUNC("BTIF_IIR:0x%x\n", BTIF_READ32(BTIF_IIR(base))); + BTIF_INFO_FUNC("BTIF_FAKELCR:0x%x\n", + BTIF_READ32(BTIF_FAKELCR(base))); + BTIF_INFO_FUNC("BTIF_LSR:0x%x\n", BTIF_READ32(BTIF_LSR(base))); + BTIF_INFO_FUNC("BTIF_SLEEP_EN:0x%x\n", + BTIF_READ32(BTIF_SLEEP_EN(base))); + BTIF_INFO_FUNC("BTIF_DMA_EN:0x%x\n", + BTIF_READ32(BTIF_DMA_EN(base))); + BTIF_INFO_FUNC("BTIF_RTOCNT:0x%x\n", + BTIF_READ32(BTIF_RTOCNT(base))); + BTIF_INFO_FUNC("BTIF_TRI_LVL:0x%x\n", + BTIF_READ32(BTIF_TRI_LVL(base))); + BTIF_INFO_FUNC("BTIF_WAT_TIME:0x%x\n", + BTIF_READ32(BTIF_WAT_TIME(base))); + BTIF_INFO_FUNC("BTIF_HANDSHAKE:0x%x\n", + BTIF_READ32(BTIF_HANDSHAKE(base))); +#endif + btif_dump_array("BTIF register", reg_map, sizeof(reg_map)); + break; + default: + break; + } + + BTIF_INFO_FUNC("Tx DMA %s\n", + (dma_en & BTIF_DMA_EN_TX) ? "enabled" : "disabled"); + BTIF_INFO_FUNC("Rx DMA %s\n", + (dma_en & BTIF_DMA_EN_RX) ? "enabled" : "disabled"); + + BTIF_INFO_FUNC("Rx data is %s\n", + (lsr & BTIF_LSR_DR_BIT) ? "not empty" : "empty"); + BTIF_INFO_FUNC("Tx data is %s\n", + (lsr & BTIF_LSR_TEMT_BIT) ? "empty" : "not empty"); + + return i_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_is_tx_complete +* DESCRIPTION +* get tx complete flag +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* true means tx complete, false means tx in process +*****************************************************************************/ +bool hal_btif_is_tx_complete(P_MTK_BTIF_INFO_STR p_btif) +{ +/*Chaozhong: To be implement*/ + bool b_ret = false; + unsigned int lsr = 0; + unsigned long flags = 0; + unsigned long base = p_btif->base; + unsigned int tx_empty = 0; + unsigned int rx_dr = 0; + unsigned int tx_irq_disable = 0; + +/* + * 3 conditions allow clock to be disable + * 1. if TEMT is set or not + * 2. if DR is set or not + * 3. Tx IRQ is disabled or not + */ + lsr = BTIF_READ32(BTIF_LSR(base)); + tx_empty = lsr & BTIF_LSR_TEMT_BIT; + rx_dr = lsr & BTIF_LSR_DR_BIT; + tx_irq_disable = BTIF_READ32(BTIF_IER(base)) & BTIF_IER_TXEEN; + + b_ret = + (tx_empty && (tx_irq_disable == 0) && (rx_dr == 0)) ? true : false; + if (!b_ret) { + BTIF_DBG_FUNC + ("BTIF flag, tx_empty:%d, rx_dr:%d, tx_irq_disable:%d\n", + tx_empty, rx_dr, tx_irq_disable); + } +#if NEW_TX_HANDLING_SUPPORT + spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags); +/*clear Tx enable flag if necessary*/ + if (!(kfifo_is_empty(p_btif->p_tx_fifo))) { + BTIF_DBG_FUNC("BTIF tx FIFO is not empty\n"); + b_ret = false; + } + spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags); +#endif + return b_ret; +} + +/***************************************************************************** +* FUNCTION +* hal_btif_is_tx_allow +* DESCRIPTION +* whether tx is allowed +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* true if tx operation is allowed; false if tx is not allowed +*****************************************************************************/ +bool hal_btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif) +{ +#define MIN_TX_MB ((26 * 1000000 / 13) / 1000000) +#define AVE_TX_MB ((26 * 1000000 / 8) / 1000000) + +/*Chaozhong: To be implement*/ + bool b_ret = false; + +#if NEW_TX_HANDLING_SUPPORT + unsigned long flags = 0; + + spin_lock_irqsave(&(p_btif->tx_fifo_spinlock), flags); +/*clear Tx enable flag if necessary*/ + if (kfifo_is_full(p_btif->p_tx_fifo)) { + BTIF_WARN_FUNC("BTIF tx FIFO is full\n"); + b_ret = false; + } else { + b_ret = true; + } + spin_unlock_irqrestore(&(p_btif->tx_fifo_spinlock), flags); +#else + unsigned int lsr = 0; + unsigned long base = p_btif->base; + unsigned int wait_us = (BTIF_TX_FIFO_SIZE - BTIF_TX_FIFO_THRE) / MIN_TX_MB; /*only ava length */ + +/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ + lsr = BTIF_READ32(BTIF_LSR(base)); + + if (!(lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT))) { + BTIF_DBG_FUNC("wait for %d ~ %d us\n", wait_us, 3 * wait_us); +/* usleep_range(wait_us, 3 * 10 * wait_us); */ + usleep_range(wait_us, 3 * wait_us); + } + lsr = BTIF_READ32(BTIF_LSR(base)); + b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false; + if (!b_ret) + BTIF_DBG_FUNC(" tx is not allowed for the moment\n"); + else + BTIF_DBG_FUNC(" tx is allowed\n"); +#endif + return b_ret; +} + +#if !(NEW_TX_HANDLING_SUPPORT) + +static bool _btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif) +{ +/*Chaozhong: To be implement*/ + bool b_ret = false; + unsigned long base = p_btif->base; + unsigned int lsr = 0; + +/*read LSR and check THER or TEMT, either one is 1 means can accept tx data*/ + lsr = BTIF_READ32(BTIF_LSR(base)); + b_ret = (lsr & (BTIF_LSR_TEMT_BIT | BTIF_LSR_THRE_BIT)) ? true : false; + return b_ret; +} +#endif + +int hal_btif_pm_ops(P_MTK_BTIF_INFO_STR p_btif_info, MTK_BTIF_PM_OPID opid) +{ + int i_ret = -1; + + BTIF_DBG_FUNC("op id: %d\n", opid); + switch (opid) { + case BTIF_PM_DPIDLE_EN: + i_ret = 0; + break; + case BTIF_PM_DPIDLE_DIS: + i_ret = 0; + break; + case BTIF_PM_SUSPEND: + i_ret = 0; + break; + case BTIF_PM_RESUME: + i_ret = 0; + break; + case BTIF_PM_RESTORE_NOIRQ:{ + unsigned int flag = 0; + P_MTK_BTIF_IRQ_STR p_irq = p_btif_info->p_irq; + +#ifdef CONFIG_OF + flag = p_irq->irq_flags; +#else + switch (p_irq->sens_type) { + case IRQ_SENS_EDGE: + if (p_irq->edge_type == IRQ_EDGE_FALL) + flag = IRQF_TRIGGER_FALLING; + else if (p_irq->edge_type == IRQ_EDGE_RAISE) + flag = IRQF_TRIGGER_RISING; + else if (p_irq->edge_type == IRQ_EDGE_BOTH) + flag = IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING; + else + flag = IRQF_TRIGGER_FALLING; /*make this as default type */ + break; + case IRQ_SENS_LVL: + if (p_irq->lvl_type == IRQ_LVL_LOW) + flag = IRQF_TRIGGER_LOW; + else if (p_irq->lvl_type == IRQ_LVL_HIGH) + flag = IRQF_TRIGGER_HIGH; + else + flag = IRQF_TRIGGER_LOW; /*make this as default type */ + break; + default: + flag = IRQF_TRIGGER_LOW; /*make this as default type */ + break; + } +#endif +/* irq_set_irq_type(p_irq->irq_id, flag); */ + i_ret = 0; + } + break; + default: + i_ret = ERR_INVALID_PAR; + break; + } + + return i_ret; +} +void mtk_btif_read_cpu_sw_rst_debug_plat(void) +{ +#define CONSYS_AP2CONN_WAKEUP_OFFSET 0x00000064 + BTIF_WARN_FUNC("+CONSYS_AP2CONN_WAKEUP_OFFSET(0x%x)\n", + BTIF_READ32(mtk_btif.base + CONSYS_AP2CONN_WAKEUP_OFFSET)); +} + diff --git a/drivers/misc/mediatek/btif/common/inc/mtk_btif.h b/drivers/misc/mediatek/btif/common/inc/mtk_btif.h new file mode 100644 index 0000000000000..5e2f5a9857d91 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/inc/mtk_btif.h @@ -0,0 +1,370 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __MTK_BTIF_H_ +#define __MTK_BTIF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* gettimeofday */ +#include + +#include "btif_pub.h" +#include "btif_dma_pub.h" +#include "mtk_btif_exp.h" + +#define BTIF_PORT_NR 1 +#define BTIF_USER_NAME_MAX_LEN 32 + +/*-------------Register Defination Start ---------------*/ +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define BTIF_RX_BUFFER_SIZE (1024 * 32) +#else +#define BTIF_RX_BUFFER_SIZE (1024 * 64) +#endif +#define BTIF_TX_FIFO_SIZE (1024 * 4) + +/*------------Register Defination End ----------------*/ + +/*------------BTIF Module Clock and Power Control Defination---------------*/ +typedef enum _ENUM_BTIF_RX_TYPE_ { + BTIF_IRQ_CTX = 0, + BTIF_TASKLET_CTX = BTIF_IRQ_CTX + 1, + BTIF_THREAD_CTX = BTIF_TASKLET_CTX + 1, + BTIF_WQ_CTX = BTIF_THREAD_CTX + 1, + BTIF_RX_TYPE_MAX, +} ENUM_BTIF_RX_TYPE; + +typedef enum _ENUM_BTIF_TX_TYPE_ { + BTIF_TX_USER_CTX = 0, + BTIF_TX_SINGLE_CTX = BTIF_TX_USER_CTX + 1, + BTIF_TX_TYPE_MAX, +} ENUM_BTIF_TX_TYPE; + +typedef enum _ENUM_BTIF_STATE_ { + B_S_OFF = 0, + B_S_SUSPEND = B_S_OFF + 1, + B_S_DPIDLE = B_S_SUSPEND + 1, + B_S_ON = B_S_DPIDLE + 1, + B_S_MAX, +} ENUM_BTIF_STATE; + +#define ENABLE_BTIF_RX_DMA 1 +#define ENABLE_BTIF_TX_DMA 1 + +#if ENABLE_BTIF_TX_DMA +#define BTIF_TX_MODE BTIF_MODE_DMA +#else +#define BTIF_TX_MODE BTIF_MODE_PIO +#endif + +#if ENABLE_BTIF_RX_DMA +#define BTIF_RX_MODE BTIF_MODE_DMA +#else +#define BTIF_RX_MODE BTIF_MODE_PIO +#endif + +#define BTIF_RX_BTM_CTX BTIF_THREAD_CTX/*BTIF_WQ_CTX*//* BTIF_TASKLET_CTX */ +/* + * -- cannot be used because , + * mtk_wcn_stp_parser data will call *(stp_if_tx) to send ack, + * in which context sleepable lock or usleep operation may be used, + * these operation is not allowed in tasklet, may cause schedule_bug + */ + +#define BTIF_TX_CTX BTIF_TX_USER_CTX /* BTIF_TX_SINGLE_CTX */ + +#define ENABLE_BTIF_RX_THREAD_RT_SCHED 0 +#define MAX_BTIF_RXD_TIME_REC 3 + +/*Structure Defination*/ + +/*-----------------BTIF setting--------------*/ +typedef struct _mtk_btif_setting_ { + ENUM_BTIF_MODE tx_mode; /*BTIF Tx Mode Setting */ + ENUM_BTIF_MODE rx_mode; /*BTIF Tx Mode Setting */ + ENUM_BTIF_RX_TYPE rx_type; /*rx handle type */ + ENUM_BTIF_TX_TYPE tx_type; /*tx type */ +} mtk_btif_setting, *p_mtk_btif_setting; +/*---------------------------------------------------------------------------*/ + +#if 0 +/*---------------------------------------------------------------------------*/ +typedef struct _mtk_btif_register_ { + unsigned int iir; /*Interrupt Identification Register */ + unsigned int lsr; /*Line Status Register */ + unsigned int fake_lcr; /*Fake Lcr Regiseter */ + unsigned int fifo_ctrl; /*FIFO Control Register */ + unsigned int ier; /*Interrupt Enable Register */ + unsigned int sleep_en; /*Sleep Enable Register */ + unsigned int rto_counter; /*Rx Timeout Counter Register */ + unsigned int dma_en; /*DMA Enalbe Register */ + unsigned int tri_lvl; /*Tx/Rx Trigger Level Register */ + unsigned int wat_time; /*Async Wait Time Register */ + unsigned int handshake; /*New HandShake Mode Register */ + unsigned int sleep_wak; /*Sleep Wakeup Reigster */ +} mtk_btif_register, *p_mtk_btif_register; +/*---------------------------------------------------------------------------*/ + +#endif + +typedef struct _btif_buf_str_ { + unsigned int size; + unsigned char *p_buf; + /* + * For Tx: next Tx data pointer to FIFO; + * For Rx: next read data pointer from BTIF user + */ + unsigned int rd_idx; + /* + * For Tx: next Tx data pointer from BTIF user; + * For Rx: next write data(from FIFO) pointer + */ + unsigned int wr_idx; +} btif_buf_str, *p_btif_buf_str; + +/*---------------------------------------------------------------------------*/ +typedef struct _mtk_btif_dma_ { + /*p_mtk_btif*/ void *p_btif; + /*BTIF pointer to which DMA belongs */ + +#if 0 + unsigned int channel; /*DMA's channel */ +#endif + + ENUM_BTIF_DIR dir; /*DMA's direction: */ + bool enable; /*DMA enable or disable flag */ + + P_MTK_DMA_INFO_STR p_dma_info; /*DMA's IRQ information */ + +#if 0 + mtk_dma_register register; /*DMA's register */ +#endif + + spinlock_t iolock; /*io lock for DMA channel */ + atomic_t entry; /* entry count */ +} mtk_btif_dma, *p_mtk_btif_dma; + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MTK_ENG_BUILD)) +#define BTIF_LOG_ENTRY_NUM 10 +#else +#define BTIF_LOG_ENTRY_NUM 30 +#endif + +#define BTIF_LOG_SZ 1536 + +typedef void (*MTK_BTIF_RX_NOTIFY) (void); + +typedef struct _btif_log_buf_t_ { + unsigned int len; + struct timeval timer; + unsigned char buffer[BTIF_LOG_SZ]; +} BTIF_LOG_BUF_T, *P_BTIF_LOG_BUF_T; + +typedef struct _btif_log_queue_t_ { + ENUM_BTIF_DIR dir; + bool enable; + bool output_flag; + unsigned int in; + unsigned int out; + unsigned int size; + spinlock_t lock; + P_BTIF_LOG_BUF_T p_queue[BTIF_LOG_ENTRY_NUM]; +} BTIF_LOG_QUEUE_T, *P_BTIF_LOG_QUEUE_T; + +/*---------------------------------------------------------------------------*/ +typedef struct _mtk_btif_ { + unsigned int open_counter; /*open counter */ + bool enable; /*BTIF module enable flag */ + bool lpbk_flag; /*BTIF module enable flag */ +#if 0 + unsigned long base; /* BTIF controller base address */ +#endif + + ENUM_BTIF_STATE state; /*BTIF state mechanism */ + struct mutex state_mtx; /*lock to BTIF state mechanism's state change */ + struct mutex ops_mtx; /*lock to BTIF's open and close */ + +#if 0 + mtk_btif_register register; /*BTIF registers */ +#endif + + ENUM_BTIF_MODE tx_mode; /* BTIF Tx channel mode */ + ENUM_BTIF_MODE rx_mode; /* BTIF Rx channel mode */ + struct mutex tx_mtx; /*lock to BTIF's tx process */ +/*rx handling */ + ENUM_BTIF_RX_TYPE btm_type; /*BTIF Rx bottom half context */ +/*tx handling*/ + ENUM_BTIF_TX_TYPE tx_ctx; /*BTIF tx context */ +/* unsigned char rx_buf[BTIF_RX_BUFFER_SIZE]; */ + btif_buf_str btif_buf; + spinlock_t rx_irq_spinlock; /*lock for rx irq handling */ + +/*rx workqueue information*/ + /*lock to BTIF's rx bottom half when kernel thread is used */ + struct mutex rx_mtx; + struct workqueue_struct *p_rx_wq; + struct work_struct rx_work; + + struct workqueue_struct *p_tx_wq; + struct work_struct tx_work; + struct kfifo *p_tx_fifo; + +/*rx tasklet information*/ + struct tasklet_struct rx_tasklet; + /*lock to BTIF's rx bottom half when tasklet is used */ + spinlock_t rx_tasklet_spinlock; + +/*rx thread information*/ + struct task_struct *p_task; + struct completion rx_comp; + + mtk_btif_setting *setting; /*BTIF setting */ + + p_mtk_btif_dma p_tx_dma; /*BTIF Tx channel DMA */ + p_mtk_btif_dma p_rx_dma; /*BTIF Rx channel DMA */ + + MTK_WCN_BTIF_RX_CB rx_cb; /*Rx callback function */ + MTK_BTIF_RX_NOTIFY rx_notify; + + P_MTK_BTIF_INFO_STR p_btif_info; /*BTIF's information */ + +/*Log Tx data to buffer*/ + BTIF_LOG_QUEUE_T tx_log; + +/*Log Rx data to buffer*/ + BTIF_LOG_QUEUE_T rx_log; + +/* struct list_head *p_user_list; */ + struct list_head user_list; +/* get btif dev pointer*/ + void *private_data; +} mtk_btif, *p_mtk_btif; +/*---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +#if 0 +/*---------------------------------------------------------------------------*/ +typedef struct _mtk_dma_register_ { + unsigned int int_flag; /*Tx offset:0x0 Rx offset:0x0 */ + unsigned int int_enable; /*Tx offset:0x4 Rx offset:0x4 */ + unsigned int dma_enable; /*Tx offset:0x8 Rx offset:0x8 */ + unsigned int dma_reset; /*Tx offset:0xc Rx offset:0xc */ + unsigned int dma_stop; /*Tx offset:0x10 Rx offset:0x10 */ + unsigned int dma_flush; /*Tx offset:0x14 Rx offset:0x14 */ + unsigned int vff_addr; /*Tx offset:0x1c Rx offset:0x1c */ + unsigned int vff_len; /*Tx offset:0x24 Rx offset:0x24 */ + unsigned int vff_thr; /*Tx offset:0x28 Rx offset:0x28 */ + unsigned int vff_wpt; /*Tx offset:0x2c Rx offset:0x2c */ + unsigned int vff_rpt; /*Tx offset:0x30 Rx offset:0x30 */ + unsigned int rx_fc_thr; /*Tx:No this register Rx offset:0x34 */ + unsigned int int_buf_size; /*Tx offset:0x38 Rx offset:0x38 */ + unsigned int vff_valid_size; /*Tx offset:0x3c Rx offset:0x3c */ + unsigned int vff_left_size; /*Tx offset:0x40 Rx offset:0x40 */ + unsigned int debug_status; /*Tx offset:0x50 Rx offset:0x50 */ +} mtk_dma_register, *p_mtk_dma_register; +/*---------------------------------------------------------------------------*/ +#endif + +/*---------------------------------------------------------------------------*/ +typedef struct _mtk_btif_user_ { + bool enable; /*register its state */ + struct list_head entry; /*btif_user's bi-direction list table */ + /*BTIF's user, static allocation */ + char u_name[BTIF_USER_NAME_MAX_LEN]; + unsigned long u_id; + p_mtk_btif p_btif; +} mtk_btif_user, *p_mtk_btif_user; + +/*---------------------------------------------------------------------------*/ +#define BBS_PTR(ptr, idx) ((ptr->p_buf) + idx) + +#define BBS_SIZE(ptr) ((ptr)->size) +#define BBS_MASK(ptr) (BBS_SIZE(ptr) - 1) +#define BBS_COUNT(ptr) ((ptr)->wr_idx >= (ptr)->rd_idx ? (ptr)->wr_idx - \ +(ptr)->rd_idx : BBS_SIZE(ptr) - \ +((ptr)->rd_idx - (ptr)->wr_idx)) +#define BBS_COUNT_CUR(ptr, wr_idx) (wr_idx >= (ptr)->rd_idx ? wr_idx - \ +(ptr)->rd_idx : BBS_SIZE(ptr) - \ +((ptr)->rd_idx - wr_idx)) + +#define BBS_LEFT(ptr) (BBS_SIZE(ptr) - BBS_COUNT(ptr)) + +#define BBS_AVL_SIZE(ptr) (BBS_SIZE(ptr) - BBS_COUNT(ptr)) +#define BBS_FULL(ptr) (BBS_COUNT(ptr) - BBS_SIZE(ptr)) +#define BBS_EMPTY(ptr) ((ptr)->wr_idx == (ptr)->rd_idx) +#define BBS_WRITE_MOVE_NEXT(ptr) ((ptr)->wr_idx = \ +((ptr)->wr_idx + 1) & BBS_MASK(ptr)) +#define BBS_READ_MOVE_NEXT(ptr) ((ptr)->rd_idx = \ +((ptr)->rd_idx + 1) & BBS_MASK(ptr)) + +#define BBS_INIT(ptr) \ +{ \ +(ptr)->rd_idx = (ptr)->wr_idx = 0; \ +(ptr)->size = BTIF_RX_BUFFER_SIZE; \ +} + + +#define BTIF_MUTEX_UNLOCK(x) mutex_unlock(x) + +extern mtk_btif g_btif[]; + +int btif_open(p_mtk_btif p_btif); +int btif_close(p_mtk_btif p_btif); +int btif_send_data(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len); +int btif_enter_dpidle(p_mtk_btif p_btif); +int btif_exit_dpidle(p_mtk_btif p_btif); +int btif_rx_cb_reg(p_mtk_btif p_btif, MTK_WCN_BTIF_RX_CB rx_cb); + +/*for test purpose*/ +int _btif_suspend(p_mtk_btif p_btif); +int _btif_resume(p_mtk_btif p_btif); +int _btif_restore_noirq(p_mtk_btif p_btif); + +int btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag); +int btif_log_buf_dmp_in(P_BTIF_LOG_QUEUE_T p_log_que, const char *p_buf, + int len); +int btif_dump_data(char *p_buf, int len); +int btif_log_buf_dmp_out(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_buf_enable(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_buf_disable(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_output_enable(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_output_disable(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_buf_reset(P_BTIF_LOG_QUEUE_T p_log_que); +int btif_log_buf_init(p_mtk_btif p_btif); +int btif_dump_reg(p_mtk_btif p_btif); +int btif_rx_notify_reg(p_mtk_btif p_btif, MTK_BTIF_RX_NOTIFY rx_notify); +int btif_raise_wak_signal(p_mtk_btif p_btif); +int btif_clock_ctrl(p_mtk_btif p_btif, int en); +bool btif_parser_wmt_evt(p_mtk_btif p_btif, + const char *sub_str, + unsigned int sub_len); +void mtk_btif_read_cpu_sw_rst_debug(void); + +#endif /*__MTK_BTIF_H_*/ diff --git a/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h b/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h new file mode 100644 index 0000000000000..3752644fe0aae --- /dev/null +++ b/drivers/misc/mediatek/btif/common/inc/mtk_btif_exp.h @@ -0,0 +1,280 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MTK_BTIF_EXP_H_ +#define _MTK_BTIF_EXP_H_ + +/*--------------marco defination---------------*/ +#define BTIF_MAX_LEN_PER_PKT 2048 +#define BTIF_RXD_BE_BLOCKED_DETECT 1 +/*--------------Enum Defination---------------*/ +typedef enum _ENUM_BTIF_DPIDLE_ { + BTIF_DPIDLE_DISABLE = 0, + BTIF_DPIDLE_ENABLE = BTIF_DPIDLE_DISABLE + 1, + BTIF_DPIDLE_MAX, +} ENUM_BTIF_DPIDLE_CTRL; + +typedef enum _ENUM_BTIF_LPBK_MODE_ { + BTIF_LPBK_DISABLE = 0, + BTIF_LPBK_ENABLE = BTIF_LPBK_DISABLE + 1, + BTIF_LPBK_MAX, +} ENUM_BTIF_LPBK_MODE; + +typedef enum _ENUM_BTIF_DBG_ID_ { + BTIF_DISABLE_LOGGER = 0, + BTIF_ENABLE_LOGGER = BTIF_DISABLE_LOGGER + 1, + BTIF_DUMP_LOG = BTIF_ENABLE_LOGGER + 1, + BTIF_CLR_LOG = BTIF_DUMP_LOG + 1, + BTIF_DUMP_BTIF_REG = BTIF_CLR_LOG + 1, + BTIF_ENABLE_RT_LOG = BTIF_DUMP_BTIF_REG + 1, + BTIF_DISABLE_RT_LOG = BTIF_ENABLE_RT_LOG + 1, + BTIF_DBG_MAX, +} ENUM_BTIF_DBG_ID; + +typedef enum _ENUM_BTIF_OP_ERROR_CODE_ { + E_BTIF_AGAIN = 0, + E_BTIF_FAIL = -1, + E_BTIF_BAD_POINTER = -2, + E_BTIF_NO_SPACE = -3, + E_BTIF_INTR = -4, + E_BTIF_INVAL_PARAM = -5, + E_BTIF_ALREADY_OPEN = -6, + E_BTIF_NOT_OPEN = -7, + E_BTIF_INVAL_STATE = -8, +} ENUM_BTIF_OP_ERROR_CODE; + +/*--------------End of Enum Defination---------------*/ + +/*--------------Type Definition---------------*/ + +typedef int (*MTK_WCN_BTIF_RX_CB) (const unsigned char *p_buf, + unsigned int len); + +/*--------------End of Type Definition---------------*/ + +/*--------------Normal Mode API declearation---------------*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_open +* DESCRIPTION +* open BTIF interface, will do BTIF module HW and SW initialization +* PARAMETERS +* p_owner [IN] pointer to owner who call this API, +* currently there are 2 owner ("stp" or "btif_tester") +* may use this module +* user's id string must be less than 32 bytes +* for "stp", BTIF will call rx callback function to route rx data to STP module +* for "stp_tester", BTIF will save rx data +* and wait for native process to access +* p_id [IN] BTIF's user id will be put to this address +* RETURNS +* int 0 = succeed; others = fail, for detailed information, +* please see ENUM_BTIF_OP_ERROR_CODE +* if open success, value p_id will be the only identifier for +* user to access BTIF's other operations +* including read/write/dpidle_ctrl/rx_cb_retister +* this user id is only an identifier used for owner identification +*****************************************************************************/ +int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id); +//EXPORT_SYMBOL(mtk_wcn_btif_open) +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_close +* DESCRIPTION +* close BTIF interface, will do BTIF module HW and SW de-initialization +* once this API is called, p_btif should never be used by BTIF's user again +* PARAMETERS +* u_id [IN] BTIF's user id +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_close(unsigned long u_id); +//EXPORT_SYMBOL(mtk_wcn_btif_close) +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_write +* DESCRIPTION +* send data throuth BTIF module +* there's no internal buffer to cache STP data in BTIF driver, +* if in DMA mode +* btif driver will check if there's enough space +* in vFIFO for data to send in DMA mode +* if yes, put data to vFIFO and return corresponding data length to caller +* if no, corresponding error code will be returned to called +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* p_buf [IN] pointer to target data to send +* len [IN] data length (should be less than 2014 bytes per STP package) +* +* if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller +* if btif driver detected that no space is available in Tx FIFO, +* will return E_BTIF_NO_SPACE, +* mostly something is wrong with BTIF or consys when this +* return value is returned +* RETURNS +* int positive: data length send through BTIF; +* negative: please see ENUM_BTIF_OP_ERROR_CODE +* E_BTIF_AGAIN (0) will be returned to caller if btif does not have +* enough vFIFO to send data, when caller get 0, +* he should wait for a moment (5~10ms maybe) and +* try a few times (maybe 10~20) +* if still get E_BTIF_AGAIN, should call BTIF's debug API and +* dump BTIF driver and BTIF/DMA register information to kernel log +* for debug +* E_BTIF_BAD_POINTER will be returned to caller if btif is not +* opened successfully before call this API +* E_BTIF_INVAL_PARAM will be returned if parameter is not valid + +*****************************************************************************/ +int mtk_wcn_btif_write(unsigned long u_id, + const unsigned char *p_buf, unsigned int len); +//EXPORT_SYMBOL(mtk_wcn_btif_write) +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_read +* DESCRIPTION +* read data from BTIF module +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* p_buf [IN/OUT] pointer to buffer where rx data will be put +* max_len [IN] max buffer length +* RETURNS +* int positive: data length read from BTIF; +* negative: please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_read(unsigned long u_id, + unsigned char *p_buf, unsigned int max_len); +//EXPORT_SYMBOL(mtk_wcn_btif_read) +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_dpidle_ctrl +* DESCRIPTION +* control if BTIF module allow system enter deepidle state or not +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* en_flag [IN] one of ENUM_BTIF_DPIDLE_CTRL +* RETURNS +* int always return 0 +*****************************************************************************/ +int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id, ENUM_BTIF_DPIDLE_CTRL en_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_rx_cb_register +* DESCRIPTION +* register rx callback function to BTIF module by btif user +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* rx_cb [IN] pointer to stp rx handler callback function, +* should be comply with MTK_WCN_BTIF_RX_CB +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_wakeup_consys +* DESCRIPTION +* once sleep command is sent to con sys, +* should call this API before send wakeup command to +* make con sys aware host want to send data to consys +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_wakeup_consys(unsigned long u_id); + +/*--------------End of Normal Mode API declearation----------------*/ + +/*--------------Debug Purpose API declearation----------------*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_loopback_ctrl +* DESCRIPTION +* enable/disable BTIF internal loopback function, +* when this function is enabled, +* data send to btif will be received by btif itself +* only for debug purpose, should never use this function in normal mode +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* enable [IN] loopback mode control flag, enable or disable, +* shou be one of ENUM_BTIF_LPBK_MODE +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_loopback_ctrl(unsigned long u_id, ENUM_BTIF_LPBK_MODE enable); +//EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl) +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_logger_ctrl +* DESCRIPTION +* control BTIF logger function's behavior +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* flag [IN] should be one of ENUM_BTIF_DBG_ID +* BTIF_DISABLE_LOGGER - disable btif logger +* BTIF_ENABLE_LOGGER - enable btif logger +* BTIF_DUMP_LOG - dump log logged by btif +* BTIF_CLR_LOG - clear btif log buffer +* BTIF_DUMP_BTIF_REG - dump btif controller's register +* BTIF_DUMP_DMA_REG - dump DMA controller's register +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, +* please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, ENUM_BTIF_DBG_ID flag); +//EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl); +/*-----------End of Debug Purpose API declearation------------*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_parser_wmt_evt +* DESCRIPTION +* parser wmt sleep/wakeup evt in btif bbs buffer for debug +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* sub_str [IN] the str to be parsered +* str_len [IN] the length of sub_str +* RETURNS +* bool true = succeed; +* false = fail; +*****************************************************************************/ +bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id, + const char *sub_str, unsigned int str_len); + +int mtk_btif_exp_open_test(void); +int mtk_btif_exp_close_test(void); +int mtk_btif_exp_write_test(void); +int mtk_btif_exp_suspend_test(void); +int mtk_btif_exp_resume_test(void); +int mtk_btif_exp_enter_dpidle_test(void); +int mtk_btif_exp_exit_dpidle_test(void); +int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int loop); +int mtk_btif_exp_log_debug_test(int flag); +int mtk_btif_exp_restore_noirq_test(void); +int btif_wakeup_consys_no_id(void); +int mtk_btif_exp_clock_ctrl(int en); +#if BTIF_RXD_BE_BLOCKED_DETECT +int mtk_btif_rxd_be_blocked_flag_get(void); +#endif +void mtk_btif_read_cpu_sw_rst_debug_exp(void); +#endif /*_MTK_BTIF_EXP_H_*/ diff --git a/drivers/misc/mediatek/btif/common/mtk_btif.c b/drivers/misc/mediatek/btif/common/mtk_btif.c new file mode 100644 index 0000000000000..5deb64ef3e56f --- /dev/null +++ b/drivers/misc/mediatek/btif/common/mtk_btif.c @@ -0,0 +1,3472 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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. + */ + +/*-----------linux system header files----------------*/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/*#include */ +/*-----------driver own header files----------------*/ +#ifdef CONFIG_COMPAT +#include +#endif +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "MTK-BTIF" + +#define BTIF_CDEV_SUPPORT 1 + +#include "btif_pub.h" +#include "btif_dma_pub.h" +#include "mtk_btif_exp.h" +#include "mtk_btif.h" + +/*-----------static function declearation----------------*/ +static int mtk_btif_probe(struct platform_device *pdev); +static int mtk_btif_remove(struct platform_device *pdev); +static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state); +static int mtk_btif_resume(struct platform_device *pdev); +static int mtk_btif_drv_resume(struct device *dev); +static int mtk_btif_drv_suspend(struct device *pdev); + +static int mtk_btif_restore_noirq(struct device *device); +static int btif_file_open(struct inode *pinode, struct file *pfile); +static int btif_file_release(struct inode *pinode, struct file *pfile); +static ssize_t btif_file_read(struct file *pfile, + char __user *buf, size_t count, loff_t *f_ops); +static unsigned int btif_poll(struct file *filp, poll_table *wait); +static int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq, + mtk_btif_irq_handler irq_handler, void *data); +static int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data); +static int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en); +static int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en); +static irqreturn_t btif_irq_handler(int irq, void *data); +static unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info, + unsigned char *p_buf, + unsigned int buf_len); + +static irqreturn_t btif_tx_dma_irq_handler(int irq, void *data); +static irqreturn_t btif_rx_dma_irq_handler(int irq, void *data); + +static unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, + unsigned int buf_len); +static int _btif_controller_tx_setup(p_mtk_btif p_btif); +static int _btif_controller_tx_free(p_mtk_btif p_btif); +static int _btif_controller_rx_setup(p_mtk_btif p_btif); +static int _btif_controller_rx_free(p_mtk_btif p_btif); +static int _btif_tx_pio_setup(p_mtk_btif p_btif); +static int _btif_rx_pio_setup(p_mtk_btif p_btif); +static int _btif_rx_dma_setup(p_mtk_btif p_btif); +static int _btif_rx_dma_free(p_mtk_btif p_btif); +static int _btif_tx_dma_setup(p_mtk_btif p_btif); +static int _btif_tx_dma_free(p_mtk_btif p_btif); +static int _btif_controller_setup(p_mtk_btif p_btif); +static int _btif_controller_free(p_mtk_btif p_btif); + +static int _btif_pio_write(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len); +static int _btif_dma_write(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len); + +static unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len); +static unsigned int btif_bbs_read(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len); +static unsigned int btif_bbs_write(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len); +static void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs); +static int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len); +static int _btif_rx_btm_deinit(p_mtk_btif p_btif); +static int _btif_rx_btm_sched(p_mtk_btif p_btif); +static int _btif_rx_btm_init(p_mtk_btif p_btif); +static void btif_rx_tasklet(unsigned long func_data); +static void btif_rx_worker(struct work_struct *p_work); +static int btif_rx_thread(void *p_data); +static int btif_rx_data_consummer(p_mtk_btif p_btif); + +static int _btif_tx_ctx_init(p_mtk_btif p_btif); +static int _btif_tx_ctx_deinit(p_mtk_btif p_btif); +static void btif_tx_worker(struct work_struct *p_work); + +static int _btif_state_deinit(p_mtk_btif p_btif); +static int _btif_state_release(p_mtk_btif p_btif); +static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif); +static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state); +static int _btif_state_hold(p_mtk_btif p_btif); +static int _btif_state_init(p_mtk_btif p_btif); + +static int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif, + ENUM_BTIF_DPIDLE_CTRL en_flag); +static int _btif_enter_dpidle(p_mtk_btif p_btif); +static int _btif_exit_dpidle(p_mtk_btif p_btif); +static int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif); +static int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif); +static int _btif_enter_dpidle_from_on(p_mtk_btif p_btif); +static int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif); + +#if ENABLE_BTIF_TX_DMA +static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma); +static int _btif_vfifo_init(p_mtk_btif_dma p_dma); +#endif + +static bool _btif_is_tx_complete(p_mtk_btif p_btif); +static int _btif_init(p_mtk_btif p_btif); +static int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag); +static int btif_rx_dma_mode_set(int en); +static int btif_tx_dma_mode_set(int en); + +static int _btif_send_data(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len); + +/*-----------end of static function declearation----------------*/ + +static const char *g_state[B_S_MAX] = { + "OFF", + "SUSPEND", + "DPIDLE", + "ON", +}; + +/*-----------BTIF setting--------------*/ +mtk_btif_setting g_btif_setting[BTIF_PORT_NR] = { + { + .tx_mode = BTIF_TX_MODE, + .rx_mode = BTIF_RX_MODE, + .rx_type = BTIF_RX_BTM_CTX, + .tx_type = BTIF_TX_CTX, + }, +}; + +mtk_btif g_btif[BTIF_PORT_NR] = { + { + .open_counter = 0, + .state = B_S_OFF, + .setting = &g_btif_setting[0], + .p_tx_dma = NULL, + .p_rx_dma = NULL, + .rx_cb = NULL, + .p_btif_info = NULL, + }, +}; + +mtk_btif_dma g_dma[BTIF_PORT_NR][BTIF_DIR_MAX] = { + { + { + .p_btif = NULL, + .dir = BTIF_TX, + .p_dma_info = NULL, + .entry = ATOMIC_INIT(0), + }, + { + .p_btif = NULL, + .dir = BTIF_RX, + .p_dma_info = NULL, + .entry = ATOMIC_INIT(0), + }, + }, +}; + +#define G_MAX_PKG_LEN (7 * 1024) +static int g_max_pkg_len = G_MAX_PKG_LEN; /*DMA vFIFO is set to 8 * 1024, we set this to 7/8 * vFIFO size*/ +static int g_max_pding_data_size = BTIF_RX_BUFFER_SIZE * 3 / 4; + + +static int mtk_btif_dbg_lvl = BTIF_LOG_ERR; + +#if BTIF_RXD_BE_BLOCKED_DETECT +static struct timeval btif_rxd_time_stamp[MAX_BTIF_RXD_TIME_REC]; +#endif +/*-----------Platform bus related structures----------------*/ +#define DRV_NAME "mtk_btif" + +#ifdef CONFIG_OF +const struct of_device_id apbtif_of_ids[] = { + { .compatible = "mediatek,btif", }, + {} +}; +#endif + +const struct dev_pm_ops mtk_btif_drv_pm_ops = { + .restore_noirq = mtk_btif_restore_noirq, + .suspend = mtk_btif_drv_suspend, + .resume = mtk_btif_drv_resume, +}; + +struct platform_driver mtk_btif_dev_drv = { + .probe = mtk_btif_probe, + .remove = mtk_btif_remove, +#ifdef CONFIG_PM + .suspend = mtk_btif_suspend, + .resume = mtk_btif_resume, +#endif + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &mtk_btif_drv_pm_ops, +#endif +#ifdef CONFIG_OF + .of_match_table = apbtif_of_ids, +#endif + } +}; + +#define BTIF_STATE_RELEASE(x) _btif_state_release(x) + +/*-----------End of Platform bus related structures----------------*/ + +/*-----------platform bus related operation APIs----------------*/ + +static int mtk_btif_probe(struct platform_device *pdev) +{ +/*Chaozhong: ToDo: to be implement*/ +/*register IRQ for BTIF and Tx Rx DMA and disable them by default*/ + BTIF_INFO_FUNC("DO BTIF PROBE\n"); + platform_set_drvdata(pdev, &g_btif[0]); + g_btif[0].private_data = (struct device *)&pdev->dev; + +#if !defined(CONFIG_MTK_CLKMGR) + hal_btif_clk_get_and_prepare(pdev); +#endif + + return 0; +} + +static int mtk_btif_remove(struct platform_device *pdev) +{ +/*Chaozhong: ToDo: to be implement*/ + BTIF_INFO_FUNC("DO BTIF REMOVE\n"); + platform_set_drvdata(pdev, NULL); + g_btif[0].private_data = NULL; + return 0; +} + +int _btif_suspend(p_mtk_btif p_btif) +{ + int i_ret; + + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + if (p_btif != NULL) { + if (!(p_btif->enable)) + i_ret = 0; + else { + if (_btif_state_get(p_btif) == B_S_ON) { + BTIF_ERR_FUNC("BTIF in ON state,", + "there are data need to be send or recev,suspend fail\n"); + i_ret = -1; + } else { + /* + * before disable BTIF controller and DMA controller + * we need to set BTIF to ON state + */ + i_ret = _btif_exit_dpidle(p_btif); + if (i_ret == 0) { + i_ret += _btif_controller_free(p_btif); + i_ret = _btif_controller_tx_free(p_btif); + i_ret += _btif_controller_rx_free(p_btif); + } + if (i_ret != 0) { + BTIF_INFO_FUNC("failed\n"); + /*Chaozhong: what if failed*/ + } else { + BTIF_INFO_FUNC("succeed\n"); + i_ret = _btif_state_set(p_btif, B_S_SUSPEND); + if (i_ret && _btif_init(p_btif)) { + /*Chaozhong:BTIF re-init failed? what to do*/ + i_ret = _btif_state_set(p_btif, B_S_OFF); + } + } + } + } + } else + i_ret = -1; + BTIF_STATE_RELEASE(p_btif); + + return i_ret; +} + + +static int mtk_btif_drv_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + pm_message_t state = PMSG_SUSPEND; + + return mtk_btif_suspend(pdev, state); +} + +static int mtk_btif_drv_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return mtk_btif_resume(pdev); +} + +static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state) +{ + int i_ret = 0; + p_mtk_btif p_btif = NULL; + +/*Chaozhong: ToDo: to be implement*/ + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_suspend(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +} + +int _btif_restore_noirq(p_mtk_btif p_btif) +{ + int i_ret = 0; + +/*BTIF IRQ restore no irq*/ + i_ret = hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_RESTORE_NOIRQ); + if (i_ret == 0) { + BTIF_INFO_FUNC("BTIF HW IRQ restore succeed\n"); + } else { + BTIF_INFO_FUNC("BTIF HW IRQ restore failed, i_ret:%d\n", i_ret); + return i_ret; + } +/*BTIF DMA restore no irq*/ + if (p_btif->tx_mode & BTIF_MODE_DMA) { + i_ret = hal_dma_pm_ops(p_btif->p_tx_dma->p_dma_info, + BTIF_PM_RESTORE_NOIRQ); + if (i_ret == 0) { + BTIF_INFO_FUNC("BTIF Tx DMA IRQ restore succeed\n"); + } else { + BTIF_INFO_FUNC + ("BTIF Tx DMA IRQ restore failed, i_ret:%d\n", + i_ret); + return i_ret; + } + } + if (p_btif->rx_mode & BTIF_MODE_DMA) { + i_ret = hal_dma_pm_ops(p_btif->p_rx_dma->p_dma_info, + BTIF_PM_RESTORE_NOIRQ); + if (i_ret == 0) { + BTIF_INFO_FUNC("BTIF Rx DMA IRQ restore succeed\n"); + } else { + BTIF_INFO_FUNC + ("BTIF Rx DMA IRQ restore failed, i_ret:%d\n", + i_ret); + return i_ret; + } + } + return i_ret; +} + +static int mtk_btif_restore_noirq(struct device *dev) +{ + int i_ret = 0; + struct platform_device *pdev = to_platform_device(dev); + p_mtk_btif p_btif = platform_get_drvdata(pdev); + + BTIF_INFO_FUNC("++\n"); + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + if (p_btif->enable) + BTIF_ERR_FUNC("!!!-----------------!BTIF is not closed before IPOH shutdown!!!---------------!\n"); + WARN_ON(p_btif->enable); + + i_ret = _btif_restore_noirq(p_btif); + BTIF_STATE_RELEASE(p_btif); + BTIF_INFO_FUNC("--\n"); + return 0; +} + +int _btif_resume(p_mtk_btif p_btif) +{ + int i_ret = 0; + ENUM_BTIF_STATE state = B_S_MAX; + + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + if (p_btif != NULL) { + state = _btif_state_get(p_btif); + if (!(p_btif->enable)) + i_ret = 0; + else if (state == B_S_SUSPEND) + i_ret = _btif_enter_dpidle(p_btif); + else + BTIF_INFO_FUNC + ("BTIF state: %s before resume, do nothing\n", g_state[state]); + } else + i_ret = -1; + BTIF_STATE_RELEASE(p_btif); + + return i_ret; +} + +static int mtk_btif_resume(struct platform_device *pdev) +{ + int i_ret = 0; + p_mtk_btif p_btif = NULL; +/*Chaozhong: ToDo: to be implement*/ + BTIF_DBG_FUNC("++\n"); + p_btif = platform_get_drvdata(pdev); + i_ret = _btif_resume(p_btif); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return 0; +} + +/*-----------device node----------------*/ +#if BTIF_CDEV_SUPPORT + +dev_t btif_dev; +struct class *p_btif_class; +struct device *p_btif_dev; +const char *p_btif_dev_name = "btif"; +static struct semaphore wr_mtx; +static struct semaphore rd_mtx; +unsigned char wr_buf[2048]; +unsigned char rd_buf[2048]; +static int rx_notify_flag; +static DECLARE_WAIT_QUEUE_HEAD(btif_wq); +static int btif_file_open(struct inode *pinode, struct file *pfile); +static int btif_file_release(struct inode *pinode, struct file *pfile); +static ssize_t btif_file_read(struct file *pfile, + char __user *buf, size_t count, loff_t *f_ops); + +static ssize_t btif_file_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos); +static long btif_unlocked_ioctl(struct file *filp, unsigned int cmd, + unsigned long arg); +#ifdef CONFIG_COMPAT +static long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static struct cdev btif_dev_c; +static wait_queue_head_t btif_read_inq; /* read queues */ + +const struct file_operations mtk_btif_fops = { + .owner = THIS_MODULE, + .open = btif_file_open, + .release = btif_file_release, + .read = btif_file_read, + .write = btif_file_write, + .unlocked_ioctl = btif_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = btif_compat_ioctl, +#endif + .poll = btif_poll, +}; + +static int btif_chrdev_init(void) +{ + int i_ret; + + int i_err; + + /* alloc device number dynamically */ + i_ret = alloc_chrdev_region(&btif_dev, 0, 1, p_btif_dev_name); + if (i_ret) { + BTIF_ERR_FUNC("devuce number allocation failed, i_ret:%d\n", + i_ret); + } else { + BTIF_INFO_FUNC("devuce number allocation succeed\n"); + } + cdev_init(&btif_dev_c, &mtk_btif_fops); + btif_dev_c.owner = THIS_MODULE; + i_err = cdev_add(&btif_dev_c, btif_dev, 1); + if (i_err) { + BTIF_ERR_FUNC("error add btif dev to kernel, error code:%d\n", + i_err); + unregister_chrdev_region(btif_dev, 1); + btif_dev = 0; + return -1; + } + BTIF_INFO_FUNC("add btif dev to kernel succeed\n"); + + p_btif_class = class_create(THIS_MODULE, p_btif_dev_name); + if (IS_ERR(p_btif_class)) { + BTIF_ERR_FUNC("error happened when doing class_create\n"); + unregister_chrdev_region(btif_dev, 1); + btif_dev = 0; + return -2; + } + BTIF_INFO_FUNC("create class for btif succeed\n"); + + p_btif_dev = device_create(p_btif_class, + NULL, btif_dev, 0, p_btif_dev_name); + if (IS_ERR(p_btif_dev)) { + BTIF_ERR_FUNC("error happened when doing device_create\n"); + class_destroy(p_btif_class); + p_btif_class = NULL; + unregister_chrdev_region(btif_dev, 1); + btif_dev = 0; + return -3; + } + BTIF_INFO_FUNC("create device for btif succeed\n"); + + return 0; +} + +void btif_rx_notify_cb(void) +{ + BTIF_DBG_FUNC("++\n"); + rx_notify_flag = 1; + wake_up(&btif_wq); + wake_up_interruptible(&btif_read_inq); + BTIF_DBG_FUNC("--\n"); +} + +unsigned int btif_poll(struct file *filp, poll_table *wait) +{ + unsigned int mask = 0; + unsigned int ava_len = 0; +/* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */ + unsigned int wr_idx = g_btif[0].btif_buf.wr_idx; + +/* BTIF_Rx_IRQ_Disable(); */ + ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx); + BTIF_INFO_FUNC("++\n"); + if (ava_len == 0) { + poll_wait(filp, &btif_read_inq, wait); + wr_idx = g_btif[0].btif_buf.wr_idx; + ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx); +/* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */ + if (ava_len) + mask |= POLLIN | POLLRDNORM; /* readable */ + } else { + mask |= POLLIN | POLLRDNORM; /* readable */ + } +/*make for writable*/ + mask |= POLLOUT | POLLWRNORM; /* writable */ + BTIF_INFO_FUNC("--, mask:%d\n", mask); + return mask; +} + +static int _btif_file_open(void) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + + BTIF_INFO_FUNC("++\n"); + +/*Chaozhong: ToDo: to be implement*/ + i_ret = btif_open(p_btif); + if ((i_ret != 0) && (i_ret != E_BTIF_ALREADY_OPEN)) { + BTIF_ERR_FUNC("btif_open failed, error code:%d\n", i_ret); + } else { + BTIF_INFO_FUNC("btif_open succeed\n"); + i_ret = 0; + } +/*semaphore for read and write operation init*/ + sema_init(&wr_mtx, 1); + sema_init(&rd_mtx, 1); + +/*buffer for read and write init*/ + memset(wr_buf, 0, sizeof(wr_buf)); + memset(rd_buf, 0, sizeof(rd_buf)); + init_waitqueue_head(&(btif_read_inq)); + btif_rx_notify_reg(p_btif, btif_rx_notify_cb); + BTIF_INFO_FUNC("--\n"); + return i_ret; +} + +static int _btif_file_close(void) +{ + int i_ret = -1; + + BTIF_INFO_FUNC("++\n"); +/*Chaozhong: ToDo: to be implement*/ + i_ret = btif_close(&g_btif[0]); + if (i_ret != 0) + BTIF_ERR_FUNC("btif_close failed, error code:%d\n", i_ret); + else + BTIF_INFO_FUNC("btif_close succeed\n"); + + BTIF_INFO_FUNC("--\n"); + return i_ret; +} + +static int btif_file_open(struct inode *pinode, struct file *pfile) +{ + int i_ret = -1; + + BTIF_INFO_FUNC("pid:%d\n", current->pid); + i_ret = 0; + return i_ret; +} + +static int btif_file_release(struct inode *pinode, struct file *pfile) +{ + int i_ret = -1; + + BTIF_INFO_FUNC("pid:%d\n", current->pid); + i_ret = 0; + return i_ret; +} + +static ssize_t btif_file_read(struct file *pfile, + char __user *buf, size_t count, loff_t *f_ops) +{ + int i_ret = 0; + int rd_len = 0; + + BTIF_INFO_FUNC("++\n"); + down(&rd_mtx); + rd_len = btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); + while (rd_len == 0) { + if (pfile->f_flags & O_NONBLOCK) + break; + + wait_event(btif_wq, rx_notify_flag != 0); + rx_notify_flag = 0; + rd_len = + btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, + sizeof(rd_buf)); + } + + if (rd_len == 0) + i_ret = 0; + else if ((rd_len > 0) && (copy_to_user(buf, rd_buf, rd_len) == 0)) + i_ret = rd_len; + else + i_ret = -EFAULT; + + up(&rd_mtx); + BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +} + +ssize_t btif_file_write(struct file *filp, + const char __user *buf, size_t count, loff_t *f_pos) +{ + int i_ret = 0; + int copy_size = 0; + + copy_size = count > sizeof(wr_buf) ? sizeof(wr_buf) : count; + + BTIF_INFO_FUNC("++\n"); + down(&wr_mtx); + if (copy_from_user(&wr_buf[0], &buf[0], copy_size)) + i_ret = -EFAULT; + else + i_ret = btif_send_data(&g_btif[0], wr_buf, copy_size); + + up(&wr_mtx); + BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret); + + return i_ret; +} +#ifdef CONFIG_COMPAT +long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + BTIF_INFO_FUNC("cmd[0x%x]\n", cmd); + ret = btif_unlocked_ioctl(filp, cmd, arg); + return ret; +} +#endif +long btif_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ +#define BTIF_IOC_MAGIC 0xb0 +#define BTIF_IOCTL_OPEN _IOW(BTIF_IOC_MAGIC, 1, int) +#define BTIF_IOCTL_CLOSE _IOW(BTIF_IOC_MAGIC, 2, int) +#define BTIF_IOCTL_LPBK_CTRL _IOWR(BTIF_IOC_MAGIC, 3, int) +#define BTIF_IOCTL_LOG_FUNC_CTRL _IOWR(BTIF_IOC_MAGIC, 4, int) +#define BTIF_IOCTL_RT_LOG_CTRL _IOWR(BTIF_IOC_MAGIC, 5, int) +#define BTIF_IOCTL_LOG_DUMP _IOWR(BTIF_IOC_MAGIC, 6, int) +#define BTIF_IOCTL_REG_DUMP _IOWR(BTIF_IOC_MAGIC, 7, int) +#define BTIF_IOCTL_DMA_CTRL _IOWR(BTIF_IOC_MAGIC, 8, int) + + long ret = 0; +/* unsigned char p_buf[NAME_MAX + 1]; */ + p_mtk_btif p_btif = &g_btif[0]; + + BTIF_INFO_FUNC("++\n"); + BTIF_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); + + switch (cmd) { + case BTIF_IOCTL_OPEN: + ret = _btif_file_open(); + break; + case BTIF_IOCTL_CLOSE: + ret = _btif_file_close(); + break; + case BTIF_IOCTL_LPBK_CTRL: + ret = btif_lpbk_ctrl(p_btif, arg == 0 ? 0 : 1); + break; + case BTIF_IOCTL_LOG_FUNC_CTRL: + if (arg == 0) { + ret += btif_log_buf_disable(&p_btif->tx_log); + ret += btif_log_buf_disable(&p_btif->rx_log); + } else { + ret += btif_log_buf_enable(&p_btif->tx_log); + ret += btif_log_buf_enable(&p_btif->rx_log); + } + break; + case BTIF_IOCTL_RT_LOG_CTRL: + if (arg == 0) { + ret += btif_log_output_disable(&p_btif->tx_log); + ret += btif_log_output_disable(&p_btif->rx_log); + } else { + ret += btif_log_output_enable(&p_btif->tx_log); + ret += btif_log_output_enable(&p_btif->rx_log); + } + break; + case BTIF_IOCTL_LOG_DUMP: + + ret += btif_log_buf_dmp_out(&p_btif->tx_log); + ret += btif_log_buf_dmp_out(&p_btif->rx_log); + break; + case BTIF_IOCTL_REG_DUMP: + ret += btif_dump_reg(p_btif); + break; + case BTIF_IOCTL_DMA_CTRL: + if (arg == 0) { + ret += btif_tx_dma_mode_set(0); + ret += btif_rx_dma_mode_set(0); + } else { + ret += btif_tx_dma_mode_set(1); + ret += btif_rx_dma_mode_set(1); + } + break; + default: + BTIF_INFO_FUNC("unknown cmd(%d)\n", cmd); + ret = -2; + break; + } + BTIF_INFO_FUNC("--\n"); + return ret; +} + +#endif + +/*-----------device property----------------*/ +//static ssize_t driver_flag_read(struct device_driver *drv, char *buf) +static ssize_t flag_show(struct device_driver *drv, char *buf) +{ + return sprintf(buf, "btif driver debug level:%d\n", mtk_btif_dbg_lvl); +} + +//static ssize_t driver_flag_set(struct device_driver *drv, +static ssize_t flag_store(struct device_driver *drv, + const char *buffer, size_t count) +{ + char buf[256]; + char *p_buf; + unsigned long len = count; + long x = 0; + long y = 0; + long z = 0; + int result = 0; + char *p_token = NULL; + char *p_delimiter = " \t"; + + BTIF_INFO_FUNC("buffer = %s, count = %zd\n", buffer, count); + if (len >= sizeof(buf)) { + BTIF_ERR_FUNC("input handling fail!\n"); + len = sizeof(buf) - 1; + return -1; + } + + memcpy(buf, buffer, sizeof(buf)); + p_buf = buf; + + p_token = strsep(&p_buf, p_delimiter); + if (p_token != NULL) { + result = kstrtol(p_token, 16, &x); + BTIF_INFO_FUNC("x = 0x%08x\n\r", x); + } else + x = 0; +/* x = (NULL != p_token) ? kstrtol(p_token, 16, NULL) : 0;*/ + + p_token = strsep(&p_buf, "\t\n "); + if (p_token != NULL) { + result = kstrtol(p_token, 16, &y); + BTIF_INFO_FUNC("y = 0x%08x\n\r", y); + } else + y = 0; + + p_token = strsep(&p_buf, "\t\n "); + if (p_token != NULL) + result = kstrtol(p_token, 16, &z); + else + z = 0; + + BTIF_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + switch (x) { + case 1: + mtk_btif_exp_open_test(); + break; + case 2: + mtk_btif_exp_close_test(); + break; + case 3: + mtk_btif_exp_write_test(); + break; + case 4: + mtk_btif_exp_enter_dpidle_test(); + break; + case 5: + mtk_btif_exp_exit_dpidle_test(); + break; + case 6: + mtk_btif_exp_suspend_test(); + break; + case 7: + mtk_btif_exp_resume_test(); + break; + case 8: + if (y > BTIF_LOG_LOUD) + mtk_btif_dbg_lvl = BTIF_LOG_LOUD; + else if (y < BTIF_LOG_ERR) + mtk_btif_dbg_lvl = BTIF_LOG_WARN; + else + mtk_btif_dbg_lvl = y; + BTIF_ERR_FUNC("mtk_btif_dbg_lvl set to %d\n", mtk_btif_dbg_lvl); + break; + case 9: + mtk_btif_exp_open_test(); + mtk_btif_exp_write_test(); + mtk_btif_exp_close_test(); + break; + case 0xa: + mtk_btif_exp_log_debug_test(y); + break; + case 0xb: + btif_tx_dma_mode_set(1); + btif_rx_dma_mode_set(1); + break; + case 0xc: + btif_tx_dma_mode_set(0); + btif_rx_dma_mode_set(0); + break; + case 0xd: + mtk_btif_exp_restore_noirq_test(); + break; + case 0xe: + btif_wakeup_consys_no_id(); + break; + case 0xf: + mtk_btif_exp_clock_ctrl(y); + break; + case 0x10: + y = y > G_MAX_PKG_LEN ? G_MAX_PKG_LEN : y; + y = y < 1024 ? 1024 : y; + BTIF_INFO_FUNC("g_max_pkg_len is set to %d\n", y); + g_max_pkg_len = y; + break; + case 0x11: + y = y > BTIF_RX_BUFFER_SIZE ? BTIF_RX_BUFFER_SIZE : y; + y = y < 1024 ? 1024 : y; + BTIF_INFO_FUNC("g_max_pding_data_size is set to %d\n", y); + g_max_pding_data_size = y; + break; + default: + mtk_btif_exp_open_test(); + mtk_btif_exp_write_stress_test(3030, 1); + mtk_btif_exp_close_test(); + BTIF_WARN_FUNC("not supported.\n"); + break; + } + + return count; +} + +//FWU: driver_ATTR dropped in 4.14 +//static DRIVER_ATTR(flag, S_IRUGO | S_IWUSR, driver_flag_read, driver_flag_set); +static DRIVER_ATTR_RW(flag); + +/*-----------End of platform bus related operation APIs------------*/ + +/*-----------------------platform driver ----------------*/ + +int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq, + mtk_btif_irq_handler irq_handler, void *data) +{ + int i_ret = -1; + unsigned int irq_id; + unsigned int flag; + + if ((p_irq == NULL) || (irq_handler == NULL)) + return E_BTIF_INVAL_PARAM; + + if (!(p_irq->is_irq_sup)) { + BTIF_WARN_FUNC("%s is not supported\n", p_irq->name); + return 0; + } + + irq_id = p_irq->irq_id; + +#ifdef CONFIG_OF + flag = p_irq->irq_flags; +#else + switch (p_irq->sens_type) { + case IRQ_SENS_EDGE: + if (p_irq->edge_type == IRQ_EDGE_FALL) + flag = IRQF_TRIGGER_FALLING; + else if (p_irq->edge_type == IRQ_EDGE_RAISE) + flag = IRQF_TRIGGER_RISING; + else if (p_irq->edge_type == IRQ_EDGE_BOTH) + flag = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; + else + /*make this as default type */ + flag = IRQF_TRIGGER_FALLING; + break; + case IRQ_SENS_LVL: + if (p_irq->lvl_type == IRQ_LVL_LOW) + flag = IRQF_TRIGGER_LOW; + else if (p_irq->lvl_type == IRQ_LVL_HIGH) + flag = IRQF_TRIGGER_HIGH; + else + /*make this as default type */ + flag = IRQF_TRIGGER_LOW; + break; + default: + /*make this as default type */ + flag = IRQF_TRIGGER_LOW; + break; + } +#endif + + p_irq->p_irq_handler = irq_handler; + i_ret = request_irq(irq_id, + (irq_handler_t) irq_handler, + flag, p_irq->name, data); + if (i_ret) + return i_ret; + + p_irq->reg_flag = true; + return 0; +} + +int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data) +{ + int i_ret = 0; + unsigned int eint_num = p_irq->irq_id; + + if ((p_irq->is_irq_sup) && (p_irq->reg_flag)) { + _btif_irq_ctrl(p_irq, false); + free_irq(eint_num, data); + p_irq->reg_flag = false; + } +/*do nothing for this operation*/ + return i_ret; +} + +int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en) +{ + unsigned int eint_num = p_irq->irq_id; + + if (en) + enable_irq(eint_num); + else + disable_irq_nosync(eint_num); + + return 0; +} + +int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en) +{ + unsigned int eint_num = p_irq->irq_id; + + if (en) + enable_irq(eint_num); + else + disable_irq(eint_num); + + return 0; +} + + +irqreturn_t btif_irq_handler(int irq, void *data) +{ +/*search BTIF? just use index 0*/ +/*Chaozhong: do we need lock here?*/ + + p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ + + BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); + + _btif_irq_ctrl(p_btif->p_btif_info->p_irq, false); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); +#endif + + hal_btif_irq_handler(p_btif->p_btif_info, NULL, 0); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); +#endif + + _btif_irq_ctrl(p_btif->p_btif_info->p_irq, true); + _btif_rx_btm_sched(p_btif); + + BTIF_DBG_FUNC("--\n"); + return IRQ_HANDLED; +} + +irqreturn_t btif_tx_dma_irq_handler(int irq, void *data) +{ +/*search BTIF? just use index 0*/ + + p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ + p_mtk_btif_dma p_tx_dma = p_btif->p_tx_dma; + P_MTK_DMA_INFO_STR p_dma_info = p_tx_dma->p_dma_info; + + BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); + _btif_irq_ctrl(p_dma_info->p_irq, false); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); +#endif + + hal_tx_dma_irq_handler(p_dma_info); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); +#endif + _btif_irq_ctrl(p_dma_info->p_irq, true); + BTIF_DBG_FUNC("--\n"); + return IRQ_HANDLED; +} + +irqreturn_t btif_rx_dma_irq_handler(int irq, void *data) +{ +/*search BTIF? just use index 0*/ + + p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */ + p_mtk_btif_dma p_rx_dma = p_btif->p_rx_dma; + P_MTK_DMA_INFO_STR p_rx_dma_info = p_rx_dma->p_dma_info; + + BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data); + + _btif_irq_ctrl(p_rx_dma_info->p_irq, false); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); + hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_ENABLE); +#endif + + hal_rx_dma_irq_handler(p_rx_dma_info, NULL, 0); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_DISABLE); + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); +#endif + + _btif_irq_ctrl(p_rx_dma_info->p_irq, true); + + _btif_rx_btm_sched(p_btif); + + BTIF_DBG_FUNC("--\n"); + + return IRQ_HANDLED; +} + +unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, + unsigned int buf_len) +{ + unsigned int index = 0; + p_mtk_btif p_btif = &(g_btif[index]); + +#if 0 + _btif_dump_memory("", p_buf, buf_len); +#endif + + btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len); +/*save DMA Rx packet here*/ + if (buf_len > 0) + btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len); + + return 0; +} + +unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info, + unsigned char *p_buf, + unsigned int buf_len) +{ + unsigned int index = 0; + p_mtk_btif p_btif = &(g_btif[index]); + +#if 0 + _btif_dump_memory("", p_buf, buf_len); +#endif + btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len); + +/*save PIO Rx packet here*/ + if (buf_len > 0) + btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len); + + return 0; +} + +bool btif_parser_wmt_evt(p_mtk_btif p_btif, + const char *sub_str, + unsigned int str_len) +{ + unsigned int data_cnt = 0; + unsigned int copy_cnt = 0; + char *local_buf = NULL; + bool b_ret = false; + p_btif_buf_str p_bbs = &(p_btif->btif_buf); + unsigned int wr_idx = p_bbs->wr_idx; + unsigned int rd_idx = p_bbs->rd_idx; + + data_cnt = copy_cnt = BBS_COUNT(p_bbs); + + if (data_cnt < str_len) { + BTIF_WARN_FUNC("there is not enough data for parser,need(%d),have(%d)\n", str_len, data_cnt); + return false; + } + BTIF_INFO_FUNC("data count in bbs buffer:%d,wr_idx(%d),rd_idx(%d)\n", data_cnt, wr_idx, rd_idx); + local_buf = vmalloc((data_cnt + 3) & ~0x3UL); + if (!local_buf) { + BTIF_WARN_FUNC("vmalloc memory fail\n"); + return false; + } + + if (wr_idx >= rd_idx) { + memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), copy_cnt); + } else { + unsigned int tail_len = BBS_SIZE(p_bbs) - rd_idx; + + BTIF_INFO_FUNC("tail_Len(%d)\n", tail_len); + memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), tail_len); + memcpy(local_buf + tail_len, BBS_PTR(p_bbs, 0), copy_cnt - tail_len); + } + + do { + int i = 0; + int j = 0; + int k = 0; + int d = 0; + + BTIF_INFO_FUNC("sub_str_len:%d\n", str_len); + for (i = 0; i < copy_cnt; i++) { + BTIF_DBG_FUNC("i:%d\n", i); + k = i; + while (1) { + if ((j >= str_len) || (k >= copy_cnt) || (sub_str[j++] != local_buf[k++])) + break; + } + + if (j == str_len) { + for (d = i; d < (str_len + i); d++) + BTIF_INFO_FUNC("0x%2x", local_buf[d]); + BTIF_INFO_FUNC("find sub str index:%d\n", i); + b_ret = true; + break; + } + if (j < str_len) + j = 0; + } + + } while (0); + + vfree(local_buf); + return b_ret; +} +int _btif_controller_tx_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif->tx_mode == BTIF_MODE_DMA) { + i_ret = _btif_tx_dma_setup(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_tx_dma_setup failed,i_ret(%d),", + "set tx to PIO mode\n", i_ret); + i_ret = _btif_tx_pio_setup(p_btif); + } + } else +/*enable Tx PIO mode*/ + i_ret = _btif_tx_pio_setup(p_btif); + + return i_ret; +} + +int _btif_controller_tx_free(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif->tx_mode == BTIF_MODE_DMA) { + i_ret = _btif_tx_dma_free(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_tx_dma_free failed, i_ret(%d)\n", + i_ret); + } + } else { +/*do nothing for Tx PIO mode*/ + } + return i_ret; +} + +int _btif_controller_rx_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif->rx_mode == BTIF_MODE_DMA) { + i_ret = _btif_rx_dma_setup(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_tx_dma_setup failed, i_ret(%d),", + "set tx to PIO mode\n", i_ret); + i_ret = _btif_rx_pio_setup(p_btif); + } + } else { +/*enable Tx PIO mode*/ + i_ret = _btif_rx_pio_setup(p_btif); + } + return i_ret; +} + +int _btif_controller_rx_free(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif->rx_mode == BTIF_MODE_DMA) { + i_ret = _btif_rx_dma_free(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_rx_dma_free failed, i_ret(%d)\n", + i_ret); + } + } else { +/*do nothing for Rx PIO mode*/ + } + return i_ret; +} + +int _btif_tx_pio_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + +/*set Tx to PIO mode*/ + p_btif->tx_mode = BTIF_MODE_PIO; +/*enable Tx PIO mode*/ + i_ret = hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_PIO); + return i_ret; +} + +int _btif_rx_pio_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq; + + p_btif->rx_mode = BTIF_MODE_PIO; +/*Enable Rx IRQ*/ + _btif_irq_ctrl(p_btif_irq, true); +/*enable Rx PIO mode*/ + i_ret = hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_PIO); + return i_ret; +} + +int _btif_rx_dma_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + P_MTK_BTIF_INFO_STR p_btif_info = NULL; + P_MTK_BTIF_IRQ_STR p_btif_irq = NULL; + P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info; + + p_btif_info = p_btif->p_btif_info; + p_btif_irq = p_dma_info->p_irq; + +/*vFIFO reset*/ + hal_btif_vfifo_reset(p_dma_info); + + i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); + if (i_ret) { + BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d),", + "set rx to pio mode\n", i_ret); +/*DMA control failed set Rx to PIO mode*/ + return _btif_rx_pio_setup(p_btif); + } +/*hardware init*/ + hal_btif_dma_hw_init(p_dma_info); + + hal_btif_dma_rx_cb_reg(p_dma_info, + (dma_rx_buf_write) btif_dma_rx_data_receiver); + +/*DMA controller enable*/ + i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); + if (i_ret) { + BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),", + "set rx to pio mode\n", i_ret); + hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); +/*DMA control failed set Rx to PIO mode*/ + i_ret = _btif_rx_pio_setup(p_btif); + } else { +/*enable Rx DMA mode*/ + hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_DMA); + +/*DMA Rx IRQ register*/ + _btif_irq_reg(p_btif_irq, btif_rx_dma_irq_handler, p_btif); +#if 0 +/*Enable DMA Rx IRQ*/ + _btif_irq_ctrl(p_btif_irq, true); +#endif + BTIF_DBG_FUNC("succeed\n"); + } + return i_ret; +} + +int _btif_rx_dma_free(p_mtk_btif p_btif) +{ + P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info; + P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_rx_dma->p_dma_info->p_irq; + + hal_btif_dma_rx_cb_reg(p_dma_info, (dma_rx_buf_write) NULL); + _btif_irq_free(p_irq, p_btif); +/*disable BTIF Rx DMA channel*/ + hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE); +/*disable clock output*/ + return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); +} + +int _btif_tx_dma_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; + P_MTK_BTIF_IRQ_STR p_btif_irq = p_dma_info->p_irq; + +/*vFIFO reset*/ + hal_btif_vfifo_reset(p_dma_info); + + i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE); + if (i_ret) { + BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d)\n", + i_ret); + return i_ret; + } +/*DMA controller setup*/ + hal_btif_dma_hw_init(p_dma_info); + +/*DMA HW Enable*/ + i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE); + if (i_ret) { + BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),", + "set tx to pio mode\n", i_ret); + +#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) + hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); +#endif + + _btif_tx_pio_setup(p_btif); + } else { + hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_DMA); +/*DMA Tx IRQ register*/ + _btif_irq_reg(p_btif_irq, btif_tx_dma_irq_handler, p_btif); +#if 0 +/*disable DMA Tx IRQ*/ + _btif_irq_ctrl(p_btif_irq, false); +#endif + + BTIF_DBG_FUNC("succeed\n"); + } + return i_ret; +} + +int _btif_tx_dma_free(p_mtk_btif p_btif) +{ + P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; + P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_tx_dma->p_dma_info->p_irq; + + _btif_irq_free(p_irq, p_btif); +/*disable BTIF Tx DMA channel*/ + hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE); +/*disable clock output*/ + return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE); +} + +int btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag) +{ + int i_ret = -1; + +/*hold state mechine lock*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; +#if 0 + state = _btif_state_get(p_btif); + if (p_btif->enable && B_S_ON == state) + i_ret = _btif_lpbk_ctrl(p_btif, flag); + else + i_ret = E_BTIF_INVAL_STATE; +#endif + i_ret = _btif_exit_dpidle(p_btif); + if (i_ret == 0) + i_ret = _btif_lpbk_ctrl(p_btif, flag); + else + i_ret = E_BTIF_INVAL_STATE; + + BTIF_STATE_RELEASE(p_btif); + return i_ret; +} + +int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag) +{ + int i_ret = -1; + + if (flag) { + i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, true); + BTIF_DBG_FUNC("loopback function enabled\n"); + } else { + i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, false); + BTIF_DBG_FUNC("loopback function disabled\n"); + } + if (i_ret == 0) + p_btif->lpbk_flag = flag; + + return i_ret; +} + +int btif_clock_ctrl(p_mtk_btif p_btif, int en) +{ + int i_ret = 0; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + ENUM_CLOCK_CTRL ctrl_flag = en == 0 ? CLK_OUT_DISABLE : CLK_OUT_ENABLE; + + i_ret = hal_btif_clk_ctrl(p_btif_info, ctrl_flag); + + if (p_btif->rx_mode == BTIF_MODE_DMA) + i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, ctrl_flag); + + if (p_btif->tx_mode == BTIF_MODE_DMA) + i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, ctrl_flag); + + return i_ret; +} + +int _btif_controller_setup(p_mtk_btif p_btif) +{ + int i_ret = -1; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq; + +/*BTIF rx buffer init*/ +/* memset(p_btif->rx_buf, 0, BTIF_RX_BUFFER_SIZE); */ + BBS_INIT(&(p_btif->btif_buf)); +/************************************************/ + hal_btif_rx_cb_reg(p_btif_info, + (btif_rx_buf_write) btif_pio_rx_data_receiver); + + i_ret = hal_btif_clk_ctrl(p_btif_info, CLK_OUT_ENABLE); + if (i_ret) { + BTIF_ERR_FUNC("hal_btif_clk_ctrl failed, i_ret(%d)\n", i_ret); + return i_ret; + } +/*BTIF controller init*/ + i_ret = hal_btif_hw_init(p_btif_info); + if (i_ret) { + hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); + BTIF_ERR_FUNC("hal_btif_hw_init failed, i_ret(%d)\n", i_ret); + return i_ret; + } + _btif_lpbk_ctrl(p_btif, p_btif->lpbk_flag); +/*BTIF IRQ register*/ + i_ret = _btif_irq_reg(p_btif_irq, btif_irq_handler, p_btif); + if (i_ret) { + hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); + + BTIF_ERR_FUNC("_btif_irq_reg failed, i_ret(%d)\n", i_ret); + return i_ret; + } + +/*disable IRQ*/ + _btif_irq_ctrl(p_btif_irq, false); + i_ret = 0; + BTIF_DBG_FUNC("succeed\n"); + return i_ret; +} + +int _btif_controller_free(p_mtk_btif p_btif) +{ +/*No need to set BTIF to PIO mode, only enable BTIF CG*/ + hal_btif_rx_cb_reg(p_btif->p_btif_info, (btif_rx_buf_write) NULL); + _btif_irq_free(p_btif->p_btif_info->p_irq, p_btif); + return hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); +} + +int _btif_init(p_mtk_btif p_btif) +{ + int i_ret = 0; + + i_ret = _btif_controller_setup(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_controller_init failed, i_ret(%d)\n", + i_ret); + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); + BTIF_STATE_RELEASE(p_btif); + return i_ret; + } + + i_ret = _btif_controller_tx_setup(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n", + i_ret); + _btif_controller_free(p_btif); + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); + BTIF_STATE_RELEASE(p_btif); + return i_ret; + } + + i_ret = _btif_controller_rx_setup(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n", + i_ret); + _btif_controller_tx_free(p_btif); + _btif_controller_free(p_btif); + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); + BTIF_STATE_RELEASE(p_btif); + return i_ret; + } + return i_ret; +} + +int btif_open(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif->enable) + return E_BTIF_ALREADY_OPEN; + +/*hold state mechine lock*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; +/*disable deepidle*/ + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE); + + i_ret = _btif_init(p_btif); + if (i_ret == 0) { + /*set BTIF's enable flag*/ + p_btif->enable = true; + _btif_state_set(p_btif, B_S_ON); + } else { + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); + } + btif_log_buf_reset(&p_btif->tx_log); + btif_log_buf_reset(&p_btif->rx_log); + + BTIF_STATE_RELEASE(p_btif); + + BTIF_DBG_FUNC("BTIF's Tx Mode:%d, Rx Mode(%d)\n", + p_btif->tx_mode, p_btif->rx_mode); + return i_ret; +} + +int btif_close(p_mtk_btif p_btif) +{ + int i_ret = 0; + + if (!(p_btif->enable)) + return E_BTIF_NOT_OPEN; + +/*hold state mechine lock*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; +/*always set state back to B_S_ON before do close operation*/ + _btif_exit_dpidle(p_btif); +/*set BTIF's state to disable state*/ + p_btif->enable = false; + + _btif_controller_free(p_btif); + _btif_controller_tx_free(p_btif); + _btif_controller_rx_free(p_btif); + +/*reset BTIF's rx_cb function*/ + p_btif->rx_cb = NULL; + p_btif->rx_notify = NULL; + p_btif->lpbk_flag = false; + +/*set state mechine to B_S_OFF*/ + _btif_state_set(p_btif, B_S_OFF); + + btif_log_buf_disable(&p_btif->tx_log); + btif_log_buf_disable(&p_btif->rx_log); + + BTIF_STATE_RELEASE(p_btif); + + return i_ret; +} + +int _btif_exit_dpidle(p_mtk_btif p_btif) +{ + int i_ret = -1; + ENUM_BTIF_STATE state = B_S_MAX; + + state = _btif_state_get(p_btif); + switch (state) { + case B_S_DPIDLE: + i_ret = _btif_exit_dpidle_from_dpidle(p_btif); + break; + case B_S_SUSPEND: +/*in suspend state, need to do reinit of btif*/ + i_ret = _btif_exit_dpidle_from_sus(p_btif); + break; + case B_S_OFF: + i_ret = _btif_init(p_btif); + break; + case B_S_ON: + i_ret = 0; /* for btif_close case */ + break; + default: + i_ret = E_BTIF_INVAL_PARAM; + BTIF_INFO_FUNC("invalid state change:%d->\n", state, B_S_ON); + break; + } + + if (i_ret == 0) + i_ret = _btif_state_set(p_btif, B_S_ON); + return i_ret; +} + +int btif_exit_dpidle(p_mtk_btif p_btif) +{ + int i_ret = 0; + +/*hold state mechine lock*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + i_ret = _btif_exit_dpidle(p_btif); + BTIF_STATE_RELEASE(p_btif); + return i_ret; +} + +int _btif_enter_dpidle(p_mtk_btif p_btif) +{ + int i_ret = 0; + ENUM_BTIF_STATE state = B_S_MAX; + + state = _btif_state_get(p_btif); + if (state == B_S_ON) { + i_ret = _btif_enter_dpidle_from_on(p_btif); + } else if (state == B_S_SUSPEND) { + /*do reinit and enter deepidle*/ + i_ret = _btif_enter_dpidle_from_sus(p_btif); + } else if (state == B_S_DPIDLE) { + /*do nothing*/ + i_ret = 0; + } else { + BTIF_WARN_FUNC("operation is not allowed, current state:%d\n", + state); + i_ret = E_BTIF_INVAL_STATE; + } +/*anyway, set to B_S_DPIDLE state*/ + if (i_ret == 0) + i_ret = _btif_state_set(p_btif, B_S_DPIDLE); + return i_ret; +} + +int btif_enter_dpidle(p_mtk_btif p_btif) +{ + int i_ret = 0; + +/*hold state mechine lock*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + i_ret = _btif_enter_dpidle(p_btif); + BTIF_STATE_RELEASE(p_btif); + return i_ret; +} + +int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif) +{ + int i_ret = 0; + +/*in dpidle state, only need to open related clock*/ + if (p_btif->tx_mode == BTIF_MODE_DMA) { + /*enable BTIF Tx DMA's clock*/ + i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, + CLK_OUT_ENABLE); + } + if (p_btif->rx_mode == BTIF_MODE_DMA) { + /*enable BTIF Rx DMA's clock*/ + i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, + CLK_OUT_ENABLE); + } +/*enable BTIF's clock*/ + i_ret += hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); + + if (i_ret != 0) + BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret); + return i_ret; +} + +int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif) +{ +/*in suspend state, need to do driver re-init*/ + + int i_ret = _btif_init(p_btif); + + return i_ret; +} + +int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif) +{ +/*do driiver reinit*/ + int i_ret = _btif_init(p_btif); + + if (i_ret == 0) + i_ret = _btif_enter_dpidle_from_on(p_btif); + return i_ret; +} + +int _btif_enter_dpidle_from_on(p_mtk_btif p_btif) +{ +#define MAX_WAIT_TIME_MS 5000 +/* + * this max wait time cannot exceed 12s, + * because dpm will monitor each device's + * resume/suspend process by start up a watch dog timer of 12s + * incase of one driver's suspend/resume process block other device's suspend/resume + */ + int i_ret = 0; + unsigned int retry = 0; + unsigned int wait_period = 1; + unsigned int max_retry = MAX_WAIT_TIME_MS / wait_period; + struct timeval timer_start; + struct timeval timer_now; + + do_gettimeofday(&timer_start); + + while ((!_btif_is_tx_complete(p_btif)) && (retry < max_retry)) { + do_gettimeofday(&timer_now); + if ((MAX_WAIT_TIME_MS/1000) <= (timer_now.tv_sec - timer_start.tv_sec)) { + BTIF_WARN_FUNC("max retry timer expired, timer_start.tv_sec:%d, timer_now.tv_sec:%d,", + "retry:%d\n", timer_start.tv_sec, timer_now.tv_sec, retry); + break; + } + msleep(wait_period); + retry++; + } + + if (retry < max_retry) { + if (p_btif->tx_mode == BTIF_MODE_DMA) { + /*disable BTIF Tx DMA's clock*/ + i_ret += + hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, + CLK_OUT_DISABLE); + } + if (p_btif->rx_mode == BTIF_MODE_DMA) { + /*disable BTIF Rx DMA's clock*/ + i_ret += + hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, + CLK_OUT_DISABLE); + } +/*disable BTIF's clock*/ + i_ret += + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE); + + if (i_ret) + BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret); + } else + i_ret = -1; + + return i_ret; +} + +int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif, ENUM_BTIF_DPIDLE_CTRL en_flag) +{ +/*call WCP's API to control deepidle's enable/disable*/ + if (en_flag == BTIF_DPIDLE_DISABLE) + hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_DIS); + else + hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_EN); + + return 0; +} + +int btif_rx_cb_reg(p_mtk_btif p_btif, MTK_WCN_BTIF_RX_CB rx_cb) +{ + if (p_btif->rx_cb) { + BTIF_WARN_FUNC + ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n", + p_btif->rx_cb, rx_cb); + } + p_btif->rx_cb = rx_cb; + + return 0; +} + +int btif_raise_wak_signal(p_mtk_btif p_btif) +{ + int i_ret = 0; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE); +#endif + + i_ret = hal_btif_raise_wak_sig(p_btif_info); + +#if MTK_BTIF_ENABLE_CLK_REF_COUNTER + hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE); +#endif + return i_ret; +} + +bool _btif_is_tx_complete(p_mtk_btif p_btif) +{ + bool b_ret = false; + ENUM_BTIF_MODE tx_mode = p_btif->tx_mode; + +/* + * make sure BTIF tx finished in PIO mode + * make sure BTIF tx finished and DMA tx finished in DMA mode + */ + if (tx_mode == BTIF_MODE_DMA) { + b_ret = hal_dma_is_tx_complete(p_btif->p_tx_dma->p_dma_info); + if (b_ret == false) { + BTIF_DBG_FUNC("Tx DMA is not finished\n"); + return b_ret; + } + } + + b_ret = hal_btif_is_tx_complete(p_btif->p_btif_info); + if (b_ret == false) { + BTIF_DBG_FUNC("BTIF Tx is not finished\n"); + return b_ret; + } + b_ret = true; + return b_ret; +} + +/*--------------------------------Functions-------------------------------------------*/ + +#if ENABLE_BTIF_TX_DMA +static int _btif_vfifo_init(p_mtk_btif_dma p_dma) +{ + P_DMA_VFIFO p_vfifo = NULL; + struct device *dev = NULL; + p_mtk_btif p_btif = NULL; + + if (p_dma == NULL) { + BTIF_ERR_FUNC("p_dma is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + + p_btif = (p_mtk_btif)p_dma->p_btif; + + if (p_btif == NULL) { + BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif); + return E_BTIF_INVAL_PARAM; + } + + dev = (struct device *)p_btif->private_data; + if (dev == NULL) + BTIF_WARN_FUNC("Null dev pointer!!!!\n"); + + p_vfifo = p_dma->p_dma_info->p_vfifo; + if (p_vfifo->p_vir_addr != NULL) { + BTIF_ERR_FUNC + ("BTIF vFIFO memory already allocated, do nothing\n"); + return E_BTIF_BAD_POINTER; + } + +/*vFIFO memory allocation*/ + p_vfifo->p_vir_addr = dma_zalloc_coherent(dev, + p_vfifo->vfifo_size, + &p_vfifo->phy_addr, GFP_DMA | GFP_DMA32); + if (p_vfifo->p_vir_addr == NULL) { + BTIF_ERR_FUNC("alloc vFIFO memory for BTIF failed\n"); + return E_BTIF_FAIL; + } + + if (sizeof(dma_addr_t) == sizeof(unsigned long long)) + BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch64,vir addr:0x%p,", + "phy addr:0x%llx\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr); + else + BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch32,vir addr:0x%p,", + "phy addr:0x%08x\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr); + + return 0; +} +#endif +#if ENABLE_BTIF_TX_DMA +static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma) +{ + P_DMA_VFIFO p_vfifo = NULL; + struct device *dev = NULL; + p_mtk_btif p_btif = NULL; + + if (p_dma == NULL) { + BTIF_ERR_FUNC("p_dma is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + + + p_btif = (p_mtk_btif)p_dma->p_btif; + if (p_btif == NULL) { + BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif); + return E_BTIF_INVAL_PARAM; + } + + dev = (struct device *)p_btif->private_data; + if (dev == NULL) + BTIF_WARN_FUNC("Null dev pointer!!!!\n"); + + p_vfifo = p_dma->p_dma_info->p_vfifo; + +/*free DMA memory if allocated successfully before*/ + if (p_vfifo->p_vir_addr != NULL) { + dma_free_coherent(dev, + p_vfifo->vfifo_size, + p_vfifo->p_vir_addr, p_vfifo->phy_addr); + p_vfifo->p_vir_addr = NULL; + } + + return 0; +} +#endif + +static int _btif_state_init(p_mtk_btif p_btif) +{ + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + p_btif->state = B_S_OFF; + mutex_init(&(p_btif->state_mtx)); + + return 0; +} + +static int _btif_state_hold(p_mtk_btif p_btif) +{ + return mutex_lock_killable(&(p_btif->state_mtx)); +} + +static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state) +{ +/*chaozhong: To do: need to finished state mechine here*/ + int i_ret = 0; + int ori_state = p_btif->state; + + if (ori_state == state) { + BTIF_INFO_FUNC("already in %s state\n", g_state[state]); + return i_ret; + } + if ((state >= B_S_OFF) && (state < B_S_MAX)) { + BTIF_DBG_FUNC("%s->%s request\n", g_state[ori_state], + g_state[state]); + if (state == B_S_ON) + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE); + switch (ori_state) { + case B_S_ON: +/*B_S_ON can only be switched to B_S_OFF, B_S_SUSPEND and B_S_DPIDLE*/ +/*B_S_ON->B_S_OFF : do nothing here*/ +/* + * B_S_ON->B_S_DPLE : disable clock backup + * BTIF and DMA controller's register if necessary + */ + if (state == B_S_DPIDLE) { + /*clock controlled id done in _btif_enter_dpidle*/ + p_btif->state = state; + i_ret = 0; + } else if (state == B_S_OFF) { + /*clock controlled is done in btif_close*/ + p_btif->state = state; + i_ret = 0; + } else if (state == B_S_SUSPEND) { + /*clock controlled is done in btif_close*/ + p_btif->state = state; + i_ret = 0; + } else { + BTIF_ERR_FUNC("%s->%s is not allowed\n", + g_state[ori_state], + g_state[state]); + i_ret = E_BTIF_INVAL_STATE; + } + break; + case B_S_DPIDLE: +/*B_S_DPIDLE can only be switched to B_S_ON and B_S_SUSPEND*/ +/*B_S_DPIDLE-> B_S_ON: do nothing for this moment*/ +/* + * B_S_DPIDLE-> B_S_SUSPEND: + * disable clock backup BTIF and DMA controller's register if necessary + */ + if (state == B_S_ON) { + /*clock controlled id done in _btif_exit_dpidle*/ + p_btif->state = state; + i_ret = 0; + } else if (state == B_S_SUSPEND) { + /*clock controlled is done in _btif_exit_dpidle*/ + p_btif->state = state; + i_ret = 0; + } else { + BTIF_ERR_FUNC("%s->%s is not allowed\n", + g_state[ori_state], + g_state[state]); + i_ret = E_BTIF_INVAL_STATE; + } + break; + + case B_S_SUSPEND: +/*B_S_SUSPEND can be switched to B_S_IDLE and B_S_ON*/ +/*reinit BTIF controller and DMA controller*/ + if (state == B_S_DPIDLE) { + /* + * system call resume API, do resume operation, + * change to deepidle state + */ + p_btif->state = state; + i_ret = 0; + } else if (state == B_S_ON) { + /* + * when stp want to send data before + * system do resume operation + */ + p_btif->state = state; + i_ret = 0; + } else { + BTIF_ERR_FUNC("%s->%s is not allowed\n", + g_state[ori_state], + g_state[state]); + i_ret = E_BTIF_INVAL_STATE; + } + break; + + case B_S_OFF:{ +/*B_S_OFF can only be switched to B_S_ON*/ + if (state == B_S_ON) { + /*clock controlled is done in btif_open*/ + p_btif->state = state; + i_ret = 0; + } else { + BTIF_ERR_FUNC("%s->%s is not allowed\n", + g_state[ori_state], + g_state[state]); + i_ret = E_BTIF_INVAL_STATE; + } + } + break; + default: +/*no this possibility*/ + BTIF_ERR_FUNC + ("state change request is not allowed, this should never happen\n"); + break; + } + + if (state != B_S_ON) + _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE); + + } else { + i_ret = E_BTIF_INVAL_PARAM; + BTIF_ERR_FUNC("invalid state:%d, do nothing\n", state); + } + return i_ret; +} + +static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif) +{ + return p_btif->state; +} + +static int _btif_state_release(p_mtk_btif p_btif) +{ + int i_ret = 0; + + BTIF_MUTEX_UNLOCK(&(p_btif->state_mtx)); + return i_ret; +} + +static int _btif_state_deinit(p_mtk_btif p_btif) +{ + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + p_btif->state = B_S_OFF; + mutex_destroy(&(p_btif->state_mtx)); + + return 0; +} + +static int btif_rx_data_consummer(p_mtk_btif p_btif) +{ + unsigned int length = 0; + unsigned char *p_buf = NULL; +/*get BTIF rx buffer's information*/ + p_btif_buf_str p_bbs = &(p_btif->btif_buf); +/* + * wr_idx of btif_buf may be modified in IRQ handler, + * in order not to be effected by case in which irq interrupt this operation, + * we record wr_idx here + */ + unsigned int wr_idx = p_bbs->wr_idx; + + length = BBS_COUNT_CUR(p_bbs, wr_idx); + +/*make sure length of rx buffer data > 0*/ + do { + if (length > 0) { + /* + * check if rx_cb empty or not, if registered , + * call user's rx callback to handle these data + */ + if (p_btif->rx_cb) { + if (p_bbs->rd_idx <= wr_idx) { + p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx); + /* p_buf = &(p_bbs->buf[p_bbs->rd_idx]); */ + /* length = BBS_COUNT(p_bbs); */ + length = (wr_idx >= (p_bbs)->rd_idx) ? + (wr_idx - (p_bbs)->rd_idx) : + BBS_SIZE(p_bbs) - + ((p_bbs)->rd_idx - wr_idx); + if (p_btif->rx_cb) + (*(p_btif->rx_cb)) (p_buf, length); + else + BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); + /*update rx data read index*/ + p_bbs->rd_idx = wr_idx; + } else { + unsigned int len_tail = + BBS_SIZE(p_bbs) - (p_bbs)->rd_idx; + /*p_buf = &(p_bbs->buf[p_bbs->->rd_idx]);*/ + p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx); + if (p_btif->rx_cb) + (*(p_btif->rx_cb)) (p_buf, len_tail); + else + BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); + length = BBS_COUNT_CUR(p_bbs, wr_idx); + length -= len_tail; + /*p_buf = &(p_bbs->buf[0]);*/ + p_buf = BBS_PTR(p_bbs, 0); + if (p_btif->rx_cb) + (*(p_btif->rx_cb)) (p_buf, length); + else + BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n"); + /*update rx data read index*/ + p_bbs->rd_idx = wr_idx; + } + } else if (p_btif->rx_notify != NULL) { + (*p_btif->rx_notify) (); + } else { + BTIF_WARN_FUNC + ("p_btif:0x%p, both rx_notify and rx_cb are NULL\n", + p_btif); + break; + } + } else { + BTIF_DBG_FUNC("length:%d\n", length); + break; + } + wr_idx = p_bbs->wr_idx; + length = BBS_COUNT_CUR(p_bbs, wr_idx); + } while (1); + return length; +} + +#if BTIF_RXD_BE_BLOCKED_DETECT +static int mtk_btif_rxd_be_blocked_by_timer(void) +{ + int ret = 0; + int counter = 0; + unsigned int i; + struct timeval now; + int time_gap[MAX_BTIF_RXD_TIME_REC]; + + do_gettimeofday(&now); + + for (i = 0; i < MAX_BTIF_RXD_TIME_REC; i++) { + BTIF_INFO_FUNC("btif_rxd_time_stamp[%d]=%d.%d\n", i, + btif_rxd_time_stamp[i].tv_sec, btif_rxd_time_stamp[i].tv_usec); + if (now.tv_sec >= btif_rxd_time_stamp[i].tv_sec) { + time_gap[i] = now.tv_sec - btif_rxd_time_stamp[i].tv_sec; + time_gap[i] *= 1000000; /*second*/ + if (now.tv_usec >= btif_rxd_time_stamp[i].tv_usec) + time_gap[i] += now.tv_usec - btif_rxd_time_stamp[i].tv_usec; + else + time_gap[i] += 1000000 - now.tv_usec + btif_rxd_time_stamp[i].tv_usec; + + if (time_gap[i] > 1000000) + counter++; + BTIF_INFO_FUNC("time_gap[%d]=%d,counter:%d\n", i, time_gap[i], counter); + } else { + time_gap[i] = 0; + BTIF_ERR_FUNC("abnormal case now:%d < time_stamp[%d]:%d\n", now.tv_sec, + i, btif_rxd_time_stamp[i].tv_usec); + } + } + if (counter > (MAX_BTIF_RXD_TIME_REC - 2)) + ret = 1; + return ret; +} +static int mtk_btif_rxd_be_blocked_by_data(void) +{ + unsigned int out_index = 0; + unsigned int in_index = 0; + unsigned int dump_size = 0; + unsigned int len = 0; + unsigned long flags; + unsigned int sync_pkt_n = 0; + P_BTIF_LOG_BUF_T p_log_buf = NULL; + P_BTIF_LOG_QUEUE_T p_log_que = NULL; + p_mtk_btif p_btif = &(g_btif[0]); + + p_log_que = &p_btif->rx_log; + spin_lock_irqsave(&p_log_que->lock, flags); + in_index = p_log_que->in; + dump_size = p_log_que->size; + out_index = p_log_que->size >= + BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM - + p_log_que->size + + in_index) % BTIF_LOG_ENTRY_NUM; + if (dump_size != 0) { + while (dump_size--) { + p_log_buf = p_log_que->p_queue[0] + out_index; + len = p_log_buf->len; + if (len > BTIF_LOG_SZ) + len = BTIF_LOG_SZ; + if ((0x7f == *(p_log_buf->buffer)) && (0x7f == *(p_log_buf->buffer + 1))) { + sync_pkt_n++; + BTIF_INFO_FUNC("tx pkt_count:%d is sync pkt\n", out_index); + } + out_index++; + out_index %= BTIF_LOG_ENTRY_NUM; + } + } + if (sync_pkt_n == 0) + BTIF_ERR_FUNC("there is no sync pkt in BTIF buffer\n"); + else + BTIF_ERR_FUNC("there are %d sync pkt in BTIF buffer\n", sync_pkt_n); + spin_unlock_irqrestore(&p_log_que->lock, flags); + return sync_pkt_n; +} + +int mtk_btif_rxd_be_blocked_flag_get(void) +{ + int ret = 0; + int condition1 = 0, condition2 = 0; + + condition1 = mtk_btif_rxd_be_blocked_by_timer(); + condition2 = mtk_btif_rxd_be_blocked_by_data(); + if (condition1 && condition2) { + BTIF_ERR_FUNC("btif_rxd thread be blocked too long!\n"); + ret = 1; + } + return ret; +} +#endif +static int btif_rx_thread(void *p_data) +{ +#if BTIF_RXD_BE_BLOCKED_DETECT + unsigned int i = 0; +#endif + p_mtk_btif p_btif = (p_mtk_btif)p_data; + + + while (1) { + wait_for_completion_interruptible(&p_btif->rx_comp); + + if (kthread_should_stop()) { + BTIF_WARN_FUNC("btif rx thread stoping ...\n"); + break; + } +#ifdef BTIF_RXD_BE_BLOCKED_DETECT + do_gettimeofday(&btif_rxd_time_stamp[i]); + i++; + if (i >= MAX_BTIF_RXD_TIME_REC) + i = 0; +#endif + btif_rx_data_consummer(p_btif); + } + return 0; +} + +static void btif_rx_worker(struct work_struct *p_work) +{ +/*get mtk_btif's pointer*/ + p_mtk_btif p_btif = container_of(p_work, mtk_btif, rx_work); + + BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); +/*lock rx_mutex*/ + + if (mutex_lock_killable(&(p_btif->rx_mtx))) { + BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); + return; + } + btif_rx_data_consummer(p_btif); + BTIF_MUTEX_UNLOCK(&(p_btif->rx_mtx)); +} + +static void btif_tx_worker(struct work_struct *p_work) +{ + int i_ret = 0; + int leng_sent = 0; +/*tx fifo out*/ + int how_much_get = 0; + unsigned char local_buf[384]; + +/*get mtk_btif's pointer*/ + p_mtk_btif p_btif = container_of(p_work, mtk_btif, tx_work); + + BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); + + if (mutex_lock_killable(&(p_btif->tx_mtx))) { + BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); + return; + } + how_much_get = + kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf)); + do { + while (leng_sent < how_much_get) { + i_ret = _btif_send_data(p_btif, + local_buf + leng_sent, + how_much_get - leng_sent); + if (i_ret > 0) { + leng_sent += i_ret; + } else if (i_ret == 0) { + BTIF_WARN_FUNC + ("_btif_send_data return 0, retry\n"); + } else { + BTIF_WARN_FUNC + ("btif send data fail,reset tx fifo, i_ret(%d)\n", + i_ret); + kfifo_reset(p_btif->p_tx_fifo); + break; + } + } + how_much_get = + kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf)); + leng_sent = 0; + } while (how_much_get > 0); + BTIF_MUTEX_UNLOCK(&(p_btif->tx_mtx)); +} + +static void btif_rx_tasklet(unsigned long func_data) +{ + unsigned long flags; +/*get mtk_btif's pointer*/ + p_mtk_btif p_btif = (p_mtk_btif) func_data; + + BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif); +/*lock rx_spinlock*/ + spin_lock_irqsave(&p_btif->rx_tasklet_spinlock, flags); + btif_rx_data_consummer(p_btif); + spin_unlock_irqrestore(&p_btif->rx_tasklet_spinlock, flags); +} + +static int _btif_tx_ctx_init(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + + if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { + p_btif->p_tx_wq = create_singlethread_workqueue("btif_txd"); + + if (!(p_btif->p_tx_wq)) { + BTIF_ERR_FUNC + ("create_singlethread_workqueue for tx thread fail\n"); + i_ret = -ENOMEM; + goto btm_init_err; + } + mutex_init(&(p_btif->tx_mtx)); +/* init btif tx work */ + INIT_WORK(&(p_btif->tx_work), btif_tx_worker); + BTIF_INFO_FUNC("btif_tx_worker init succeed\n"); + + p_btif->p_tx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (p_btif->p_tx_fifo == NULL) { + i_ret = -ENOMEM; + BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n"); + goto btm_init_err; + } + + i_ret = kfifo_alloc(p_btif->p_tx_fifo, + BTIF_TX_FIFO_SIZE, GFP_ATOMIC); + if (i_ret != 0) { + BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret); + i_ret = -ENOMEM; + goto btm_init_err; + } + } else if (p_btif->tx_ctx == BTIF_TX_USER_CTX) { + BTIF_INFO_FUNC + ("nothing is done when btif tx in user's thread\n"); + } else { + BTIF_ERR_FUNC("unsupported tx context type:%d\n", + p_btif->tx_ctx); + goto btm_init_err; + } + + BTIF_INFO_FUNC("succeed\n"); + + i_ret = 0; + return i_ret; +btm_init_err: + if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { + if (p_btif->p_tx_wq) { + destroy_workqueue(p_btif->p_tx_wq); + p_btif->p_tx_wq = NULL; + BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n"); + } + kfree(p_btif->p_tx_fifo); + } + return i_ret; +} + +static int _btif_tx_ctx_deinit(p_mtk_btif p_btif) +{ + int i_ret = 0; + + if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { + if (p_btif->p_tx_wq) { + destroy_workqueue(p_btif->p_tx_wq); + p_btif->p_tx_wq = NULL; + BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n"); + } + if (p_btif->p_tx_fifo) { + kfifo_free(p_btif->p_tx_fifo); + kfree(p_btif->p_tx_fifo); + p_btif->p_tx_fifo = NULL; + } + } + return i_ret; +} + +static int _btif_rx_btm_init(p_mtk_btif p_btif) +{ + int i_ret = -1; + + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + + if (p_btif->btm_type == BTIF_THREAD_CTX) { + init_completion(&p_btif->rx_comp); + + /*create kernel thread for later rx data handle*/ + p_btif->p_task = kthread_create(btif_rx_thread, p_btif, "btif_rxd"); + if (p_btif->p_task == NULL) { + BTIF_ERR_FUNC("kthread_create fail\n"); + i_ret = -ENOMEM; + goto btm_init_err; + } + +#if ENABLE_BTIF_RX_THREAD_RT_SCHED + { + int i_ret = -1; + int policy = SCHED_FIFO; + struct sched_param param; + + param.sched_priority = MAX_RT_PRIO - 20; + i_ret = sched_setscheduler(p_btif->p_task, policy, ¶m); + if (i_ret != 0) + BTIF_WARN_FUNC("set RT to btif_rxd workqueue failed\n"); + else + BTIF_INFO_FUNC("set RT to btif_rxd workqueue succeed\n"); + } +#endif + + wake_up_process(p_btif->p_task); + BTIF_INFO_FUNC("btif_rxd start to work!\n"); + } else if (p_btif->btm_type == BTIF_WQ_CTX) { + p_btif->p_rx_wq = create_singlethread_workqueue("btif_rxwq"); + if (!(p_btif->p_rx_wq)) { + BTIF_ERR_FUNC("create_singlethread_workqueue fail\n"); + i_ret = -ENOMEM; + goto btm_init_err; + } + mutex_init(&(p_btif->rx_mtx)); + /* init btif rx work */ + INIT_WORK(&(p_btif->rx_work), btif_rx_worker); + BTIF_INFO_FUNC("btif_rx_worker init succeed\n"); + } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { + /*init rx tasklet*/ + tasklet_init(&(p_btif->rx_tasklet), btif_rx_tasklet, + (unsigned long)p_btif); + spin_lock_init(&(p_btif->rx_tasklet_spinlock)); + BTIF_INFO_FUNC("btif_rx_tasklet init succeed\n"); + } else { + BTIF_ERR_FUNC("unsupported rx context type:%d\n", + p_btif->btm_type); + } + +/*spinlock init*/ + spin_lock_init(&(p_btif->rx_irq_spinlock)); + BTIF_INFO_FUNC("rx_spin_lock init succeed\n"); + + i_ret = 0; + return i_ret; +btm_init_err: + if (p_btif->btm_type == BTIF_THREAD_CTX) { + /*do nothing*/ + BTIF_INFO_FUNC("failed\n"); + } else if (p_btif->btm_type == BTIF_WQ_CTX) { + if (p_btif->p_rx_wq) { + destroy_workqueue(p_btif->p_rx_wq); + p_btif->p_rx_wq = NULL; + BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n"); + } + } + return i_ret; +} + +static int _btif_rx_btm_sched(p_mtk_btif p_btif) +{ + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + + if (p_btif->btm_type == BTIF_THREAD_CTX) { + complete(&p_btif->rx_comp); + BTIF_DBG_FUNC("schedule btif_rx_thread\n"); + } else if (p_btif->btm_type == BTIF_WQ_CTX) { + queue_work(p_btif->p_rx_wq, &(p_btif->rx_work)); + BTIF_DBG_FUNC("schedule btif_rx_worker\n"); + } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { + /*schedule it!*/ + tasklet_schedule(&(p_btif->rx_tasklet)); + BTIF_DBG_FUNC("schedule btif_rx_tasklet\n"); + } else { + BTIF_ERR_FUNC("unsupported rx context type:%d\n", + p_btif->btm_type); + } + + return 0; +} + +static int _btif_rx_btm_deinit(p_mtk_btif p_btif) +{ + if (p_btif == NULL) { + BTIF_ERR_FUNC("p_btif is NULL\n"); + return E_BTIF_INVAL_PARAM; + } + if (p_btif->btm_type == BTIF_THREAD_CTX) { + if (p_btif->p_task != NULL) { + BTIF_INFO_FUNC("signaling btif rx thread to stop ...\n"); + kthread_stop(p_btif->p_task); + } + } else if (p_btif->btm_type == BTIF_WQ_CTX) { + if (p_btif->p_rx_wq) { + cancel_work_sync(&(p_btif->rx_work)); + BTIF_INFO_FUNC("btif_rx_worker cancelled\n"); + destroy_workqueue(p_btif->p_rx_wq); + p_btif->p_rx_wq = NULL; + BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n"); + } + mutex_destroy(&(p_btif->rx_mtx)); + } else if (p_btif->btm_type == BTIF_TASKLET_CTX) { + tasklet_kill(&(p_btif->rx_tasklet)); + BTIF_INFO_FUNC("rx_tasklet killed\n"); + } else { + BTIF_ERR_FUNC("unsupported rx context type:%d\n", + p_btif->btm_type); + } + + spin_lock_init(&(p_btif->rx_irq_spinlock)); + + return 0; +} + + +void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs) +{ + BTIF_INFO_FUNC + ("%s UBS:0x%p\n Size:0x%p\n read:0x%08x\n write:0x%08x\n", + p_str, p_bbs, p_bbs->size, p_bbs->rd_idx, p_bbs->wr_idx); +} + +unsigned int btif_bbs_write(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len) +{ +/*in IRQ context, so read operation won't interrupt this operation*/ + + unsigned int wr_len = 0; + + unsigned int emp_len = BBS_LEFT(p_bbs); + unsigned int ava_len = emp_len - 1; + p_mtk_btif p_btif = container_of(p_bbs, mtk_btif, btif_buf); + + if (ava_len <= 0) { + BTIF_ERR_FUNC + ("no empty space left for write, (%d)ava_len, (%d)to write\n", + ava_len, buf_len); + hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); + hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); + return 0; + } + + if (ava_len < buf_len) { + BTIF_ERR_FUNC("BTIF overrun, (%d)empty, (%d)needed\n", + emp_len, buf_len); + hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); + hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); + _btif_dump_memory("", p_buf, buf_len); + } + + if (buf_len >= g_max_pkg_len) { + BTIF_WARN_FUNC("buf_len too long, (%d)ava_len, (%d)to write\n", + ava_len, buf_len); + hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); + hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); + _btif_dump_memory("", p_buf, buf_len); + } + + wr_len = min(buf_len, ava_len); + btif_bbs_wr_direct(p_bbs, p_buf, wr_len); + + if (BBS_COUNT(p_bbs) >= g_max_pding_data_size) { + BTIF_WARN_FUNC("Rx buf_len too long, size(%d)\n", + BBS_COUNT(p_bbs)); + btif_dump_bbs_str("Rx buffer tooo long", p_bbs); + hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); + hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); + _btif_dump_memory("", p_buf, buf_len); + BBS_INIT(p_bbs); + } + + return wr_len; +} + +unsigned int btif_bbs_read(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len) +{ + unsigned int rd_len = 0; + unsigned int ava_len = 0; + unsigned int wr_idx = p_bbs->wr_idx; + + ava_len = BBS_COUNT_CUR(p_bbs, wr_idx); + if (ava_len >= 4096) { + BTIF_WARN_FUNC("ava_len too long, size(%d)\n", ava_len); + btif_dump_bbs_str("Rx buffer tooo long", p_bbs); + } + if (ava_len != 0) { + if (buf_len >= ava_len) { + rd_len = ava_len; + if (wr_idx >= (p_bbs)->rd_idx) { + memcpy(p_buf, BBS_PTR(p_bbs, + p_bbs->rd_idx), + ava_len); + (p_bbs)->rd_idx = wr_idx; + } else { + unsigned int tail_len = BBS_SIZE(p_bbs) - + (p_bbs)->rd_idx; + memcpy(p_buf, BBS_PTR(p_bbs, + p_bbs->rd_idx), + tail_len); + memcpy(p_buf + tail_len, BBS_PTR(p_bbs, + 0), ava_len - tail_len); + (p_bbs)->rd_idx = wr_idx; + } + } else { + rd_len = buf_len; + if (wr_idx >= (p_bbs)->rd_idx) { + memcpy(p_buf, BBS_PTR(p_bbs, + p_bbs->rd_idx), + rd_len); + (p_bbs)->rd_idx = (p_bbs)->rd_idx + rd_len; + } else { + unsigned int tail_len = BBS_SIZE(p_bbs) - + (p_bbs)->rd_idx; + if (tail_len >= rd_len) { + memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx), + rd_len); + (p_bbs)->rd_idx = + ((p_bbs)->rd_idx + rd_len) & (BBS_MASK(p_bbs)); + } else { + memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx), tail_len); + memcpy(p_buf + tail_len, + (p_bbs)->p_buf, rd_len - tail_len); + (p_bbs)->rd_idx = rd_len - tail_len; + } + } + } + } + mb(); + return rd_len; +} + +unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs, + unsigned char *p_buf, unsigned int buf_len) +{ + unsigned int tail_len = 0; + unsigned int l = 0; + unsigned int tmp_wr_idx = p_bbs->wr_idx; + + tail_len = BBS_SIZE(p_bbs) - (tmp_wr_idx & BBS_MASK(p_bbs)); + + l = min(tail_len, buf_len); + + memcpy((p_bbs->p_buf) + (tmp_wr_idx & BBS_MASK(p_bbs)), p_buf, l); + memcpy(p_bbs->p_buf, p_buf + l, buf_len - l); + + mb(); + + tmp_wr_idx += buf_len; + tmp_wr_idx &= BBS_MASK(p_bbs); + p_bbs->wr_idx = tmp_wr_idx; + + mb(); + return buf_len; +} + +int _btif_dma_write(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len) +{ + unsigned int i_ret = 0; + unsigned int retry = 0; + unsigned int max_tx_retry = 10; + + P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info; + + _btif_irq_ctrl_sync(p_dma_info->p_irq, false); + do { + /*wait until tx is allowed*/ + while (!hal_dma_is_tx_allow(p_dma_info) && + (retry < max_tx_retry)) { + retry++; + if (retry >= max_tx_retry) { + BTIF_ERR_FUNC("wait for tx allowed timeout\n"); + break; + } + } + if (retry >= max_tx_retry) + break; + + if (buf_len <= hal_dma_get_ava_room(p_dma_info)) + i_ret = hal_dma_send_data(p_dma_info, p_buf, buf_len); + else + i_ret = 0; + } while (0); + _btif_irq_ctrl_sync(p_dma_info->p_irq, true); + return i_ret; +} + +int _btif_pio_write(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len) +{ + unsigned int i_ret = 0; + unsigned int sent_len = 0; + unsigned int retry = 0; + unsigned int max_tx_retry = 10; + P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info; + + while ((sent_len < buf_len)) { + if (hal_btif_is_tx_allow(p_btif_info)) { + i_ret = hal_btif_send_data(p_btif_info, + p_buf + sent_len, + buf_len - sent_len); + if (i_ret > 0) { + sent_len += i_ret; + BTIF_DBG_FUNC("lent sent:%d, total sent:%d\n", + i_ret, sent_len); + retry = 0; + } + } + if ((++retry > max_tx_retry) || (i_ret < 0)) { + BTIF_INFO_FUNC("exceed retry times limit :%d\n", retry); + break; + } + } + i_ret = sent_len; + return i_ret; +} + +int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len) +{ + unsigned int idx = 0; + + pr_debug("%s:, length:%d\n", str, buf_len); + for (idx = 0; idx < buf_len;) { + pr_debug("%02x ", p_buf[idx]); + idx++; + if (idx % 8 == 0) + pr_debug("\n"); + } + return 0; +} + +int btif_send_data(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len) +{ + int i_ret = 0; + + if (p_btif->tx_ctx == BTIF_TX_USER_CTX) { + i_ret = _btif_send_data(p_btif, p_buf, buf_len); + } else if (p_btif->tx_ctx == BTIF_TX_SINGLE_CTX) { + int length = 0; +/*tx fifo in*/ + length = kfifo_in(p_btif->p_tx_fifo, + (unsigned char *)p_buf, buf_len); + if (length == buf_len) { + queue_work(p_btif->p_tx_wq, &(p_btif->tx_work)); + BTIF_DBG_FUNC("schedule btif_tx_worker\n"); + i_ret = length; + } else { + i_ret = 0; + BTIF_ERR_FUNC("fifo in failed, target len(%d),in len(%d),", + "don't schedule btif_tx_worker\n", buf_len, length); + } + } else { + BTIF_ERR_FUNC("invalid btif tx context:%d\n", p_btif->tx_ctx); + i_ret = 0; + } + + return i_ret; +} + +int _btif_send_data(p_mtk_btif p_btif, + const unsigned char *p_buf, unsigned int buf_len) +{ + int i_ret = 0; + unsigned int state = 0; + +/*make sure BTIF in ON state before doing tx operation*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + state = _btif_state_get(p_btif); + + if (state != B_S_ON) + i_ret = _btif_exit_dpidle(p_btif); + + if (i_ret != 0) { + i_ret = E_BTIF_INVAL_STATE; + } else if (p_btif->tx_mode == BTIF_MODE_DMA) { + /*_btif_dump_memory("tx data:", p_buf, buf_len);*/ + i_ret = _btif_dma_write(p_btif, p_buf, buf_len); + } else if (p_btif->tx_mode == BTIF_MODE_PIO) { + /*_btif_dump_memory("tx data:", p_buf, buf_len);*/ + i_ret = _btif_pio_write(p_btif, p_buf, buf_len); + } else { + BTIF_ERR_FUNC("invalid tx mode:%d\n", p_btif->tx_mode); + i_ret = 0; + } + +/*save Tx packet here*/ + if (i_ret > 0) + btif_log_buf_dmp_in(&p_btif->tx_log, p_buf, i_ret); + + BTIF_STATE_RELEASE(p_btif); + return i_ret; +} + +int btif_dump_reg(p_mtk_btif p_btif) +{ + int i_ret = 0; + unsigned int ori_state = 0; + +/*make sure BTIF in ON state before doing tx operation*/ + if (_btif_state_hold(p_btif)) + return E_BTIF_INTR; + ori_state = _btif_state_get(p_btif); + + if (ori_state == B_S_OFF) { + i_ret = E_BTIF_INVAL_STATE; + BTIF_ERR_FUNC + ("BTIF in OFF state, ", + "should no need to dump register, ", + "please check wmt's operation is okay or not.\n"); + goto dmp_reg_err; + } + + if ((ori_state != B_S_ON) && (ori_state < B_S_MAX)) { + BTIF_ERR_FUNC("BTIF's original state is %s, not B_S_ON\n", g_state[ori_state]); + BTIF_ERR_FUNC("!!!!---<<>>---!!!"); + i_ret = _btif_exit_dpidle(p_btif); + } + + if (i_ret != 0) { + i_ret = E_BTIF_INVAL_STATE; + BTIF_ERR_FUNC("switch to B_S_ON failed\n"); + goto dmp_reg_err; + } + +/*dump BTIF register*/ + hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL); + +/*dump BTIF Tx DMA channel register if in DMA mode*/ + if (p_btif->tx_mode == BTIF_MODE_DMA) + hal_dma_dump_reg(p_btif->p_tx_dma->p_dma_info, REG_TX_DMA_ALL); + else + BTIF_INFO_FUNC("BTIF Tx in PIO mode,no need to dump Tx DMA's register\n"); + +/*dump BTIF Rx DMA channel register if in DMA mode*/ + if (p_btif->rx_mode == BTIF_MODE_DMA) + hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL); + else + BTIF_INFO_FUNC("BTIF Rx in PIO mode,no need to dump Rx DMA's register\n"); + + switch (ori_state) { + case B_S_SUSPEND: +/*return to dpidle state*/ +/* break; */ + case B_S_DPIDLE: +/*return to dpidle state*/ + _btif_enter_dpidle(p_btif); + break; + case B_S_ON: +/*nothing needs to be done*/ + break; + default: + break; + } + +dmp_reg_err: + + BTIF_STATE_RELEASE(p_btif); + return i_ret; +} + +int btif_rx_notify_reg(p_mtk_btif p_btif, MTK_BTIF_RX_NOTIFY rx_notify) +{ + if (p_btif->rx_notify) { + BTIF_WARN_FUNC + ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n", + p_btif->rx_notify, rx_notify); + } + p_btif->rx_notify = rx_notify; + + return 0; +} + +int btif_dump_data(char *p_buf, int len) +{ + unsigned int idx = 0; + unsigned char str[30]; + unsigned char *p_str; + + p_str = &str[0]; + for (idx = 0; idx < len; idx++, p_buf++) { + sprintf(p_str, "%02x ", *p_buf); + p_str += 3; + if (7 == (idx % 8)) { + *p_str++ = '\n'; + *p_str = '\0'; + pr_debug("%s", str); + p_str = &str[0]; + } + } + if (len % 8) { + *p_str++ = '\n'; + *p_str = '\0'; + pr_debug("%s", str); + } + return 0; +} + +int btif_log_buf_dmp_in(P_BTIF_LOG_QUEUE_T p_log_que, const char *p_buf, + int len) +{ + P_BTIF_LOG_BUF_T p_log_buf = NULL; + char *dir = NULL; + struct timeval *p_timer = NULL; + unsigned long flags; + bool output_flag = false; + + BTIF_DBG_FUNC("++\n"); + + if ((p_log_que == NULL) || (p_buf == NULL) || (len == 0)) { + BTIF_ERR_FUNC("invalid parameter, p_log_que(0x%x), buf(0x%x), ", + "len(%d)\n", p_log_que, p_buf, len); + return 0; + } + if (!(p_log_que->enable)) + return 0; + + dir = p_log_que->dir == BTIF_TX ? "Tx" : "Rx"; + output_flag = p_log_que->output_flag; + + spin_lock_irqsave(&(p_log_que->lock), flags); + +/*get next log buffer for record usage*/ + p_log_buf = p_log_que->p_queue[0] + p_log_que->in; + p_timer = &p_log_buf->timer; + +/*log time stamp*/ + do_gettimeofday(p_timer); + +/*record data information including length and content*/ + p_log_buf->len = len; + memcpy(p_log_buf->buffer, p_buf, len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len); + +/*update log queue size information*/ + p_log_que->size++; + p_log_que->size = p_log_que->size > + BTIF_LOG_ENTRY_NUM ? BTIF_LOG_ENTRY_NUM : p_log_que->size; + +/*update log queue index information*/ + p_log_que->in++; + p_log_que->in %= BTIF_LOG_ENTRY_NUM; + + spin_unlock_irqrestore(&p_log_que->lock, flags); + +/*check if log dynamic output function is enabled or not*/ + if (output_flag) { + pr_debug("BTIF-DBG, dir:%s, %d.%ds len:%d\n", + dir, (int)p_timer->tv_sec, (int)p_timer->tv_usec, len); +/*output buffer content*/ + btif_dump_data((char *)p_buf, len); + } + BTIF_DBG_FUNC("--\n"); + + return 0; +} + +int btif_log_buf_dmp_out(P_BTIF_LOG_QUEUE_T p_log_que) +{ + P_BTIF_LOG_BUF_T p_log_buf = NULL; + unsigned int out_index = 0; + unsigned int in_index = 0; + unsigned int dump_size = 0; + unsigned char *p_buf = NULL; + unsigned int len = 0; + unsigned int pkt_count = 0; + unsigned char *p_dir = NULL; + struct timeval *p_timer = NULL; + unsigned long flags; + +#if 0 /* no matter enable or not, we allowed output */ + if (!(p_log_que->enable)) + return; +#endif + BTIF_DBG_FUNC("++\n"); + + spin_lock_irqsave(&p_log_que->lock, flags); + in_index = p_log_que->in; + dump_size = p_log_que->size; + out_index = p_log_que->size >= + BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM - + p_log_que->size + + in_index) % BTIF_LOG_ENTRY_NUM; + p_dir = p_log_que->dir == BTIF_TX ? "Tx" : "Rx"; + + BTIF_INFO_FUNC("btif %s log buffer size:%d\n", p_dir, dump_size); + + if (dump_size != 0) { + while (dump_size--) { + p_log_buf = p_log_que->p_queue[0] + out_index; + + len = p_log_buf->len; + p_buf = p_log_buf->buffer; + p_timer = &p_log_buf->timer; + + len = len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len; + + BTIF_INFO_FUNC("dir:%s, pkt_count:%d, %d.%ds len:%d\n", + p_dir, + pkt_count++, + (int)p_timer->tv_sec, + (int)p_timer->tv_usec, len); +/*output buffer content*/ + btif_dump_data(p_log_buf->buffer, len); + out_index++; + out_index %= BTIF_LOG_ENTRY_NUM; + } + } + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_DBG_FUNC("--\n"); + + return 0; +} + +int btif_log_buf_enable(P_BTIF_LOG_QUEUE_T p_log_que) +{ + unsigned long flags; + + spin_lock_irqsave(&p_log_que->lock, flags); + p_log_que->enable = true; + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_INFO_FUNC("enable %s log function\n", + p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); + return 0; +} + +int btif_log_buf_disable(P_BTIF_LOG_QUEUE_T p_log_que) +{ + unsigned long flags; + + spin_lock_irqsave(&p_log_que->lock, flags); + p_log_que->enable = false; + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_INFO_FUNC("disable %s log function\n", + p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); + return 0; +} + +int btif_log_output_enable(P_BTIF_LOG_QUEUE_T p_log_que) +{ + unsigned long flags; + + spin_lock_irqsave(&p_log_que->lock, flags); + p_log_que->output_flag = true; + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_INFO_FUNC("%s log rt output enabled\n", + p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); + return 0; +} + +int btif_log_output_disable(P_BTIF_LOG_QUEUE_T p_log_que) +{ + unsigned long flags; + + spin_lock_irqsave(&p_log_que->lock, flags); + p_log_que->output_flag = false; + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_INFO_FUNC("%s log rt output disabled\n", + p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); + return 0; +} + +int btif_log_buf_reset(P_BTIF_LOG_QUEUE_T p_log_que) +{ + unsigned long flags; + + spin_lock_irqsave(&p_log_que->lock, flags); + +/*tx log buffer init*/ + p_log_que->in = 0; + p_log_que->out = 0; + p_log_que->size = 0; + p_log_que->enable = true; + memset((p_log_que->p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); + + spin_unlock_irqrestore(&p_log_que->lock, flags); + BTIF_DBG_FUNC("reset %s log buffer\n", + p_log_que->dir == BTIF_TX ? "Tx" : "Rx"); + return 0; +} + +int btif_log_buf_init(p_mtk_btif p_btif) +{ +/*tx log buffer init*/ + p_btif->tx_log.dir = BTIF_TX; + p_btif->tx_log.in = 0; + p_btif->tx_log.out = 0; + p_btif->tx_log.size = 0; + p_btif->tx_log.output_flag = false; + p_btif->tx_log.enable = true; + spin_lock_init(&(p_btif->tx_log.lock)); + BTIF_DBG_FUNC("tx_log.p_queue:0x%p\n", p_btif->tx_log.p_queue[0]); + memset((p_btif->tx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); + +/*rx log buffer init*/ + p_btif->rx_log.dir = BTIF_RX; + p_btif->rx_log.in = 0; + p_btif->rx_log.out = 0; + p_btif->rx_log.size = 0; + p_btif->rx_log.output_flag = false; + p_btif->rx_log.enable = true; + spin_lock_init(&(p_btif->rx_log.lock)); + BTIF_DBG_FUNC("rx_log.p_queue:0x%p\n", p_btif->rx_log.p_queue[0]); + memset((p_btif->rx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T)); + + return 0; +} + +int btif_tx_dma_mode_set(int en) +{ + int index = 0; + ENUM_BTIF_MODE mode = (en == 1) ? BTIF_MODE_DMA : BTIF_MODE_PIO; + + for (index = 0; index < BTIF_PORT_NR; index++) + g_btif[index].tx_mode = mode; + + return 0; +} + +int btif_rx_dma_mode_set(int en) +{ + int index = 0; + ENUM_BTIF_MODE mode = (en == 1) ? BTIF_MODE_DMA : BTIF_MODE_PIO; + + for (index = 0; index < BTIF_PORT_NR; index++) + g_btif[index].rx_mode = mode; + + return 0; +} + +static int BTIF_init(void) +{ + int i_ret = -1; + int index = 0; + p_mtk_btif_dma p_tx_dma = NULL; + p_mtk_btif_dma p_rx_dma = NULL; + unsigned char *p_btif_buffer = NULL; + unsigned char *p_tx_queue = NULL; + unsigned char *p_rx_queue = NULL; + + BTIF_DBG_FUNC("++\n"); + +/*Platform Driver initialization*/ + i_ret = platform_driver_register(&mtk_btif_dev_drv); + if (i_ret) { + BTIF_ERR_FUNC("BTIF platform driver registered failed, ret(%d)\n", i_ret); + goto err_exit1; + } + + i_ret = driver_create_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); + if (i_ret) + BTIF_ERR_FUNC("BTIF pdriver_create_file failed, ret(%d)\n", i_ret); + +/*SW init*/ + for (index = 0; index < BTIF_PORT_NR; index++) { + p_btif_buffer = kmalloc(BTIF_RX_BUFFER_SIZE, GFP_ATOMIC); + if (!p_btif_buffer) { + BTIF_ERR_FUNC("p_btif_buffer kmalloc memory fail\n"); + return -1; + } + BTIF_INFO_FUNC("p_btif_buffer get memory 0x%p\n", p_btif_buffer); + p_tx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC); + if (!p_tx_queue) { + BTIF_ERR_FUNC("p_tx_queue kmalloc memory fail\n"); + kfree(p_btif_buffer); + return -1; + } + BTIF_INFO_FUNC("p_tx_queue get memory 0x%p\n", p_tx_queue); + p_rx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC); + if (!p_rx_queue) { + BTIF_ERR_FUNC("p_rx_queue kmalloc memory fail\n"); + kfree(p_btif_buffer); + kfree(p_tx_queue); + return -1; + } + BTIF_INFO_FUNC("p_rx_queue get memory 0x%p\n", p_rx_queue); + + INIT_LIST_HEAD(&(g_btif[index].user_list)); + BBS_INIT(&(g_btif[index].btif_buf)); + g_btif[index].enable = false; + g_btif[index].open_counter = 0; + g_btif[index].setting = &g_btif_setting[index]; + g_btif[index].p_btif_info = hal_btif_info_get(); + g_btif[index].tx_mode = g_btif_setting[index].tx_mode; + g_btif[index].rx_mode = g_btif_setting[index].rx_mode; + g_btif[index].btm_type = g_btif_setting[index].rx_type; + g_btif[index].tx_ctx = g_btif_setting[index].tx_type; + g_btif[index].lpbk_flag = false; + g_btif[index].rx_cb = NULL; + g_btif[index].rx_notify = NULL; + g_btif[index].btif_buf.p_buf = p_btif_buffer; + g_btif[index].tx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_tx_queue; + g_btif[index].rx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_rx_queue; + btif_log_buf_init(&g_btif[index]); + +#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) +/*enable BTIF clock gating by default*/ + i_ret = hal_btif_clk_ctrl(g_btif[index].p_btif_info, + CLK_OUT_DISABLE); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF controller CG failed\n"); + goto err_exit2; + } +#endif + +/* + * viftual FIFO memory must be physical continious, + * because DMA will access it directly without MMU + */ +#if ENABLE_BTIF_TX_DMA + p_tx_dma = &g_dma[index][BTIF_TX]; + g_btif[index].p_tx_dma = p_tx_dma; + p_tx_dma->dir = BTIF_TX; + p_tx_dma->p_btif = &(g_btif[index]); + +/*DMA Tx vFIFO initialization*/ + p_tx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_TX); +/*spinlock init*/ + spin_lock_init(&(p_tx_dma->iolock)); +/*entry setup*/ + atomic_set(&(p_tx_dma->entry), 0); +/*vFIFO initialization*/ + i_ret = _btif_vfifo_init(p_tx_dma); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Tx vFIFO allocation failed\n"); + goto err_exit2; + } + +#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) +/*enable BTIF Tx DMA channel's clock gating by default*/ + i_ret = hal_btif_dma_clk_ctrl(p_tx_dma->p_dma_info, + CLK_OUT_DISABLE); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Tx DMA's CG failed\n"); + goto err_exit2; + } +#endif + +#else + g_btif[index].p_tx_dma = NULL; +/*force tx mode to DMA no matter what it is in default setting*/ + g_btif[index].tx_mode = BTIF_MODE_PIO; +#endif + +#if ENABLE_BTIF_RX_DMA + p_rx_dma = &g_dma[index][BTIF_RX]; + g_btif[index].p_rx_dma = p_rx_dma; + p_rx_dma->p_btif = &(g_btif[index]); + p_rx_dma->dir = BTIF_RX; + +/*DMA Tx vFIFO initialization*/ + p_rx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_RX); +/*spinlock init*/ + spin_lock_init(&(p_rx_dma->iolock)); +/*entry setup*/ + atomic_set(&(p_rx_dma->entry), 0); +/*vFIFO initialization*/ + i_ret = _btif_vfifo_init(p_rx_dma); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Rx vFIFO allocation failed\n"); + goto err_exit2; + } + +#if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER) +/*enable BTIF Tx DMA channel's clock gating by default*/ + i_ret = hal_btif_dma_clk_ctrl(p_rx_dma->p_dma_info, + CLK_OUT_DISABLE); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Rx DMA's CG failed\n"); + goto err_exit2; + } +#endif + +#else + g_btif[index].p_rx_dma = NULL; +/*force rx mode to DMA no matter what it is in default setting*/ + g_btif[index].rx_mode = BTIF_MODE_PIO; + +#endif +/*PM state mechine initialization*/ + i_ret = _btif_state_init(&(g_btif[index])); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF state mechanism init failed\n"); + goto err_exit2; + } + +/*Rx bottom half initialization*/ + i_ret = _btif_rx_btm_init(&(g_btif[index])); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Rx btm init failed\n"); + goto err_exit3; + } + i_ret = _btif_tx_ctx_init(&(g_btif[index])); + if (i_ret != 0) { + BTIF_ERR_FUNC("BTIF Tx context init failed\n"); + goto err_exit4; + } +/*Character Device initialization*/ +/*Chaozhong: ToDo: to be initialized*/ + + mutex_init(&g_btif[index].ops_mtx); + } + +/*Debug purpose initialization*/ + +#if BTIF_CDEV_SUPPORT + btif_chrdev_init(); +#endif + + return 0; + +err_exit4: + for (index = 0; index < BTIF_PORT_NR; index++) + _btif_tx_ctx_deinit(&(g_btif[index])); + +err_exit3: + for (index = 0; index < BTIF_PORT_NR; index++) { + _btif_rx_btm_deinit(&(g_btif[index])); + + _btif_state_deinit(&(g_btif[index])); + } + +err_exit2: + for (index = 0; index < BTIF_PORT_NR; index++) { + p_tx_dma = &g_dma[index][BTIF_TX]; + p_rx_dma = &g_dma[index][BTIF_RX]; +#if ENABLE_BTIF_TX_DMA + _btif_vfifo_deinit(p_tx_dma); +#endif + +#if ENABLE_BTIF_RX_DMA + _btif_vfifo_deinit(p_rx_dma); +#endif + g_btif[index].open_counter = 0; + g_btif[index].enable = false; + } + driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); + platform_driver_unregister(&mtk_btif_dev_drv); + +err_exit1: + i_ret = -1; + BTIF_DBG_FUNC("--\n"); + return i_ret; +} + +static void BTIF_exit(void) +{ + unsigned int index = 0; + p_mtk_btif_dma p_tx_dma = NULL; + p_mtk_btif_dma p_rx_dma = NULL; + + BTIF_DBG_FUNC("++\n"); + + for (index = 0; index < BTIF_PORT_NR; index++) { + g_btif[index].open_counter = 0; + g_btif[index].enable = false; + p_tx_dma = &g_dma[index][BTIF_TX]; + p_rx_dma = &g_dma[index][BTIF_RX]; +#if ENABLE_BTIF_TX_DMA + _btif_vfifo_deinit(p_tx_dma); +#endif + +#if ENABLE_BTIF_RX_DMA + _btif_vfifo_deinit(p_rx_dma); +#endif + _btif_state_deinit(&(g_btif[index])); + + _btif_rx_btm_deinit(&(g_btif[index])); + + mutex_destroy(&g_btif[index].ops_mtx); + } + +#if !defined(CONFIG_MTK_CLKMGR) + hal_btif_clk_unprepare(); +#endif + + driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag); + platform_driver_unregister(&mtk_btif_dev_drv); + BTIF_DBG_FUNC("--\n"); +} + +int mtk_btif_hal_get_log_lvl(void) +{ + return mtk_btif_dbg_lvl; +} + +void mtk_btif_read_cpu_sw_rst_debug(void) +{ + mtk_btif_read_cpu_sw_rst_debug_plat(); +} + +/*---------------------------------------------------------------------------*/ + +module_init(BTIF_init); +module_exit(BTIF_exit); + +/*---------------------------------------------------------------------------*/ + +MODULE_AUTHOR("MBJ/WCN/SE/SS1/Chaozhong.Liang"); +MODULE_DESCRIPTION("MTK BTIF Driver$1.0$"); +MODULE_LICENSE("GPL"); + +/*---------------------------------------------------------------------------*/ diff --git a/drivers/misc/mediatek/btif/common/mtk_btif_exp.c b/drivers/misc/mediatek/btif/common/mtk_btif_exp.c new file mode 100644 index 0000000000000..c0df44558357b --- /dev/null +++ b/drivers/misc/mediatek/btif/common/mtk_btif_exp.c @@ -0,0 +1,786 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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. + */ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "MTK-BTIF-EXP" + +/*#include "mtk_btif_exp.h"*/ +#include "mtk_btif.h" + +/*---------------------------------Function----------------------------------*/ + +p_mtk_btif btif_exp_srh_id(unsigned long u_id) +{ + int index = 0; + p_mtk_btif p_btif = NULL; + struct list_head *p_list = NULL; + struct list_head *tmp = NULL; + p_mtk_btif_user p_user = NULL; + + for (index = 0; (index < BTIF_PORT_NR) && (p_btif == NULL); index++) { + p_list = &(g_btif[index].user_list); + list_for_each(tmp, p_list) { + p_user = container_of(tmp, mtk_btif_user, entry); + if (u_id == p_user->u_id) { + p_btif = p_user->p_btif; + BTIF_DBG_FUNC + ("BTIF's user id(0x%p), p_btif(0x%p)\n", + p_user->u_id, p_btif); + break; + } + } + } + if (p_btif == NULL) { + BTIF_INFO_FUNC + ("no btif structure found for BTIF's user id(0x%lx)\n", + u_id); + } + return p_btif; +} + +/*-----Normal Mode API declearation-------*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_open +* DESCRIPTION +* open BTIF interface, will do BTIF module HW and SW initialization +* PARAMETERS +* p_owner [IN] pointer to owner who call this API, +* currently there are 2 owner ("stp" or "btif_tester") +* may use this module +* for "stp", BTIF will call rx callback function to route rx data to STP module +* for "stp_tester", BTIF will save rx data and wait for native process to access +* p_id [IN] BTIF's user id will be put to this address +* RETURNS +* int 0 = BTIF module initialization fail; negative = BTIF module initialization success +* if open success, value p_id will be the only identifier +* for user to access BTIF's other operations +* including read/write/dpidle_ctrl/rx_cb_retister +* this user id is only an identifier used for owner identification +*****************************************************************************/ +int mtk_wcn_btif_open(char *p_owner, unsigned long *p_id) +{ + int i_ret = -1; + unsigned int index = 0; + p_mtk_btif_user p_new_user = NULL; + p_mtk_btif p_btif = &g_btif[index]; + struct list_head *p_user_list = &(p_btif->user_list); + + BTIF_DBG_FUNC("++"); + BTIF_DBG_FUNC("p_btif(0x%p)\n", p_btif); + + if (mutex_lock_killable(&(p_btif->ops_mtx))) { + BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); + return E_BTIF_INTR; + } + if ((p_owner == NULL) || (p_id == NULL)) { + if (p_id) + *p_id = 0; + BTIF_ERR_FUNC("parameter invalid, p_owner(0x%p), p_id(0x%p)\n", + p_owner, p_id); + BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); + return E_BTIF_INVAL_PARAM; + } + +/*check if btif is already opened or not, if yes, just return fail*/ + if (!list_empty(p_user_list)) { + struct list_head *pos; + p_mtk_btif_user p_user; + + BTIF_ERR_FUNC("BTIF's user list is not empty\n"); + list_for_each(pos, p_user_list) { + p_user = container_of(pos, mtk_btif_user, entry); + BTIF_INFO_FUNC("BTIF's user id(0x%lx), name(%s)\n", + p_user->u_id, p_user->u_name); + } +/*leave p_id alone*/ + BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); + return E_BTIF_ALREADY_OPEN; + } + p_new_user = vmalloc(sizeof(mtk_btif_user)); + + if (p_new_user != NULL) { + INIT_LIST_HEAD(&(p_new_user->entry)); + p_new_user->enable = false; + p_new_user->p_btif = p_btif; + p_new_user->u_id = (unsigned long)p_new_user; + strncpy(p_new_user->u_name, p_owner, sizeof(p_new_user->u_name) - 1); + p_new_user->u_name[sizeof(p_new_user->u_name) - 1] = '\0'; + BTIF_DBG_FUNC("owner name:%s, recorded name:%s\n", + p_owner, p_new_user->u_name); + + i_ret = btif_open(p_btif); + if (i_ret) { + BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); + *p_id = 0; +/*free btif new user's structure*/ + vfree(p_new_user); + p_new_user = NULL; + } else { + BTIF_INFO_FUNC("btif_open succeed\n"); + *p_id = p_new_user->u_id; +/*mark enable flag to true*/ + p_new_user->enable = true; +/*add to uer lsit*/ + list_add_tail(&(p_new_user->entry), p_user_list); + } + } else { + *p_id = 0; + i_ret = -ENOMEM; + BTIF_ERR_FUNC("allocate memory for mtk_btif_user failed\n"); + } + BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); + BTIF_DBG_FUNC("--"); + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_open); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_close +* DESCRIPTION +* close BTIF interface, will do BTIF module HW and SW de-initialization +* once this API is called, p_btif should never be used by BTIF's user again +* PARAMETERS +* u_id [IN] BTIF's user id +* RETURNS +* int 0 = succeed; +* others = fail, +* for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_close(unsigned long u_id) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + struct list_head *pos = NULL; + struct list_head *p_user_list = NULL; + + BTIF_DBG_FUNC("++"); + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + + if (mutex_lock_killable(&(p_btif->ops_mtx))) { + BTIF_ERR_FUNC("mutex_lock_killable return failed\n"); + return E_BTIF_INTR; + } + p_user_list = &(p_btif->user_list); + list_for_each(pos, p_user_list) { + p_mtk_btif_user p_user = + container_of(pos, mtk_btif_user, entry); + + if (p_user->u_id == u_id) { + BTIF_INFO_FUNC + ("user who's id is 0x%lx deleted from user list\n", + u_id); + list_del(pos); + vfree(p_user); + i_ret = btif_close(p_btif); + if (i_ret) + BTIF_WARN_FUNC("BTIF close failed"); + break; + } + } + BTIF_MUTEX_UNLOCK(&(p_btif->ops_mtx)); + BTIF_DBG_FUNC("--"); + return 0; +} +EXPORT_SYMBOL(mtk_wcn_btif_close); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_write +* DESCRIPTION +* send data throuth BTIF module +* there's no internal buffer to cache STP data in BTIF driver, +* if in DMA mode +* btif driver will check if there's enough space in vFIFO for data to send in DMA mode +* if yes, put data to vFIFO and return corresponding data length to caller +* if no, corresponding error code will be returned to called +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* p_buf [IN] pointer to target data to send +* len [IN] data length (should be less than 2014 bytes per STP package) +* +* if in non-DMA mode, BTIF driver will try to write to THR of BTIF controller +* if btif driver detected that no space is available in Tx FIFO, +* will return E_BTIF_NO_SPACE, mostly something is wrong with BTIF or +* consys when this return value is returned +* RETURNS +* int positive: data length send through BTIF; +* negative: please see ENUM_BTIF_OP_ERROR_CODE +* E_BTIF_AGAIN (0) will be returned to caller +* if btif does not have enough vFIFO to send data, +* when caller get 0, he should wait for a moment +* (5~10ms maybe) and try a few times (maybe 10~20) +* if still get E_BTIF_AGAIN, +* should call BTIF's debug API and dump BTIF driver +* and BTIF/DMA register information to kernel log for debug +* E_BTIF_BAD_POINTER will be returned to caller +* if btif is not opened successfully before call this API +* E_BTIF_INVAL_PARAM will be returned if parameter is not valid + +*****************************************************************************/ +int mtk_wcn_btif_write(unsigned long u_id, + const unsigned char *p_buf, unsigned int len) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + BTIF_DBG_FUNC("++"); + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + if (p_buf == NULL) { + BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); + return E_BTIF_INVAL_PARAM; + } + if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { + BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); + return E_BTIF_INVAL_PARAM; + } + + i_ret = btif_send_data(p_btif, p_buf, len); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_write); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_read +* DESCRIPTION +* read data from BTIF module +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* p_buf [IN/OUT] pointer to buffer where rx data will be put +* max_len [IN] max buffer length +* RETURNS +* int positive: data length read from BTIF; +* negative: please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_read(unsigned long u_id, + unsigned char *p_buf, unsigned int max_len) +{ + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_dpidle_ctrl +* DESCRIPTION +* control if BTIF module allow system enter deepidle state or not +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* en_flag [IN] one of ENUM_BTIF_DPIDLE_CTRL +* RETURNS +* int always return 0 +*****************************************************************************/ +int mtk_wcn_btif_dpidle_ctrl(unsigned long u_id, ENUM_BTIF_DPIDLE_CTRL en_flag) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + + if (en_flag == BTIF_DPIDLE_DISABLE) + i_ret = btif_exit_dpidle(p_btif); + else + i_ret = btif_enter_dpidle(p_btif); + + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_dpidle_ctrl); + + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_rx_cb_register +* DESCRIPTION +* register rx callback function to BTIF module by btif user +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* rx_cb [IN] pointer to stp rx handler callback function, +* should be comply with MTK_WCN_BTIF_RX_CB +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, +* please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_rx_cb_register(unsigned long u_id, MTK_WCN_BTIF_RX_CB rx_cb) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + + i_ret = btif_rx_cb_reg(p_btif, rx_cb); + + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_rx_cb_register); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_wakeup_consys +* DESCRIPTION +* once sleep command is sent to con sys, +* should call this API before send wakeup command +* to make con sys aware host want to send data to consys +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* RETURNS +* int 0 = succeed; others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_wakeup_consys(unsigned long u_id) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + +/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ + i_ret = btif_raise_wak_signal(p_btif); + + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_wakeup_consys); + + +/***************End of Normal Mode API declearation**********/ + +/***************Debug Purpose API declearation**********/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_loopback_ctrl +* DESCRIPTION +* enable/disable BTIF internal loopback function, +* when this function is enabled data send to btif +* will be received by btif itself +* only for debug purpose, should never use this function in normal mode +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* enable [IN] loopback mode control flag, enable or disable, +* shou be one of ENUM_BTIF_LPBK_MODE +* RETURNS +* int 0 = succeed; +* others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_loopback_ctrl(unsigned long u_id, ENUM_BTIF_LPBK_MODE enable) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + i_ret = + btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); + + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_loopback_ctrl); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_btif_logger_ctrl +* DESCRIPTION +* control BTIF logger function's behavior +* PARAMETERS +* p_btif [IN] pointer returned by mtk_wcn_btif_open +* flag [IN] should be one of ENUM_BTIF_DBG_ID +* BTIF_DISABLE_LOGGER - disable btif logger +* BTIF_ENABLE_LOGGER - enable btif logger +* BTIF_DUMP_LOG - dump log logged by btif +* BTIF_CLR_LOG - clear btif log buffer +* BTIF_DUMP_BTIF_REG - dump btif controller's register +* BTIF_DUMP_DMA_REG - dump DMA controller's register +* RETURNS +* int 0 = succeed; others = fail, for detailed information, please see ENUM_BTIF_OP_ERROR_CODE +*****************************************************************************/ +int mtk_wcn_btif_dbg_ctrl(unsigned long u_id, ENUM_BTIF_DBG_ID flag) +{ + int i_ret = -1; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + + i_ret = 0; + switch (flag) { + case BTIF_DISABLE_LOGGER:{ + BTIF_INFO_FUNC + ("disable btif log function for both Tx and Rx\n"); + btif_log_buf_disable(&p_btif->tx_log); + btif_log_buf_disable(&p_btif->rx_log); + } + break; + case BTIF_ENABLE_LOGGER:{ + BTIF_INFO_FUNC + ("enable btif log function for both Tx and Rx\n"); + btif_log_buf_enable(&p_btif->tx_log); + btif_log_buf_enable(&p_btif->rx_log); + } + break; + case BTIF_DUMP_LOG:{ + BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); + btif_log_buf_dmp_out(&p_btif->tx_log); + btif_log_buf_dmp_out(&p_btif->rx_log); + } + break; + + case BTIF_CLR_LOG:{ + BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); + btif_log_buf_reset(&p_btif->tx_log); + btif_log_buf_reset(&p_btif->rx_log); + } + break; + case BTIF_DUMP_BTIF_REG: + /*TBD*/ btif_dump_reg(p_btif); + break; + case BTIF_ENABLE_RT_LOG: + BTIF_INFO_FUNC + ("enable btif real time log for both Tx and Rx\n"); + btif_log_output_enable(&p_btif->tx_log); + btif_log_output_enable(&p_btif->rx_log); + break; + case BTIF_DISABLE_RT_LOG: + BTIF_INFO_FUNC + ("disable btif real time log for both Tx and Rx\n"); + btif_log_output_disable(&p_btif->tx_log); + btif_log_output_disable(&p_btif->rx_log); + break; + default: + BTIF_INFO_FUNC("not supported flag:%d\n", flag); + i_ret = -2; + break; + } + + return i_ret; +} +EXPORT_SYMBOL(mtk_wcn_btif_dbg_ctrl); + +bool mtk_wcn_btif_parser_wmt_evt(unsigned long u_id, + const char *sub_str, unsigned int str_len) +{ + bool b_ret = false; + p_mtk_btif p_btif = NULL; + + p_btif = btif_exp_srh_id(u_id); + + if (p_btif == NULL) + return E_BTIF_INVAL_PARAM; + b_ret = btif_parser_wmt_evt(p_btif, sub_str, str_len); + BTIF_INFO_FUNC("parser wmt evt %s\n", b_ret ? "ok" : "fail"); + + return b_ret; +} + +/**********End of Debug Purpose API declearation**********/ + +int btif_open_no_id(void) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = btif_open(p_btif); + + if (i_ret) + BTIF_ERR_FUNC("btif_open failed, i_ret(%d)\n", i_ret); + else + BTIF_INFO_FUNC("btif_open succeed\n"); + + return i_ret; +} + +int btif_close_no_id(void) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = btif_close(p_btif); + + if (i_ret) + BTIF_ERR_FUNC("btif_close failed, i_ret(%d)\n", i_ret); + else + BTIF_INFO_FUNC("btif_close succeed\n"); + return i_ret; +} + +int btif_write_no_id(const unsigned char *p_buf, unsigned int len) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + + BTIF_DBG_FUNC("++"); + + if (p_buf == NULL) { + BTIF_ERR_FUNC("invalid p_buf (0x%p)\n", p_buf); + return E_BTIF_INVAL_PARAM; + } + if ((len == 0) || (len > BTIF_MAX_LEN_PER_PKT)) { + BTIF_ERR_FUNC("invalid buffer length(%d)\n", len); + return E_BTIF_INVAL_PARAM; + } + + i_ret = btif_send_data(p_btif, p_buf, len); + BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret); + return i_ret; +} + +int btif_dpidle_ctrl_no_id(ENUM_BTIF_DPIDLE_CTRL en_flag) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + + if (en_flag == BTIF_DPIDLE_DISABLE) + i_ret = btif_exit_dpidle(p_btif); + else + i_ret = btif_enter_dpidle(p_btif); + + return i_ret; +} + +int btif_wakeup_consys_no_id(void) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + +/*i_ret = hal_btif_raise_wak_sig(p_btif->p_btif_info);*/ + i_ret = btif_raise_wak_signal(p_btif); + + return i_ret; +} + +int btif_loopback_ctrl_no_id(ENUM_BTIF_LPBK_MODE enable) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = + btif_lpbk_ctrl(p_btif, enable == BTIF_LPBK_ENABLE ? true : false); + + return i_ret; +} + +int btif_dbg_ctrl_no_id(ENUM_BTIF_DBG_ID flag) +{ + int i_ret = -1; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = 0; + switch (flag) { + case BTIF_DISABLE_LOGGER:{ + BTIF_INFO_FUNC + ("disable btif log function for both Tx and Rx\n"); + btif_log_buf_disable(&p_btif->tx_log); + btif_log_buf_disable(&p_btif->rx_log); + } + break; + case BTIF_ENABLE_LOGGER:{ + BTIF_INFO_FUNC + ("enable btif log function for both Tx and Rx\n"); + btif_log_buf_enable(&p_btif->tx_log); + btif_log_buf_enable(&p_btif->rx_log); + } + break; + case BTIF_DUMP_LOG:{ + BTIF_INFO_FUNC("dump btif log for both Tx and Rx\n"); + btif_log_buf_dmp_out(&p_btif->tx_log); + btif_log_buf_dmp_out(&p_btif->rx_log); + } + break; + + case BTIF_CLR_LOG:{ + BTIF_INFO_FUNC("clear btif log for both Tx and Rx\n"); + btif_log_buf_reset(&p_btif->tx_log); + btif_log_buf_reset(&p_btif->rx_log); + } + break; + case BTIF_DUMP_BTIF_REG: + /*TBD*/ btif_dump_reg(p_btif); + break; + case BTIF_ENABLE_RT_LOG: + BTIF_INFO_FUNC + ("enable btif real time log for both Tx and Rx\n"); + btif_log_output_enable(&p_btif->tx_log); + btif_log_output_enable(&p_btif->rx_log); + break; + case BTIF_DISABLE_RT_LOG: + BTIF_INFO_FUNC + ("disable btif real time log for both Tx and Rx\n"); + btif_log_output_disable(&p_btif->tx_log); + btif_log_output_disable(&p_btif->rx_log); + break; + default: + BTIF_INFO_FUNC("not supported flag:%d\n", flag); + i_ret = -2; + break; + } + + return i_ret; +} + +int mtk_btif_exp_open_test(void) +{ + int i_ret = 0; + + i_ret = btif_open_no_id(); + if (i_ret < 0) { + BTIF_INFO_FUNC("mtk_wcn_btif_open failed\n"); + return -1; + } + + BTIF_INFO_FUNC("mtk_wcn_btif_open succeed\n"); + + return i_ret; +} + +int mtk_btif_exp_close_test(void) +{ + int i_ret = 0; + + i_ret = btif_close_no_id(); + if (i_ret < 0) { + BTIF_INFO_FUNC("mtk_wcn_btif_close failed\n"); + return -1; + } + + BTIF_INFO_FUNC("mtk_wcn_btif_close succeed\n"); + + return i_ret; +} + +int mtk_btif_exp_write_test(void) +{ + return mtk_btif_exp_write_stress_test(100, 10); +} + +int mtk_btif_exp_write_stress_test(unsigned int length, unsigned int max_loop) +{ +#define BUF_LEN 1024 + int i_ret = 0; + int idx = 0; + int buf_len = length > BUF_LEN ? BUF_LEN : length; + int loop = max_loop > 1000000 ? 1000000 : max_loop; + unsigned char *buffer; + + buffer = kmalloc(BUF_LEN, GFP_KERNEL); + if (!buffer) { + BTIF_ERR_FUNC("btif tester kmalloc failed\n"); + return -1; + } + + for (idx = 0; idx < buf_len; idx++) + /* btif_stress_test_buf[idx] = BUF_LEN -idx; */ + *(buffer + idx) = idx % 255; + i_ret = btif_loopback_ctrl_no_id(BTIF_LPBK_ENABLE); + BTIF_INFO_FUNC("mtk_wcn_btif_loopback_ctrl returned %d\n", i_ret); + while (loop--) { + i_ret = btif_write_no_id(buffer, buf_len); + BTIF_INFO_FUNC("mtk_wcn_btif_write left loop:%d, i_ret:%d\n", + loop, i_ret); + if (i_ret != buf_len) { + BTIF_INFO_FUNC + ("mtk_wcn_btif_write failed, target len %d, sent len: %d\n", + buf_len, i_ret); + break; + } + buf_len--; + if (buf_len <= 0) + buf_len = length > BUF_LEN ? BUF_LEN : length; + } + kfree(buffer); + return i_ret; +} + +int mtk_btif_exp_suspend_test(void) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = _btif_suspend(p_btif); + return i_ret; +} + +int mtk_btif_exp_restore_noirq_test(void) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = _btif_restore_noirq(p_btif); + return i_ret; +} + +int mtk_btif_exp_clock_ctrl(int en) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = btif_clock_ctrl(p_btif, en); + return i_ret; +} + +int mtk_btif_exp_resume_test(void) +{ + int i_ret = 0; + p_mtk_btif p_btif = &g_btif[0]; + + i_ret = _btif_resume(p_btif); + return i_ret; +} + +int mtk_btif_exp_enter_dpidle_test(void) +{ + return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_ENABLE); +} + +int mtk_btif_exp_exit_dpidle_test(void) +{ + return btif_dpidle_ctrl_no_id(BTIF_DPIDLE_DISABLE); +} + +int mtk_btif_exp_log_debug_test(int flag) +{ + int i_ret = 0; + + i_ret = btif_dbg_ctrl_no_id(flag); + return i_ret; +} + +void mtk_btif_read_cpu_sw_rst_debug_exp(void) +{ + mtk_btif_read_cpu_sw_rst_debug(); +} + +/************End of Function**********/ diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h new file mode 100644 index 0000000000000..97756f684ab40 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_priv.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __HAL_BTIF_DMA_H_ +#define __HAL_BTIF_DMA_H_ + +#include +#include "btif_dma_pub.h" + +#if defined(CONFIG_MTK_CLKMGR) +#if defined(CONFIG_ARCH_MT6580) +#define MTK_BTIF_APDMA_CLK_CG MT_CG_APDMA_SW_CG +#elif defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753) +#define MTK_BTIF_APDMA_CLK_CG MT_CG_PERI_APDMA +#endif +#else +extern struct clk *clk_btif_apdma; /*btif apdma clock*/ +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +#define TX_DMA_VFF_SIZE (1024 * 8) /*Tx vFIFO Len must be 8 Byte allignment */ +#define RX_DMA_VFF_SIZE (1024 * 8) /*Rx vFIFO Len must be 8 Byte allignment */ + +#define DMA_TX_THRE(n) (n - 7) /*Tx Trigger Level */ +#define DMA_RX_THRE(n) ((n) * 3 / 4) /*Rx Trigger Level */ + +/**********************************Hardware related defination**************************/ +#ifndef CONFIG_OF +/*DMA channel's offset refer to AP_DMA's base address*/ +#define BTIF_TX_DMA_OFFSET 0x880 +#define BTIF_RX_DMA_OFFSET 0x900 +#endif + +/*Register Address Mapping*/ +#define DMA_INT_FLAG_OFFSET 0x00 +#define DMA_INT_EN_OFFSET 0x04 +#define DMA_EN_OFFSET 0x08 +#define DMA_RST_OFFSET 0x0C +#define DMA_STOP_OFFSET 0x10 +#define DMA_FLUSH_OFFSET 0x14 + +#define DMA_BASE_OFFSET 0x1C +#define DMA_LEN_OFFSET 0x24 + +#define DMA_THRE_OFFSET 0x28 +#define DMA_WPT_OFFSET 0x2C +#define DMA_RPT_OFFSET 0x30 +#define DMA_VALID_OFFSET 0x3C +#define DMA_LEFT_OFFSET 0x40 +#define DMA_VFF_BIT29_OFFSET 0x01 + +#define TX_DMA_INT_FLAG(base) (unsigned long)(base + 0x0) /*BTIF Tx Virtual FIFO Interrupt Flag Register */ +#define TX_DMA_INT_EN(base) (unsigned long)(base + 0x4) /*BTIF Tx Virtual FIFO Interrupt Enable Register */ +#define TX_DMA_EN(base) (unsigned long)(base + DMA_EN_OFFSET)/*BTIF Tx Virtual FIFO Enable Register */ +#define TX_DMA_RST(base) (unsigned long)(base + DMA_RST_OFFSET)/*BTIF Tx Virtual FIFO Reset Register */ +#define TX_DMA_STOP(base) (unsigned long)(base + DMA_STOP_OFFSET)/*BTIF Tx Virtual FIFO STOP Register */ +#define TX_DMA_FLUSH(base) (unsigned long)(base + DMA_FLUSH_OFFSET)/*BTIF Tx Virtual FIFO Flush Register */ +#define TX_DMA_VFF_ADDR(base) (unsigned long)(base + 0x1C) /*BTIF Tx Virtual FIFO Base Address Register */ +#define TX_DMA_VFF_LEN(base) (unsigned long)(base + 0x24) /*BTIF Tx Virtual FIFO Length Register */ +#define TX_DMA_VFF_THRE(base) (unsigned long)(base + 0x28) /*BTIF Tx Virtual FIFO Threshold Register */ +#define TX_DMA_VFF_WPT(base) (unsigned long)(base + 0x2C) /*BTIF Tx Virtual FIFO Write Pointer Register */ +#define TX_DMA_VFF_RPT(base) (unsigned long)(base + 0x30) /*BTIF Tx Virtual FIFO Read Pointer Register */ +#define TX_DMA_W_INT_BUF_SIZE(base) (unsigned long)(base + 0x34) +/*BTIF Tx Virtual FIFO Internal Tx Write Buffer Size Register */ +#define TX_DMA_INT_BUF_SIZE(base) (unsigned long)(base + 0x38) +/*BTIF Tx Virtual FIFO Internal Tx Buffer Size Register */ + +#define TX_DMA_VFF_VALID_SIZE(base) (unsigned long)(base + 0x3C) /*BTIF Tx Virtual FIFO Valid Size Register */ +#define TX_DMA_VFF_LEFT_SIZE(base) (unsigned long)(base + 0x40) /*BTIF Tx Virtual FIFO Left Size Register */ +#define TX_DMA_DEBUG_STATUS(base) (unsigned long)(base + 0x50) /*BTIF Tx Virtual FIFO Debug Status Register */ +#define TX_DMA_VFF_ADDR_H(base) (unsigned long)(base + 0x54) /*BTIF Tx Virtual FIFO Base High Address Register */ + +/*Rx Register Address Mapping*/ +#define RX_DMA_INT_FLAG(base) (unsigned long)(base + 0x0) /*BTIF Rx Virtual FIFO Interrupt Flag Register */ +#define RX_DMA_INT_EN(base) (unsigned long)(base + 0x4) /*BTIF Rx Virtual FIFO Interrupt Enable Register */ +#define RX_DMA_EN(base) (unsigned long)(base + DMA_EN_OFFSET) /*BTIF Rx Virtual FIFO Enable Register */ +#define RX_DMA_RST(base) (unsigned long)(base + DMA_RST_OFFSET) /*BTIF Rx Virtual FIFO Reset Register */ +#define RX_DMA_STOP(base) (unsigned long)(base + DMA_STOP_OFFSET) /*BTIF Rx Virtual FIFO Stop Register */ +#define RX_DMA_FLUSH(base) (unsigned long)(base + DMA_FLUSH_OFFSET) /*BTIF Rx Virtual FIFO Flush Register */ +#define RX_DMA_VFF_ADDR(base) (unsigned long)(base + 0x1C) /*BTIF Rx Virtual FIFO Base Address Register */ +#define RX_DMA_VFF_LEN(base) (unsigned long)(base + 0x24) /*BTIF Rx Virtual FIFO Length Register */ +#define RX_DMA_VFF_THRE(base) (unsigned long)(base + 0x28) /*BTIF Rx Virtual FIFO Threshold Register */ +#define RX_DMA_VFF_WPT(base) (unsigned long)(base + 0x2C) /*BTIF Rx Virtual FIFO Write Pointer Register */ +#define RX_DMA_VFF_RPT(base) (unsigned long)(base + 0x30) /*BTIF Rx Virtual FIFO Read Pointer Register */ +#define RX_DMA_FLOW_CTRL_THRE(base) (unsigned long)(base + 0x34) /*BTIF Rx Virtual FIFO Flow Control Register */ +#define RX_DMA_INT_BUF_SIZE(base) (unsigned long)(base + 0x38) /*BTIF Rx Virtual FIFO Internal Buffer Register */ +#define RX_DMA_VFF_VALID_SIZE(base) (unsigned long)(base + 0x3C) /*BTIF Rx Virtual FIFO Valid Size Register */ +#define RX_DMA_VFF_LEFT_SIZE(base) (unsigned long)(base + 0x40) /*BTIF Rx Virtual FIFO Left Size Register */ +#define RX_DMA_DEBUG_STATUS(base) (unsigned long)(base + 0x50) /*BTIF Rx Virtual FIFO Debug Status Register */ +#define RX_DMA_VFF_ADDR_H(base) (unsigned long)(base + 0x54) /*BTIF Rx Virtual FIFO Base High Address Register */ + +#define DMA_EN_BIT (0x1) +#define DMA_STOP_BIT (0x1) +#define DMA_RST_BIT (0x1) +#define DMA_FLUSH_BIT (0x1) + +#define DMA_WARM_RST (0x1 << 0) +#define DMA_HARD_RST (0x1 << 1) + +#define DMA_WPT_MASK (0x0000FFFF) +#define DMA_WPT_WRAP (0x00010000) + +#define DMA_RPT_MASK (0x0000FFFF) +#define DMA_RPT_WRAP (0x00010000) + +/*APDMA BTIF Tx Reg Ctrl Bit*/ +#define TX_DMA_INT_FLAG_MASK (0x1) + +#define TX_DMA_INTEN_BIT (0x1) + +#define TX_DMA_ADDR_MASK (0xFFFFFFF8) +#define TX_DMA_LEN_MASK (0x0000FFF8) + +#define TX_DMA_THRE_MASK (0x0000FFFF) + +#define TX_DMA_W_INT_BUF_MASK (0x000000FF) + +#define TX_DMA_VFF_VALID_MASK (0x0000FFFF) +#define TX_DMA_VFF_LEFT_MASK (0x0000FFFF) + +/*APDMA BTIF Rx Reg Ctrl Bit*/ +#define RX_DMA_INT_THRE (0x1 << 0) +#define RX_DMA_INT_DONE (0x1 << 1) + +#define RX_DMA_INT_THRE_EN (0x1 << 0) +#define RX_DMA_INT_DONE_EN (0x1 << 1) + +#define RX_DMA_ADDR_MASK (0xFFFFFFF8) +#define RX_DMA_LEN_MASK (0x0000FFF8) + +#define RX_DMA_THRE_MASK (0x0000FFFF) + +#define RX_DMA_FLOW_CTRL_THRE_MASK (0x000000FF) + +#define RX_DMA_INT_BUF_SIZE_MASK (0x0000001F) + +#define RX_DMA_VFF_VALID_MASK (0x0000001F) + +#define RX_DMA_VFF_LEFT_MASK (0x0000FFFF) + +typedef struct _MTK_BTIF_DMA_VFIFO_ { + DMA_VFIFO vfifo; + unsigned int wpt; /*DMA's write pointer, which is maintained by SW for Tx DMA and HW for Rx DMA */ + unsigned int last_wpt_wrap; /*last wrap bit for wpt */ + unsigned int rpt; /*DMA's read pointer, which is maintained by HW for Tx DMA and SW for Rx DMA */ + unsigned int last_rpt_wrap; /*last wrap bit for rpt */ +} MTK_BTIF_DMA_VFIFO, *P_MTK_BTIF_DMA_VFIFO; + +/*for DMA debug purpose*/ +typedef struct _MTK_BTIF_DMA_REG_DMP_DBG_ { + unsigned long reg_addr; + unsigned int reg_val; +} MTK_BTIF_DMA_REG_DMP_DBG, *P_MTK_BTIF_DMA_REG_DMP_DBG; + +#endif /*__HAL_BTIF_DMA_H_*/ diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h new file mode 100644 index 0000000000000..0773f2ce387ac --- /dev/null +++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_dma_pub.h @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __HAL_BTIFD_DMA_PUB_H_ +#define __HAL_BTIFD_DMA_PUB_H_ + +#include + +#include "plat_common.h" + +typedef enum _ENUM_DMA_CTRL_ { + DMA_CTRL_DISABLE = 0, + DMA_CTRL_ENABLE = DMA_CTRL_DISABLE + 1, + DMA_CTRL_BOTH, +} ENUM_DMA_CTRL; + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_info_get +* DESCRIPTION +* get btif tx dma channel's information +* PARAMETERS +* dma_dir [IN] DMA's direction +* RETURNS +* pointer to btif dma's information structure +*****************************************************************************/ +P_MTK_DMA_INFO_STR hal_btif_dma_info_get(ENUM_DMA_DIR dma_dir); + +/***************************************************************************** +* FUNCTION +* hal_btif_dma_hw_init +* DESCRIPTION +* control clock output enable/disable of DMA module +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dma_hw_init(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_btif_clk_ctrl +* DESCRIPTION +* control clock output enable/disable of DMA module +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dma_clk_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_CLOCK_CTRL flag); + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_ctrl +* DESCRIPTION +* enable/disable Tx DMA channel +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* ctrl_id [IN] enable/disable ID +* dma_dir [IN] DMA's direction +* RETURNS +* 0 means success; negative means fail +*****************************************************************************/ +int hal_btif_dma_ctrl(P_MTK_DMA_INFO_STR p_dma_info, ENUM_DMA_CTRL ctrl_id); + +/***************************************************************************** +* FUNCTION +* hal_btif_dma_rx_cb_reg +* DESCRIPTION +* register rx callback function to dma module +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* rx_cb [IN] function pointer to btif +* RETURNS +* 0 means success; negative means fail +*****************************************************************************/ +int hal_btif_dma_rx_cb_reg(P_MTK_DMA_INFO_STR p_dma_info, + dma_rx_buf_write rx_cb); + +/***************************************************************************** +* FUNCTION +* hal_tx_vfifo_reset +* DESCRIPTION +* reset tx virtual fifo information, except memory information +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* dma_dir [IN] DMA's direction +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_vfifo_reset(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_tx_dma_irq_handler +* DESCRIPTION +* lower level tx interrupt handler +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_tx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_dma_send_data +* DESCRIPTION +* send data through btif in DMA mode +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN] pointer to rx data buffer +* max_len [IN] tx buffer length +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_dma_send_data(P_MTK_DMA_INFO_STR p_dma_info, + const unsigned char *p_buf, const unsigned int buf_len); + +/***************************************************************************** +* FUNCTION +* hal_dma_is_tx_complete +* DESCRIPTION +* get tx complete flag +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* true means tx complete, false means tx in process +*****************************************************************************/ +bool hal_dma_is_tx_complete(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_dma_get_ava_room +* DESCRIPTION +* get tx available room +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* available room size +*****************************************************************************/ +int hal_dma_get_ava_room(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_dma_is_tx_allow +* DESCRIPTION +* is tx operation allowed by DMA +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* RETURNS +* true if tx operation is allowed; false if tx is not allowed +*****************************************************************************/ +bool hal_dma_is_tx_allow(P_MTK_DMA_INFO_STR p_dma_info); + +/***************************************************************************** +* FUNCTION +* hal_rx_dma_irq_handler +* DESCRIPTION +* lower level rx interrupt handler +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_rx_dma_irq_handler(P_MTK_DMA_INFO_STR p_dma_info, + unsigned char *p_buf, const unsigned int max_len); + +/***************************************************************************** +* FUNCTION +* hal_dma_dump_reg +* DESCRIPTION +* dump BTIF module's information when needed +* PARAMETERS +* p_dma_info [IN] pointer to BTIF dma channel's information +* flag [IN] register id flag +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_dma_dump_reg(P_MTK_DMA_INFO_STR p_dma_info, ENUM_BTIF_REG_ID flag); + +int hal_dma_pm_ops(P_MTK_DMA_INFO_STR p_dma_info, MTK_BTIF_PM_OPID opid); + +#endif /*__HAL_BTIFD_DMA_PUB_H_*/ diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h new file mode 100644 index 0000000000000..51fe58a82b49c --- /dev/null +++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_priv.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __HAL_BTIF_H_ +#define __HAL_BTIF_H_ + +#ifndef CONFIG_OF +#define MTK_BTIF_REG_BASE BTIF_BASE +#endif + +#if defined(CONFIG_MTK_CLKMGR) +#if defined(CONFIG_ARCH_MT6580) +#define MTK_BTIF_CG_BIT MT_CG_BTIF_SW_CG +#elif defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || defined(CONFIG_ARCH_MT6753) +#define MTK_BTIF_CG_BIT MT_CG_PERI_BTIF +#endif +#else +struct clk *clk_btif_apdma; /*btif apdma clock*/ +struct clk *clk_btif; /*btif clock*/ +#endif /* !defined(CONFIG_MTK_CLKMGR) */ + +#define BTIF_RBR(base) (unsigned long)(base + 0x0) /*RX Buffer Register: read only */ +#define BTIF_THR(base) (unsigned long)(base + 0x0) /*Rx Holding Register: write only */ +#define BTIF_IER(base) (unsigned long)(base + 0x4) /*Interrupt Enable Register: read/write */ +#define BTIF_IIR(base) (unsigned long)(base + 0x8) /*Interrupt Identification Register: read only */ +#define BTIF_FIFOCTRL(base) (unsigned long)(base + 0x8) /*FIFO Control Register: write only */ +#define BTIF_FAKELCR(base) (unsigned long)(base + 0xC) /*FAKE LCR Register: read/write */ +#define BTIF_LSR(base) (unsigned long)(base + 0x14) /*Line Status Register: read only */ +#define BTIF_SLEEP_EN(base) (unsigned long)(base + 0x48) /*Sleep Enable Register: read/write */ +#define BTIF_DMA_EN(base) (unsigned long)(base + 0x4C) /*DMA Enable Register: read/write */ +#define BTIF_RTOCNT(base) (unsigned long)(base + 0x54) /*Rx Timeout Count Register: read/write */ +#define BTIF_TRI_LVL(base) (unsigned long)(base + 0x60) /*Tx/Rx Trigger Level Control Register: read/write */ +#define BTIF_WAK(base) (unsigned long)(base + 0x64) /*BTIF module wakeup Register: write only */ +#define BTIF_WAT_TIME(base) (unsigned long)(base + 0x68) /*BTIF ASYNC Wait Time Control Register: read/write */ +#define BTIF_HANDSHAKE(base) (unsigned long)(base + 0x6C) /*BTIF New Handshake Control Register: read/write */ + +/*BTIF_IER bits*/ +#define BTIF_IER_TXEEN (0x1 << 1) /*1: Tx holding register is empty */ +#define BTIF_IER_RXFEN (0x1 << 0) /*1: Rx buffer contains data */ + +/*BTIF_IIR bits*/ +#define BTIF_IIR_NINT (0x1 << 0) /*No INT Pending */ +#define BTIF_IIR_TX_EMPTY (0x1 << 1) /*Tx Holding Register empty */ +#define BTIF_IIR_RX (0x1 << 2) /*Rx data received */ +#define BTIF_IIR_RX_TIMEOUT (0x11 << 2) /*Rx data received */ + +/*BTIF_LSR bits*/ +#define BTIF_LSR_DR_BIT (0x1 << 0) +#define BTIF_LSR_THRE_BIT (0x1 << 5) +#define BTIF_LSR_TEMT_BIT (0x1 << 6) + +/*BTIF_FIFOCTRL bits*/ +#define BTIF_FIFOCTRL_CLR_TX (0x1 << 2) /*Clear Tx FIRO */ +#define BTIF_FIFOCTRL_CLR_RX (0x1 << 1) /*Clear Rx FIRO */ + +/*BTIF_FAKELCR bits*/ +#define BTIF_FAKELCR_NORMAL_MODE 0x0 + +/*BTIF_SLEEP_EN bits*/ +#define BTIF_SLEEP_EN_BIT (0x1 << 0) /*enable Sleep mode */ +#define BTIF_SLEEP_DIS_BIT (0x0) /*disable sleep mode */ + +/*BTIF_DMA_EN bits*/ +#define BTIF_DMA_EN_RX (0x1 << 0) /*Enable Rx DMA */ +#define BTIF_DMA_EN_TX (0x1 << 1) /*Enable Tx DMA */ +#define BTIF_DMA_EN_AUTORST_EN (0x1 << 2) /*1: timeout counter will be auto reset */ +#define BTIF_DMA_EN_AUTORST_DIS (0x0 << 2) /* + * 0: after Rx timeout happens, + * SW shall reset the interrupt by reading BTIF 0x4C + */ + +/*BTIF_TRI_LVL bits*/ +#define BTIF_TRI_LVL_TX_MASK ((0xf) << 0) +#define BTIF_TRI_LVL_RX_MASK ((0x7) << 4) + +#define BTIF_TRI_LVL_TX(x) ((x & 0xf) << 0) +#define BTIF_TRI_LVL_RX(x) ((x & 0x7) << 4) + +#define BTIF_TRI_LOOP_EN (0x1 << 7) +#define BTIF_TRI_LOOP_DIS (0x0 << 7) + +/*BTIF_WAK bits*/ +#define BTIF_WAK_BIT (0x1 << 0) + +/*BTIF_HANDSHAKE bits*/ +#define BTIF_HANDSHAKE_EN_HANDSHAKE 1 +#define BTIF_HANDSHAKE_DIS_HANDSHAKE 0 + +#define BTIF_TX_FIFO_SIZE 16 +#define BTIF_RX_FIFO_SIZE 8 + +#define BTIF_TX_FIFO_THRE (BTIF_TX_FIFO_SIZE / 2) +#define BTIF_RX_FIFO_THRE 0x1 /* 0x5 */ + +#endif /*__HAL_BTIF_H_*/ diff --git a/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h b/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h new file mode 100644 index 0000000000000..1555d5a50c384 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/plat_inc/btif_pub.h @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __HAL_BTIF_PUB_H_ +#define __HAL_BTIF_PUB_H_ + +#include "plat_common.h" + +/*Enum Defination*/ +/*BTIF Mode Enum */ +typedef enum _ENUM_BTIF_MODE_ { + BTIF_MODE_PIO = 0, + BTIF_MODE_DMA = BTIF_MODE_PIO + 1, + BTIF_MODE_MAX, +} ENUM_BTIF_MODE; + +/***************************************************************************** +* FUNCTION +* hal_btif_info_get +* DESCRIPTION +* get btif's information included base address , irq related information +* PARAMETERS +* RETURNS +* BTIF's information +*****************************************************************************/ +P_MTK_BTIF_INFO_STR hal_btif_info_get(void); + +#if 0 /*included in hal_btif_info_get */ +/***************************************************************************** +* FUNCTION +* hal_btif_get_irq +* DESCRIPTION +* get BTIF module's IRQ information +* PARAMETERS +* RETURNS +* pointer to BTIF's irq structure +*****************************************************************************/ +P_MTK_BTIF_IRQ_STR hal_btif_get_irq(void); +#endif + +#if !defined(CONFIG_MTK_CLKMGR) +/***************************************************************************** +* FUNCTION +* hal_btif_clk_get_and_prepare +* DESCRIPTION +* get clock from device tree and prepare for enable/disable control +* PARAMETERS +* pdev device pointer +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_clk_get_and_prepare(struct platform_device *pdev); +/***************************************************************************** +* FUNCTION +* hal_btif_clk_unprepare +* DESCRIPTION +* unprepare btif clock and apdma clock +* PARAMETERS +* none +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_clk_unprepare(void); +#endif +/***************************************************************************** +* FUNCTION +* hal_btif_clk_ctrl +* DESCRIPTION +* control clock output enable/disable of BTIF module +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_clk_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_CLOCK_CTRL flag); + +/***************************************************************************** +* FUNCTION +* hal_btif_hw_init +* DESCRIPTION +* BTIF module init, after this step, BTIF should enable to do tx/rx with PIO +* mode +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_hw_init(P_MTK_BTIF_INFO_STR p_btif); + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_cb_reg +* DESCRIPTION +* BTIF rx callback register API +* PARAMETERS +* p_btif_info [IN] pointer to BTIF's information +* rx_cb [IN] rx callback function +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_rx_cb_reg(P_MTK_BTIF_INFO_STR p_btif_info, + btif_rx_buf_write rx_cb); + +/***************************************************************************** +* FUNCTION +* hal_btif_loopback_ctrl +* DESCRIPTION +* BTIF Tx/Rx loopback mode set, this operation can only be done +* after set BTIF to normal mode +* PARAMETERS +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_loopback_ctrl(P_MTK_BTIF_INFO_STR p_btif, bool en); + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_handler +* DESCRIPTION +* lower level interrupt handler +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN/OUT] pointer to rx data buffer +* max_len [IN] max length of rx buffer +* RETURNS +* 0 means success; negative means fail; positive means rx data length +*****************************************************************************/ +int hal_btif_irq_handler(P_MTK_BTIF_INFO_STR p_btif, + unsigned char *p_buf, const unsigned int max_len); + +/***************************************************************************** +* FUNCTION +* hal_btif_tx_mode_ctrl +* DESCRIPTION +* set BTIF tx to corresponding mode (PIO/DMA) +* PARAMETERS +* p_base [IN] BTIF module's base address +* mode [IN] rx mode +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_tx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode); + +/***************************************************************************** +* FUNCTION +* hal_btif_rx_mode_ctrl +* DESCRIPTION +* set BTIF rx to corresponding mode (PIO/DMA) +* PARAMETERS +* p_base [IN] BTIF module's base address +* mode [IN] rx mode +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_rx_mode_ctrl(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_MODE mode); + +/***************************************************************************** +* FUNCTION +* hal_btif_send_data +* DESCRIPTION +* send data through btif in FIFO mode +* PARAMETERS +* p_base [IN] BTIF module's base address +* p_buf [IN] pointer to rx data buffer +* max_len [IN] tx buffer length +* RETURNS +* positive means number of data sent; +* 0 means no data put to FIFO; +* negative means error happens +*****************************************************************************/ +int hal_btif_send_data(P_MTK_BTIF_INFO_STR p_btif, + const unsigned char *p_buf, const unsigned int buf_len); + +/***************************************************************************** +* FUNCTION +* hal_btif_raise_wak_sig +* DESCRIPTION +* raise wakeup signal to counterpart +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_raise_wak_sig(P_MTK_BTIF_INFO_STR p_btif); + +/***************************************************************************** +* FUNCTION +* hal_btif_dump_reg +* DESCRIPTION +* dump BTIF module's information when needed +* PARAMETERS +* p_base [IN] BTIF module's base address +* flag [IN] register id flag +* RETURNS +* 0 means success, negative means fail +*****************************************************************************/ +int hal_btif_dump_reg(P_MTK_BTIF_INFO_STR p_btif, ENUM_BTIF_REG_ID flag); + +/***************************************************************************** +* FUNCTION +* hal_btif_is_tx_complete +* DESCRIPTION +* get tx complete flag +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* true means tx complete, false means tx in process +*****************************************************************************/ +bool hal_btif_is_tx_complete(P_MTK_BTIF_INFO_STR p_btif); + +/***************************************************************************** +* FUNCTION +* hal_btif_is_tx_allow +* DESCRIPTION +* whether tx is allowed +* PARAMETERS +* p_base [IN] BTIF module's base address +* RETURNS +* true if tx operation is allowed; false if tx is not allowed +*****************************************************************************/ +bool hal_btif_is_tx_allow(P_MTK_BTIF_INFO_STR p_btif); + +int hal_btif_pm_ops(P_MTK_BTIF_INFO_STR p_btif, MTK_BTIF_PM_OPID opid); + +void mtk_btif_read_cpu_sw_rst_debug_plat(void); + +#endif /*__HAL_BTIF_PUB_H_*/ diff --git a/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h b/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h new file mode 100644 index 0000000000000..2a1462cb32ff4 --- /dev/null +++ b/drivers/misc/mediatek/btif/common/plat_inc/plat_common.h @@ -0,0 +1,307 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __HAL_PUB_H_ +#define __HAL_PUB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_OF +#include +#include +#include +#else +#include +#include +#endif +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ +#include + +extern int mtk_btif_hal_get_log_lvl(void); + +#define MTK_BTIF_MARK_UNUSED_API + +typedef irq_handler_t mtk_btif_irq_handler; + +#define MTK_BTIF_ENABLE_CLK_CTL 1 +#define MTK_BTIF_ENABLE_CLK_REF_COUNTER 1 + +#define DBG_LOG_STR_SIZE 256 + +/*Log defination*/ +static int hal_log_print(const char *str, ...) +{ + va_list args; + char temp_sring[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(temp_sring, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + pr_err("%s", temp_sring); + + return 0; +} + +#define BTIF_LOG_LOUD 4 +#define BTIF_LOG_DBG 3 +#define BTIF_LOG_INFO 2 +#define BTIF_LOG_WARN 1 +#define BTIF_LOG_ERR 0 + +#ifndef DFT_TAG +#define DFT_TAG "[BTIF-DFT]" +#endif + +#define BTIF_LOUD_FUNC(fmt, arg ...) \ +do { \ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_LOUD) \ + hal_log_print(DFT_TAG "[L]%s:" fmt, \ + __func__, ## arg); \ +} while (0) + +#define BTIF_INFO_FUNC(fmt, arg ...) \ +do { \ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_INFO)\ + hal_log_print(DFT_TAG "[I]%s:" fmt, \ + __func__, ## arg); \ +} while (0) + +#define BTIF_WARN_FUNC(fmt, arg ...) \ +do { \ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_WARN)\ + hal_log_print(DFT_TAG "[W]%s:" fmt, \ + __func__, ## arg); \ +} while (0) + +#define BTIF_ERR_FUNC(fmt, arg ...)\ +do {\ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_ERR)\ + hal_log_print(DFT_TAG "[E]%s(%d):" fmt,\ + __func__, __LINE__, ## arg);\ +} while (0) + +#define BTIF_DBG_FUNC(fmt, arg ...) \ +do { \ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_DBG) \ + hal_log_print(DFT_TAG "[D]%s:" fmt, \ + __func__, ## arg); \ +} while (0) + +#define BTIF_TRC_FUNC(f) \ +do { \ + if (mtk_btif_hal_get_log_lvl() >= BTIF_LOG_DBG) \ + hal_log_print(DFT_TAG "<%s> <%d>\n", \ + __func__, __LINE__); \ +} while (0) + +/*-----------------------------------Enum Defination--------------------------------*/ +/*IRQ sensetive type */ +typedef enum _ENUM_IRQ_SENS_TYPE_ { + IRQ_SENS_EDGE = 0, + IRQ_SENS_LVL = IRQ_SENS_EDGE + 1, + IRQ_SENS_TYPE_MAX +} ENUM_IRQ_SENS_TYPE; + +/*IRQ level trigger type */ +typedef enum _ENUM_IRQ_LVL_TYPE_ { + IRQ_LVL_LOW = 0, + IRQ_LVL_HIGH = IRQ_LVL_LOW + 1, + IRQ_LVL_MAX +} ENUM_IRQ_LVL; + +/*IRQ edge trigger type */ +typedef enum _ENUM_IRQ_EDGE_TYPE_ { + IRQ_EDGE_FALL = 0, + IRQ_EDGE_RAISE = IRQ_EDGE_FALL + 1, + IRQ_EDGE_BOTH = IRQ_EDGE_RAISE + 1, + IRQ_EDGE_MAX +} ENUM_IRQ_EDGE; + +typedef enum _ENUM_CLOCK_CTRL_ { + CLK_OUT_DISABLE = 0, + CLK_OUT_ENABLE = CLK_OUT_DISABLE + 1, + CLK_OUT_MAX +} ENUM_CLOCK_CTRL; + +/*Error No. table */ +typedef enum _ENUM_ERROR_CODE_ { + ERR_NO_ERROR = 0, + ERR_INVALID_PAR = ERR_NO_ERROR - 1, + ERR_MAX = ERR_INVALID_PAR - 1, +} ENUM_ERROR_CODE; + +typedef enum _ENUM_BTIF_DIR_ { + BTIF_TX = 0, + BTIF_RX = BTIF_TX + 1, + BTIF_DIR_MAX, +} ENUM_BTIF_DIR; + +typedef enum _ENUM_DMA_DIR_ { + DMA_DIR_RX = 0, + DMA_DIR_TX = DMA_DIR_RX + 1, + DMA_DIR_BOTH, +} ENUM_DMA_DIR; + +typedef enum _ENUM_BTIF_REG_ID_ { + REG_IIR = 0, /*Interrupt Identification Register */ + REG_LSR = 1, /*Line Status Register */ + REG_FAKE_LCR = 2, /*Fake Lcr Regiseter */ + REG_FIFO_CTRL = 3, /*FIFO Control Register */ + REG_IER = 4, /*Interrupt Enable Register */ + REG_SLEEP_EN = 5, /*Sleep Enable Register */ + REG_RTO_COUNTER = 6, /*Rx Timeout Counter Register */ + REG_DMA_EN = 7, /*DMA Enalbe Register */ + REG_TRIG_LVL = 8, /*Tx/Rx Trigger Level Register */ + REG_WAT_TIME = 9, /*Async Wait Time Register */ + REG_HANDSHAKE = 10, /*New HandShake Mode Register */ + REG_SLP_WAK = 11, /*Sleep Wakeup Reigster */ + REG_BTIF_ALL = 12, /*all btif controller's registers */ + REG_TX_DMA_ALL = 13, + REG_RX_DMA_ALL = 14, + REG_MAX +} ENUM_BTIF_REG_ID; + +typedef enum _MTK_BTIF_PM_OPID_ { + BTIF_PM_DPIDLE_EN, + BTIF_PM_DPIDLE_DIS, + BTIF_PM_SUSPEND, + BTIF_PM_RESUME, + BTIF_PM_RESTORE_NOIRQ, +} MTK_BTIF_PM_OPID; + +#define BTIF_HAL_TX_FIFO_SIZE (1024 * 4) + +/*-----------------------------------Enum Defination End--------------------------------*/ + +/*****************************structure definition***************************/ +/*IRQ related information*/ +typedef struct _MTK_BTIF_IRQ_STR_ { + const char *name; + bool is_irq_sup; + unsigned int irq_id; +#ifdef CONFIG_OF + unsigned int irq_flags; +#else + ENUM_IRQ_SENS_TYPE sens_type; + union { + ENUM_IRQ_LVL lvl_type; + ENUM_IRQ_EDGE edge_type; + }; +#endif + bool reg_flag; + irq_handler_t p_irq_handler; +} MTK_BTIF_IRQ_STR, *P_MTK_BTIF_IRQ_STR; + +typedef struct _DMA_VFIFO_ { + /*[Driver Access] vFIFO memory'svirtual address */ + unsigned char *p_vir_addr; + /*[HW Access] dma handle , physically address, set to DMA's HW Register */ + dma_addr_t phy_addr; + /*DMA's vFIFO size */ + unsigned int vfifo_size; + /*DMA's threshold value */ + unsigned int thre; +} DMA_VFIFO, *P_DMA_VFIFO; + +typedef unsigned int (*dma_rx_buf_write) (void *p_dma_info, + unsigned char *p_buf, + unsigned int buf_len); +typedef unsigned int (*btif_rx_buf_write) (void *p_btif_info, + unsigned char *p_buf, + unsigned int buf_len); + +/*DMA related information*/ +typedef struct _MTK_DMA_INFO_STR_ { + unsigned long base; + ENUM_DMA_DIR dir; + P_MTK_BTIF_IRQ_STR p_irq; + dma_rx_buf_write rx_cb; + P_DMA_VFIFO p_vfifo; +} MTK_DMA_INFO_STR, *P_MTK_DMA_INFO_STR; + +/*DMA related information*/ +typedef struct _MTK_BTIF_INFO_STR_ { + unsigned long base; /*base address */ + P_MTK_BTIF_IRQ_STR p_irq; /*irq related information */ + + unsigned int tx_fifo_size; /*BTIF tx FIFO size */ + unsigned int rx_fifo_size; /*BTIF rx FIFO size */ + + unsigned int tx_tri_lvl; /*BTIFtx trigger level in FIFO mode */ + unsigned int rx_tri_lvl; /*BTIFrx trigger level in FIFO mode */ + + unsigned int clk_gat_addr; /*clock gating address */ + unsigned int set_bit; /*enable clock gating bit */ + unsigned int clr_bit; /*clear clock gating bit */ + + unsigned int rx_data_len; /*rx data length */ + + btif_rx_buf_write rx_cb; + + struct kfifo *p_tx_fifo; /*tx fifo */ + spinlock_t tx_fifo_spinlock; /*tx fifo spinlock */ +} MTK_BTIF_INFO_STR, *P_MTK_BTIF_INFO_STR; + +/**********End of Structure Definition***********/ + +/***********register operation***********/ +#ifdef __KERNEL__ +/*byte write <1 byte> */ +#define btif_reg_sync_writeb(v, a) mt_reg_sync_writeb(v, a) +/*word write <2 byte> */ +#define btif_reg_sync_writew(v, a) mt_reg_sync_writew(v, a) +/*long write <4 byte> */ +#define btif_reg_sync_writel(v, a) mt_reg_sync_writel(v, a) +#else +/*byte write <1 byte> */ +#define btif_reg_sync_writeb(v, a) mt65xx_reg_sync_writeb(v, a) +/*word write <2 byte> */ +#define btif_reg_sync_writew(v, a) mt65xx_reg_sync_writew(v, a) +/*long write <4 byte> */ +#define btif_reg_sync_writel(v, a) mt65xx_reg_sync_writel(v, a) +#endif +#define BTIF_READ8(REG) __raw_readb((unsigned char *)(REG)) +#define BTIF_READ16(REG) __raw_readw((unsigned short *)(REG)) +#define BTIF_READ32(REG) __raw_readl((unsigned int *)(REG)) + +#define BTIF_SET_BIT(REG, BITVAL) do { \ +*((volatile unsigned int *)(REG)) |= ((unsigned int)(BITVAL)); \ +mb(); /**/ \ +} \ +while (0) +#define BTIF_CLR_BIT(REG, BITVAL) do { \ +(*(volatile unsigned int *)(REG)) &= ~((unsigned int)(BITVAL)); \ +mb(); /**/\ +} \ +while (0) + +/***********end of register operation *********/ + +#endif /*__HAL_PUB_H_*/ diff --git a/drivers/misc/mediatek/connectivity/Kconfig b/drivers/misc/mediatek/connectivity/Kconfig new file mode 100644 index 0000000000000..4a944b1f0ebe5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/Kconfig @@ -0,0 +1,299 @@ +config MTK_COMBO + tristate "MediaTek Connectivity Combo Chip Support" + help + MTK connectivity combo chip driver for MT66xx + +# +# MTK Combo Chip Selection +# + +choice + prompt "Select Chip" + depends on MTK_COMBO + +config MTK_COMBO_CHIP_MT6620 + bool "MT6620" + help + this config is used to decided combo chip version + in current platform + is + MT6620 + +config MTK_COMBO_CHIP_MT6628 + bool "MT6628" + help + this config is used to decided combo chip version + in current platform + is + MT6628 + +config MTK_COMBO_CHIP_MT6630 + bool "MT6630" + help + this config is used to decided combo chip version + in current platform + is + MT6630 + +config MTK_COMBO_CHIP_CONSYS_6572 + bool "CONSYS_6572" + help + this config is used to decided SOC consys version + in current platform + is + MT6572 + +config MTK_COMBO_CHIP_CONSYS_6582 + bool "CONSYS_6582" + help + this config is used to decided SOC consys version + in current platform + is + MT6582 + +config MTK_COMBO_CHIP_CONSYS_8127 + bool "CONSYS_8127" + help + this config is used to decided SOC consys version + in current platform + is + MT6572 + +config MTK_COMBO_CHIP_CONSYS_7623 + bool "CONSYS_7623" + #select MTK_PLATFORM::="mt7623" + help + this config is used to decide SOC consys version + in current platform is MT7623 and prepare proper + system services like radio power on/off and firmware + download for the Bluetotoh and Wifi. + + +config MTK_COMBO_CHIP_CONSYS_6752 + bool "CONSYS_6752" + help + this config is used to decided SOC consys version + in current platform + is + MT6752 + +config MTK_COMBO_CHIP_CONSYS_6592 + bool "CONSYS_6592" + help + this config is used to decided SOC consys version + in current platform + is + MT6592 + +config MTK_COMBO_CHIP_CONSYS_8163 + bool "CONSYS_8163" + help + this config is used to decided SOC consys version + in current platform + is + MT8163 + +config MTK_COMBO_CHIP_CONSYS_6735 + bool "CONSYS_6735" + help + this config is used to decided SOC consys version + in current platform + is + MT6735 + +config MTK_COMBO_CHIP_CONSYS_6755 + bool "CONSYS_6755" + help + this config is used to decided SOC consys version + in current platform + is + MT6755 + +config MTK_COMBO_CHIP_CONSYS_6580 + bool "CONSYS_6580" + help + this config is used to decided SOC consys version + in current platform + is + MT6580 + +config MTK_COMBO_CHIP_CONSYS_6797 + bool "CONSYS_6797" + help + this config is used to decided SOC consys version + in current platform + is + MT6797 +endchoice + +config MTK_COMBO_CHIP + string + default "MT6620" if MTK_COMBO_CHIP_MT6620 + default "MT6628" if MTK_COMBO_CHIP_MT6628 + default "MT6630" if MTK_COMBO_CHIP_MT6630 + default "CONSYS_6572" if MTK_COMBO_CHIP_CONSYS_6572 + default "CONSYS_6582" if MTK_COMBO_CHIP_CONSYS_6582 + default "CONSYS_8127" if MTK_COMBO_CHIP_CONSYS_8127 + default "CONSYS_7623" if MTK_COMBO_CHIP_CONSYS_7623 + default "CONSYS_6752" if MTK_COMBO_CHIP_CONSYS_6752 + default "CONSYS_6755" if MTK_COMBO_CHIP_CONSYS_6755 + default "CONSYS_6592" if MTK_COMBO_CHIP_CONSYS_6592 + default "CONSYS_8163" if MTK_COMBO_CHIP_CONSYS_8163 + default "CONSYS_6735" if MTK_COMBO_CHIP_CONSYS_6735 + default "CONSYS_6580" if MTK_COMBO_CHIP_CONSYS_6580 + default "CONSYS_6797" if MTK_COMBO_CHIP_CONSYS_6797 + help + this feature is used to identify combo chip version or SOC chip + consys version. + +# +# Target Platform Selection +# +config MTK_COMBO_PLAT_PATH + string "Platform folder name" + depends on MTK_COMBO + default "sample" if MTK_COMBO_PLAT_SAMPLE + help + Specify platform folder under common driver platform folder: + mtk_wcn_combo/common/platform/* + +# +# MTK COMBO Chip Configuration +# +config MTK_COMBO_COMM + depends on MTK_COMBO + tristate "MediaTek Combo Chip Common part driver" + help + MediaTek combo chip common part driver + +#config MTK_COMBO_COMM_PS +# depends on MTK_COMBO_COMM +# bool "Enable PS support" +# default n +# help +# Enable PS support of common UART interface + +config MTK_COMBO_COMM_UART + depends on MTK_COMBO_COMM + tristate "Common interface UART" + help + Use UART for common part interface type + +config MTK_COMBO_COMM_SDIO + depends on MTK_COMBO_COMM + tristate "Common interface SDIO" + help + Use SDIO for common part interface type + +config MTK_COMBO_COMM_NPWR + depends on MTK_COMBO_COMM + bool "Enable NPWR support" + default n + help + Enable NPWR support of new power on swquence + +config MTK_COMBO_COMM_APO + depends on MTK_COMBO_COMM + bool "Enable always power on support" + #default y + help + Enable chip will always power on + +config MTK_COMBO_BT + tristate "MediaTek Combo Chip BT driver" + depends on BT && MTK_COMBO + select MTK_BTIF + help + MTK BT /dev/stpbt driver for Bluedroid + +config MTK_COMBO_BT_HCI + tristate "MediaTek Combo Chip BlueZ driver" + depends on BT && MTK_COMBO + select MTK_BTIF + help + MTK BT driver for BlueZ + +config MTK_COMBO_WIFI + tristate "MediaTek combo chip Wi-Fi support" + depends on MTK_COMBO + select MTK_BTIF + select WIRELESS_EXT + select WEXT_PRIV + +config MTK_WAPI_SUPPORT + bool "MTK_WAPI_SUPPORT" + depends on MTK_COMBO_WIFI + #default y + help + if it is set to TRUE: Support WAPI (WLAN Authentication and + Privacy Infrastructure) + +config MTK_PASSPOINT_R1_SUPPORT + bool "MTK_PASSPOINT_R1_SUPPORT" + depends on MTK_COMBO_WIFI + help + Support Passpoint R1 (Hotspot 2.0 R1) + +config MTK_PASSPOINT_R2_SUPPORT + bool "MTK_PASSPOINT_R2_SUPPORT" + depends on MTK_COMBO_WIFI + help + Support Passpoint R2 + +config MTK_WIFI_MCC_SUPPORT + bool "MTK_WIFI_MCC_SUPPORT" + depends on MTK_COMBO_WIFI + #default y + help + if it is set to TRUE, wlan will support Multi-Channel Concurrency, + otherwise, only support Single Channel Concurrency + +config MTK_DHCPV6C_WIFI + bool "MTK_DHCPV6C_WIFI" + help + no: disable this feature + +config MTK_CONN_LTE_IDC_SUPPORT + bool "MediaTek CONN LTE IDC support" + select MTK_CONN_MD + #default y + help + This option enables CONN LTE IDC support + +menuconfig GPS + tristate "GPS drivers" + #default y + ---help--- + Say Y here for supporting GPS. + +if GPS +config MTK_GPS + tristate "MediaTek GPS driver" + #default y + ---help--- + MTK GPS driver + To switch gps nmea port driver. + Set "yes" to turn on. + Set "no" to turn off. +endif # GPS + +config MTK_GPS_SUPPORT + tristate "MediaTek GPS driver" + select MTK_GPS + help + to switch GPS feature on the platform. + Set "yes" to turn on and set "no" + (with MTK_AGPS_APP=no at the same time) + to turn off. + +config MTK_GPS_REGISTER_SETTING + tristate "MediaTek GPS Register Setting" + depends on MTK_COMBO_GPS + help + GPS register settings. + +config MTK_GPS_EMI + tristate "MediaTek GPS EMI Driver" + depends on MTK_COMBO_GPS + help + GPS EMI driver is for MNL OFFLOAD feature. diff --git a/drivers/misc/mediatek/connectivity/Makefile b/drivers/misc/mediatek/connectivity/Makefile new file mode 100644 index 0000000000000..0947788d189a8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/Makefile @@ -0,0 +1,41 @@ +# +# Copyright (C) 2015 MediaTek Inc. +# +# 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. +# + +# Connectivity combo driver +# If KERNELRELEASE is defined, we've been invoked from the +# kernel build system and can use its language. +ifneq ($(KERNELRELEASE),) +subdir-ccflags-y += -D MTK_WCN_REMOVE_KERNEL_MODULE +ifeq ($(CONFIG_ARM64), y) +subdir-ccflags-y += -D CONFIG_MTK_WCN_ARM64 +endif + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + subdir-ccflags-y += -D WMT_IDC_SUPPORT=1 +else + subdir-ccflags-y += -D WMT_IDC_SUPPORT=0 +endif + subdir-ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + + obj-y += common/ + obj-$(CONFIG_MTK_COMBO_WIFI) += wlan/ + obj-n := dummy.o + +# Otherwise we were called directly from the command line; +# invoke the kernel build system. +else + KERNELDIR ?= /lib/modules/$(shell uname -r)/build + PWD := $(shell pwd) +default: + $(MAKE) -C $(KERNELDIR) M=$(PWD) modules +endif diff --git a/drivers/misc/mediatek/connectivity/common/Makefile b/drivers/misc/mediatek/connectivity/common/Makefile new file mode 100644 index 0000000000000..622b74430e132 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/Makefile @@ -0,0 +1,23 @@ +subdir-ccflags-y += -Werror -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include +subdir-ccflags-y += -Werror -I$(srctree)/drivers/misc/mediatek/include/mt-plat + +#ifneq ($(filter "MT6620E3",$(CONFIG_MTK_COMBO_CHIP)),) +# obj-y += combo/ +#endif +#ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) +# subdir-ccflags-y += -D MT6628 +# subdir-ccflags-y += -D MERGE_INTERFACE_SUPPORT +# obj-y += combo/ +#endif +#ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) +# subdir-ccflags-y += -D MT6630 +#ifneq ($(CONFIG_ARCH_MT2601),y) +# subdir-ccflags-y += -D MERGE_INTERFACE_SUPPORT +#endif +# obj-y += combo/ +#endif +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + obj-y += conn_soc/ +endif + +obj-y += common_detect/ diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/Makefile b/drivers/misc/mediatek/connectivity/common/common_detect/Makefile new file mode 100644 index 0000000000000..8d7dc690affd2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/Makefile @@ -0,0 +1,47 @@ +subdir-ccflags-y += -I$(srctree)/arch/arm/mach-$(MTK_PLATFORM)/$(ARCH_MTK_PROJECT)/dct/dct +subdir-ccflags-y += -DWMT_PLAT_ALPS=1 + +COMBO_CHIP_SUPPORT := false +ifneq ($(filter "MT6620E3",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifneq ($(filter "MT6628",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) + COMBO_CHIP_SUPPORT := true +endif +ifeq ($(COMBO_CHIP_SUPPORT), true) + subdir-ccflags-y += -D MTK_WCN_COMBO_CHIP_SUPPORT + ccflags-y += -I$(src)/../combo/linux/include +endif + +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + subdir-ccflags-y += -D MTK_WCN_SOC_CHIP_SUPPORT + ccflags-y += -I$(src)/../conn_soc/linux/include +endif + + +ifeq ($(CONFIG_MTK_COMBO),y) + ccflags-y += -I$(src)/drv_init/inc + obj-y += mtk_wcn_stub_alps.o + obj-y += wmt_stp_exp.o + obj-y += wmt_gpio.o + + obj-y += wmt_detect.o + obj-y += sdio_detect.o + obj-y += wmt_detect_pwr.o + + obj-y += drv_init/ +endif + +ifeq ($(CONFIG_MTK_COMBO),m) + obj-y += mtk_wcn_stub_alps.o + obj-y += wmt_stp_exp.o + obj-y += wmt_gpio.o + + obj-$(CONFIG_MTK_COMBO) += mtk_wmt_detect.o + mtk_wmt_detect-objs := wmt_detect.o + mtk_wmt_detect-objs += sdio_detect.o + mtk_wmt_detect-objs += wmt_detect_pwr.o +endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile new file mode 100644 index 0000000000000..bb84384b9a24f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/Makefile @@ -0,0 +1,22 @@ +ifeq ($(CONFIG_MTK_COMBO),y) + ccflags-y += -I$(src)/inc/ + ccflags-y += -I$(src)/../ + +ifneq ($(filter "MT6630",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN3 +endif +ifneq ($(filter "CONSYS_6797",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN3 +else ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) + ccflags-y += -D MTK_WCN_WLAN_GEN2 +endif + + obj-y += conn_drv_init.o + obj-y += common_drv_init.o + obj-y += bluetooth_drv_init.o + obj-y += gps_drv_init.o + obj-y += fm_drv_init.o + obj-y += wlan_drv_init.o + obj-($(CONFIG_MTK_COMBO_ANT)) += ant_drv_init.o + +endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c new file mode 100644 index 0000000000000..aa453f9397a47 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/ant_drv_init.c @@ -0,0 +1,38 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[ANT-MOD-INIT]" + +#include "wmt_detect.h" +#include "ant_drv_init.h" + +int do_ant_drv_init(int chip_id) +{ + int i_ret = -1; + + WMT_DETECT_INFO_FUNC("start to do ANT driver init\n"); + switch (chip_id) { + case 0x6630: + case 0x6797: + i_ret = mtk_wcn_stpant_drv_init(); + WMT_DETECT_INFO_FUNC("finish ANT driver init, i_ret:%d\n", i_ret); + break; + default: + WMT_DETECT_ERR_FUNC("chipid is not 6630,ANT is not supported!\n"); + } + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c new file mode 100644 index 0000000000000..47b0554334433 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/bluetooth_drv_init.c @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[BT-MOD-INIT]" + +#include "wmt_detect.h" +#include "bluetooth_drv_init.h" + +int do_bluetooth_drv_init(int chip_id) +{ + int i_ret = -1; + +#if defined(CONFIG_MTK_COMBO_BT) || defined(CONFIG_MTK_COMBO_BT_HCI) + WMT_DETECT_INFO_FUNC("start to do bluetooth driver init\n"); + i_ret = mtk_wcn_stpbt_drv_init(); + WMT_DETECT_INFO_FUNC("finish bluetooth driver init, i_ret:%d\n", i_ret); +#else + WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_BT is not defined\n"); +#endif + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c new file mode 100644 index 0000000000000..f9c332ea266b9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/common_drv_init.c @@ -0,0 +1,103 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-MOD-INIT]" + +#include "wmt_detect.h" +#include "common_drv_init.h" + +static int do_combo_common_drv_init(int chip_id) +{ + int i_ret = 0; + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + int i_ret_tmp = 0; + + WMT_DETECT_DBG_FUNC("start to do combo driver init, chipid:0x%08x\n", chip_id); + + /* HIF-SDIO driver init */ + i_ret_tmp = mtk_wcn_hif_sdio_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_DBG_FUNC("HIF-SDIO driver init, i_ret:%d\n", i_ret); + + /* WMT driver init */ + i_ret_tmp = mtk_wcn_combo_common_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_DBG_FUNC("COMBO COMMON driver init, i_ret:%d\n", i_ret); + + /* STP-UART driver init */ + i_ret_tmp = mtk_wcn_stp_uart_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_DBG_FUNC("STP-UART driver init, i_ret:%d\n", i_ret); + + /* STP-SDIO driver init */ + i_ret_tmp = mtk_wcn_stp_sdio_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_DBG_FUNC("STP-SDIO driver init, i_ret:%d\n", i_ret); + +#else + i_ret = -1; + WMT_DETECT_ERR_FUNC("COMBO chip is not supported, please check CONFIG_MTK_COMBO_CHIP in kernel config\n"); +#endif + WMT_DETECT_DBG_FUNC("finish combo driver init\n"); + return i_ret; +} + +static int do_soc_common_drv_init(int chip_id) +{ + int i_ret = 0; + +#ifdef MTK_WCN_SOC_CHIP_SUPPORT + int i_ret_tmp = 0; + + WMT_DETECT_DBG_FUNC("start to do soc common driver init, chipid:0x%08x\n", chip_id); + + /* WMT driver init */ + i_ret_tmp = mtk_wcn_soc_common_drv_init(); + i_ret += i_ret_tmp; + WMT_DETECT_DBG_FUNC("COMBO COMMON driver init, i_ret:%d\n", i_ret); + +#else + i_ret = -1; + WMT_DETECT_ERR_FUNC("SOC chip is not supported, please check CONFIG_MTK_COMBO_CHIP in kernel config\n"); +#endif + + WMT_DETECT_DBG_FUNC("TBD........\n"); + return i_ret; +} + +int do_common_drv_init(int chip_id) +{ + int i_ret = 0; + + WMT_DETECT_INFO_FUNC("start to do common driver init, chipid:0x%08x\n", chip_id); + + switch (chip_id) { + case 0x6620: + case 0x6628: + case 0x6630: + i_ret = do_combo_common_drv_init(chip_id); + break; + default: + i_ret = do_soc_common_drv_init(chip_id); + break; + } + + WMT_DETECT_INFO_FUNC("finish common driver init\n"); + + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c new file mode 100644 index 0000000000000..8112d2a1d95e2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/conn_drv_init.c @@ -0,0 +1,80 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WCN-MOD-INIT]" + +#include "wmt_detect.h" +#include "conn_drv_init.h" +#include "common_drv_init.h" +#include "fm_drv_init.h" +#include "wlan_drv_init.h" +#include "bluetooth_drv_init.h" +#include "gps_drv_init.h" +#include "ant_drv_init.h" + +int __weak do_wlan_drv_init(int chip_id) +{ + WMT_DETECT_ERR_FUNC("Can not find wlan module for chip: %d !\n", chip_id); + return 0; +} + +int __weak do_ant_drv_init(int chip_id) +{ + WMT_DETECT_DBG_FUNC("Chip: %d can not support ANT !\n", chip_id); + return 0; +} + +int do_connectivity_driver_init(int chip_id) +{ + int i_ret = 0; + int tmp_ret = 0; + + tmp_ret = do_common_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) { + WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); + WMT_DETECT_ERR_FUNC("abort connectivity driver init, because common part is not ready\n"); + return i_ret; + } + + tmp_ret = do_bluetooth_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_gps_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_ERR_FUNC("do common driver init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_fm_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_ERR_FUNC("do fm module init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_wlan_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_ERR_FUNC("do wlan module init failed, ret:%d\n", tmp_ret); + + tmp_ret = do_ant_drv_init(chip_id); + i_ret += tmp_ret; + if (tmp_ret) + WMT_DETECT_ERR_FUNC("do ANT module init failed, ret:%d\n", tmp_ret); + + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c new file mode 100644 index 0000000000000..069c1cf13bbaf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/fm_drv_init.c @@ -0,0 +1,33 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[FM-MOD-INIT]" + +#include "wmt_detect.h" +#include "fm_drv_init.h" + +int do_fm_drv_init(int chip_id) +{ + WMT_DETECT_INFO_FUNC("start to do fm module init\n"); + +#ifdef CONFIG_MTK_FMRADIO + mtk_wcn_fm_init(); +#endif + + WMT_DETECT_INFO_FUNC("finish fm module init\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c new file mode 100644 index 0000000000000..6da1d70a3ca65 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/gps_drv_init.c @@ -0,0 +1,35 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[GPS-MOD-INIT]" + +#include "wmt_detect.h" +#include "gps_drv_init.h" + +int do_gps_drv_init(int chip_id) +{ + int i_ret = -1; +#ifdef CONFIG_MTK_COMBO_GPS + WMT_DETECT_INFO_FUNC("start to do gps driver init\n"); + i_ret = mtk_wcn_stpgps_drv_init(); + WMT_DETECT_INFO_FUNC("finish gps driver init, i_ret:%d\n", i_ret); +#else + WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_GPS is not defined\n"); +#endif + return i_ret; + +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h new file mode 100644 index 0000000000000..4a436a2362900 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/ant_drv_init.h @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _ANT_DRIVER_INIT_H_ +#define _ANT_DRIVER_INIT_H_ + +extern int do_ant_drv_init(int chip_id); +extern int mtk_wcn_stpant_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h new file mode 100644 index 0000000000000..8a847d361fc8c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/bluetooth_drv_init.h @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _BLUETOOTH_DRIVER_INIT_H_ +#define _BLUETOOTH_DRIVER_INIT_H_ + +extern int do_bluetooth_drv_init(int chip_id); +extern int mtk_wcn_stpbt_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h new file mode 100644 index 0000000000000..ea01bd633c3c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/common_drv_init.h @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _COMMON_DRV_INIT_H_ +#define _COMMON_DRV_INIT_H_ +extern int do_common_drv_init(int chip_id); + +/*defined in common part driver*/ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +extern int mtk_wcn_combo_common_drv_init(void); +extern int mtk_wcn_hif_sdio_drv_init(void); +extern int mtk_wcn_stp_uart_drv_init(void); +extern int mtk_wcn_stp_sdio_drv_init(void); +#endif + +#ifdef MTK_WCN_SOC_CHIP_SUPPORT +extern int mtk_wcn_soc_common_drv_init(void); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h new file mode 100644 index 0000000000000..971193eade9e9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/conn_drv_init.h @@ -0,0 +1,18 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _CONNECTIVITY_DRV_INIT_H_ +#define _CONNECTIVITY_DRV_INIT_H_ +extern int do_connectivity_driver_init(int chip_id); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h new file mode 100644 index 0000000000000..f6ea30addc5da --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/fm_drv_init.h @@ -0,0 +1,20 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _FM_DRV_INIT_H_ +#define _FM_DRV_INIT_H_ +extern int do_fm_drv_init(int chip_id); +extern int mtk_wcn_fm_init(void); +extern void mtk_wcn_fm_exit(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h new file mode 100644 index 0000000000000..006ce072c53b6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/gps_drv_init.h @@ -0,0 +1,19 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _GPS_DRIVER_INIT_H_ +#define _GPS_DRIVER_INIT_H_ +extern int do_gps_drv_init(int chip_id); +extern int mtk_wcn_stpgps_drv_init(void); +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h new file mode 100644 index 0000000000000..cb71b50bf950d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/inc/wlan_drv_init.h @@ -0,0 +1,30 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WLAN_DRV_INIT_H_ +#define _WLAN_DRV_INIT_H_ + + +extern int do_wlan_drv_init(int chip_id); + +extern int mtk_wcn_wmt_wifi_init(void); + +#ifdef MTK_WCN_WLAN_GEN2 +extern int mtk_wcn_wlan_gen2_init(void); +#endif +#ifdef MTK_WCN_WLAN_GEN3 +extern int mtk_wcn_wlan_gen3_init(void); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c new file mode 100644 index 0000000000000..5b0d039a4a425 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/drv_init/wlan_drv_init.c @@ -0,0 +1,74 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WLAN-MOD-INIT]" + +#include "wmt_detect.h" +#include "wlan_drv_init.h" + + +int do_wlan_drv_init(int chip_id) +{ + int i_ret = 0; + +#ifdef CONFIG_MTK_COMBO_WIFI + int ret = 0; + + WMT_DETECT_INFO_FUNC("start to do wlan module init 0x%x\n", chip_id); + + /* WMT-WIFI char dev init */ + ret = mtk_wcn_wmt_wifi_init(); + WMT_DETECT_INFO_FUNC("WMT-WIFI char dev init, ret:%d\n", ret); + i_ret += ret; + + switch (chip_id) { + case 0x6630: + case 0x6797: +#ifdef MTK_WCN_WLAN_GEN3 + /* WLAN driver init */ + ret = mtk_wcn_wlan_gen3_init(); + WMT_DETECT_INFO_FUNC("WLAN-GEN3 driver init, ret:%d\n", ret); + i_ret += ret; +#else + WMT_DETECT_ERR_FUNC("WLAN-GEN3 driver is not supported, please check CONFIG_MTK_COMBO_CHIP\n"); + i_ret = -1; +#endif + break; + + default: +#ifdef MTK_WCN_WLAN_GEN2 + /* WLAN driver init */ + ret = mtk_wcn_wlan_gen2_init(); + WMT_DETECT_INFO_FUNC("WLAN-GEN2 driver init, ret:%d\n", ret); + i_ret += ret; +#else + WMT_DETECT_ERR_FUNC("WLAN-GEN2 driver is not supported, please check CONFIG_MTK_COMBO_CHIP\n"); + i_ret = -1; +#endif + break; + } + + WMT_DETECT_INFO_FUNC("finish wlan module init\n"); + +#else + + WMT_DETECT_INFO_FUNC("CONFIG_MTK_COMBO_WIFI is not defined\n"); + +#endif + + return i_ret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c new file mode 100644 index 0000000000000..fa8d437686f2d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/mtk_wcn_stub_alps.c @@ -0,0 +1,605 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CMB_STUB_DBG_LOG 3 +#define CMB_STUB_INFO_LOG 2 +#define CMB_STUB_WARN_LOG 1 + +int gCmbStubLogLevel = CMB_STUB_INFO_LOG; + +#define CMB_STUB_LOG_INFO(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_INFO_LOG) \ + pr_warn(fmt, ##arg); \ +} while (0) +#define CMB_STUB_LOG_WARN(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_WARN_LOG) \ + pr_warn(fmt, ##arg); \ +} while (0) +#define CMB_STUB_LOG_DBG(fmt, arg...) \ +do { \ + if (gCmbStubLogLevel >= CMB_STUB_DBG_LOG) \ + pr_debug(fmt, ##arg); \ +} while (0) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "wmt_detect.h" + + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#ifndef MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 0 +#endif + +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +struct work_struct *g_sdio_1v_autok_wk = NULL; +#endif +int gConnectivityChipId = -1; + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +/* +* current used uart port name, default is "ttyMT2", +* will be changed when wmt driver init +*/ +char *wmt_uart_port_desc = "ttyMT2"; +EXPORT_SYMBOL(wmt_uart_port_desc); +#endif + +static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data); +static void mtk_wcn_cmb_sdio_enable_eirq(void); +static void mtk_wcn_cmb_sdio_disable_eirq(void); +static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data); + +struct sdio_ops mt_sdio_ops[4] = { + {NULL, NULL, NULL, NULL}, + {NULL, NULL, NULL, NULL}, + {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, + mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm}, + {mtk_wcn_cmb_sdio_request_eirq, mtk_wcn_cmb_sdio_enable_eirq, + mtk_wcn_cmb_sdio_disable_eirq, mtk_wcn_cmb_sdio_register_pm} +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static wmt_aif_ctrl_cb cmb_stub_aif_ctrl_cb; +static wmt_func_ctrl_cb cmb_stub_func_ctrl_cb; +static wmt_thermal_query_cb cmb_stub_thermal_ctrl_cb; +static CMB_STUB_AIF_X cmb_stub_aif_stat = CMB_STUB_AIF_0; +static wmt_deep_idle_ctrl_cb cmb_stub_deep_idle_ctrl_cb; +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +static wmt_get_drv_status cmb_stub_drv_status_ctrl_cb; +#endif +static wmt_func_do_reset cmb_stub_do_reset_cb; +/* A temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X. + * This is used for ALPS backward compatible ONLY!!! Remove this table, related + * functions, and type definition after modifying other kernel built-in modules, + * such as AUDIO. [FixMe][GeorgeKuo] + */ +#if 0 +static CMB_STUB_AIF_X audio2aif[] = { + [COMBO_AUDIO_STATE_0] = CMB_STUB_AIF_0, + [COMBO_AUDIO_STATE_1] = CMB_STUB_AIF_1, + [COMBO_AUDIO_STATE_2] = CMB_STUB_AIF_2, + [COMBO_AUDIO_STATE_3] = CMB_STUB_AIF_3, +}; +#endif +static msdc_sdio_irq_handler_t mtk_wcn_cmb_sdio_eirq_handler; +static atomic_t sdio_claim_irq_enable_flag; +static atomic_t irq_enable_flag; +static pm_callback_t mtk_wcn_cmb_sdio_pm_cb; +static void *mtk_wcn_cmb_sdio_pm_data; +static void *mtk_wcn_cmb_sdio_eirq_data; + +static u32 wifi_irq = 0xffffffff; +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +static void mtk_wcn_cmb_stub_1v_autok_work(struct work_struct *work) +{ + CMB_STUB_LOG_WARN("++enter++\n"); + mtk_wcn_cmb_stub_func_ctrl(11, 1); + mtk_wcn_cmb_stub_func_ctrl(11, 0); + CMB_STUB_LOG_WARN("--exit--\n"); +} + +/*! + * \brief A function for Getting current driver status:on/off + * + * \param driver type:0/bt,1/fm,2/gps,3/wifi,11/autok->run wmt turn on/off wifi flow + * + * \retval 0/off,2/on,-1/null pointer + */ +static int mtk_wcn_cmb_stub_drv_status(unsigned int type) +{ + int ret = -1; + + if (cmb_stub_drv_status_ctrl_cb) + ret = (*cmb_stub_drv_status_ctrl_cb) (type); + else + CMB_STUB_LOG_WARN("cmb_stub_drv_status_ctrl_cb is NULL\n"); + return ret; +} + +/*! + * \brief A 1v AutoK function for kernel DVFS driver calling when screen off + * + * \param void + * + * \retval int,mt6630 state:0/off,1/power on,2/func on, -1/null + */ +int mtk_wcn_cmb_stub_1vautok_for_dvfs(void) +{ + int wmt_status; + + CMB_STUB_LOG_WARN("DVFS driver call sdio 1v autok\n"); + + wmt_status = mtk_wcn_cmb_stub_drv_status(4); + CMB_STUB_LOG_WARN("current mt6630 status is %d\n", wmt_status); + if (0 == wmt_status) { + if (g_sdio_1v_autok_wk) + schedule_work(g_sdio_1v_autok_wk); + else + CMB_STUB_LOG_WARN("g_sdio_1v_autok_wk is NULL\n"); + } else if ((2 == wmt_status) || (1 == wmt_status)) { + CMB_STUB_LOG_WARN("mt6630 is on state,skip AUTOK\n"); + } else { + CMB_STUB_LOG_WARN("mt6630 is unknown state(%d)\n", wmt_status); + } + + return wmt_status; + +} +#endif +/*! + * \brief A registration function for WMT-PLAT to register itself to CMB-STUB. + * + * An MTK-WCN-CMB-STUB registration function provided to WMT-PLAT to register + * itself and related callback functions when driver being loaded into kernel. + * + * \param p_stub_cb a pointer carrying CMB_STUB_CB information + * + * \retval 0 operation success + * \retval -1 invalid parameters + */ +int mtk_wcn_cmb_stub_reg(P_CMB_STUB_CB p_stub_cb) +{ + if ((!p_stub_cb) + || (p_stub_cb->size != sizeof(CMB_STUB_CB))) { + CMB_STUB_LOG_WARN("[cmb_stub] invalid p_stub_cb:0x%p size(%d)\n", + p_stub_cb, (p_stub_cb) ? p_stub_cb->size : 0); + return -1; + } + + CMB_STUB_LOG_DBG("[cmb_stub] registered, p_stub_cb:0x%p size(%d)\n", p_stub_cb, p_stub_cb->size); + + cmb_stub_aif_ctrl_cb = p_stub_cb->aif_ctrl_cb; + cmb_stub_func_ctrl_cb = p_stub_cb->func_ctrl_cb; + cmb_stub_thermal_ctrl_cb = p_stub_cb->thermal_query_cb; + cmb_stub_deep_idle_ctrl_cb = p_stub_cb->deep_idle_ctrl_cb; + cmb_stub_do_reset_cb = p_stub_cb->wmt_do_reset_cb; +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK + cmb_stub_drv_status_ctrl_cb = p_stub_cb->get_drv_status_cb; + g_sdio_1v_autok_wk = vmalloc(sizeof(struct work_struct)); + if (!g_sdio_1v_autok_wk) + CMB_STUB_LOG_WARN("vmalloc work_struct(%zd) fail\n", sizeof(struct work_struct)); + else + INIT_WORK(g_sdio_1v_autok_wk, mtk_wcn_cmb_stub_1v_autok_work); + +#endif + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_reg); +/*! + * \brief A unregistration function for WMT-PLAT to unregister from CMB-STUB. + * + * An MTK-WCN-CMB-STUB unregistration function provided to WMT-PLAT to + * unregister itself and clear callback function references. + * + * \retval 0 operation success + */ +int mtk_wcn_cmb_stub_unreg(void) +{ + cmb_stub_aif_ctrl_cb = NULL; + cmb_stub_func_ctrl_cb = NULL; + cmb_stub_thermal_ctrl_cb = NULL; + cmb_stub_deep_idle_ctrl_cb = NULL; + cmb_stub_do_reset_cb = NULL; + CMB_STUB_LOG_INFO("[cmb_stub] unregistered\n"); /* KERN_DEBUG */ + +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK + if (g_sdio_1v_autok_wk) { + vfree(g_sdio_1v_autok_wk); + g_sdio_1v_autok_wk = NULL; + } +#endif + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_unreg); + +/* stub functions for kernel to control audio path pin mux */ +int mtk_wcn_cmb_stub_aif_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + int ret; + + if ((CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl)) { + + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl invalid (%d, %d)\n", state, ctrl); + return -1; + } + + /* avoid the early interrupt before we register the eirq_handler */ + if (cmb_stub_aif_ctrl_cb) { + ret = (*cmb_stub_aif_ctrl_cb) (state, ctrl); + CMB_STUB_LOG_INFO("[cmb_stub] aif_ctrl_cb state(%d->%d) ctrl(%d) ret(%d)\n", + cmb_stub_aif_stat, state, ctrl, ret); /* KERN_DEBUG */ + + cmb_stub_aif_stat = state; + } else { + CMB_STUB_LOG_WARN("[cmb_stub] aif_ctrl_cb null\n"); + ret = -2; + } + return ret; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_aif_ctrl); + +/* Use a temp translation table between COMBO_AUDIO_STATE_X and CMB_STUB_AIF_X + * for ALPS backward compatible ONLY!!! Remove this table, related functions, + * and type definition after modifying other kernel built-in modules, such as + * AUDIO. [FixMe][GeorgeKuo] + */ + +void mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on) +{ + if (cmb_stub_func_ctrl_cb) + (*cmb_stub_func_ctrl_cb) (type, on); + else + CMB_STUB_LOG_WARN("[cmb_stub] func_ctrl_cb null\n"); +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_func_ctrl); + +int mtk_wcn_cmb_stub_query_ctrl(void) +{ + signed long temp = 0; + + if (cmb_stub_thermal_ctrl_cb) + temp = (*cmb_stub_thermal_ctrl_cb) (); + else + CMB_STUB_LOG_WARN("[cmb_stub] thermal_ctrl_cb null\n"); + + return temp; +} + +/*platform-related APIs*/ +/* void clr_device_working_ability(UINT32 clockId, MT6573_STATE state); */ +/* void set_device_working_ability(UINT32 clockId, MT6573_STATE state); */ + +static int _mt_combo_plt_do_deep_idle(COMBO_IF src, int enter) +{ + int ret = -1; + +#if 0 + if (src != COMBO_IF_UART && src != COMBO_IF_MSDC && src != COMBO_IF_BTIF) { + CMB_STUB_LOG_WARN("src = %d is error\n", src); + return ret; + } + if (src >= 0 && src < COMBO_IF_MAX) + CMB_STUB_LOG_INFO("src = %s, to enter deep idle? %d\n", combo_if_name[src], enter); +#endif + /*TODO: For Common SDIO configuration, we need to do some judgement between STP and WIFI + to decide if the msdc will enter deep idle safely */ + + switch (src) { + case COMBO_IF_UART: + if (enter == 0) { + /* clr_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ + /* disable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +#if 0 + ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 0); + if (ret < 0) + CMB_STUB_LOG_WARN("[CMB] %s exit deep idle failed\n", wmt_uart_port_desc); +#endif +#endif + } else { + /* set_device_working_ability(MT65XX_PDN_PERI_UART3, DEEP_IDLE_STATE); */ + /* enable_dpidle_by_bit(MT65XX_PDN_PERI_UART2); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +#if 0 + ret = mtk_uart_pdn_enable(wmt_uart_port_desc, 1); + if (ret < 0) + CMB_STUB_LOG_WARN("[CMB] %s enter deep idle failed\n", wmt_uart_port_desc); +#endif +#endif + } + ret = 0; + break; + + case COMBO_IF_MSDC: + if (enter == 0) { + /* for common sdio hif */ + /* clr_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ + } else { + /* for common sdio hif */ + /* set_device_working_ability(MT65XX_PDN_PERI_MSDC2, DEEP_IDLE_STATE); */ + } + ret = 0; + break; + + case COMBO_IF_BTIF: + if (cmb_stub_deep_idle_ctrl_cb) + ret = (*cmb_stub_deep_idle_ctrl_cb) (enter); + else + CMB_STUB_LOG_WARN("NULL function pointer\n"); + + if (ret) + CMB_STUB_LOG_WARN("%s deep idle fail(%d)\n", enter == 1 ? "enter" : "exit", ret); + else + CMB_STUB_LOG_DBG("%s deep idle ok(%d)\n", enter == 1 ? "enter" : "exit", ret); + break; + default: + break; + } + + return ret; +} + +int mt_combo_plt_enter_deep_idle(COMBO_IF src) +{ + /* return 0; */ + /* TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO */ + return _mt_combo_plt_do_deep_idle(src, 1); +} +EXPORT_SYMBOL(mt_combo_plt_enter_deep_idle); + +int mt_combo_plt_exit_deep_idle(COMBO_IF src) +{ + /* return 0; */ + /* TODO: [FixMe][GeorgeKuo] handling this depends on common UART or common SDIO */ + return _mt_combo_plt_do_deep_idle(src, 0); +} +EXPORT_SYMBOL(mt_combo_plt_exit_deep_idle); + +int mtk_wcn_wmt_chipid_query(void) +{ + return gConnectivityChipId; +} +EXPORT_SYMBOL(mtk_wcn_wmt_chipid_query); + +void mtk_wcn_wmt_set_chipid(int chipid) +{ + CMB_STUB_LOG_INFO("set current consys chipid (0x%x)\n", chipid); + gConnectivityChipId = chipid; +} +EXPORT_SYMBOL(mtk_wcn_wmt_set_chipid); + +int mtk_wcn_cmb_stub_do_reset(unsigned int type) +{ + if (cmb_stub_do_reset_cb) + return (*cmb_stub_do_reset_cb) (type); + else + return -1; +} +EXPORT_SYMBOL(mtk_wcn_cmb_stub_do_reset); + +static void mtk_wcn_cmb_sdio_enable_eirq(void) +{ + if (atomic_read(&irq_enable_flag)) + CMB_STUB_LOG_DBG("wifi eint has been enabled\n"); + else { + atomic_set(&irq_enable_flag, 1); + if (wifi_irq != 0xfffffff) { + enable_irq(wifi_irq); + CMB_STUB_LOG_DBG(" enable WIFI EINT irq %d !!\n", wifi_irq); + } + } +} + +static void mtk_wcn_cmb_sdio_disable_eirq(void) +{ + if (!atomic_read(&irq_enable_flag)) + CMB_STUB_LOG_DBG("wifi eint has been disabled!\n"); + else { + if (wifi_irq != 0xfffffff) { + disable_irq_nosync(wifi_irq); + CMB_STUB_LOG_DBG("disable WIFI EINT irq %d !!\n", wifi_irq); + } + atomic_set(&irq_enable_flag, 0); + } +} + +irqreturn_t mtk_wcn_cmb_sdio_eirq_handler_stub(int irq, void *data) +{ + if ((NULL != mtk_wcn_cmb_sdio_eirq_handler)&&(0 != atomic_read(&sdio_claim_irq_enable_flag))) + mtk_wcn_cmb_sdio_eirq_handler(mtk_wcn_cmb_sdio_eirq_data); + return IRQ_HANDLED; +} + +static void mtk_wcn_cmb_sdio_request_eirq(msdc_sdio_irq_handler_t irq_handler, void *data) +{ + struct device_node *node; + int ret = -EINVAL; +#if 0 + unsigned int gpio_wifi_eint_pin; +#endif + + CMB_STUB_LOG_INFO("enter %s\n", __func__); + mtk_wcn_sdio_irq_flag_set(0); + atomic_set(&irq_enable_flag, 0); + mtk_wcn_cmb_sdio_eirq_data = data; + mtk_wcn_cmb_sdio_eirq_handler = irq_handler; + + node = (struct device_node *)of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (node) { +#if 0 + gpio_wifi_eint_pin = of_get_gpio(node, 5); + CMB_STUB_LOG_INFO("WIFI EINT pin %d !!\n", gpio_wifi_eint_pin); + wifi_irq = gpio_to_irq(gpio_wifi_eint_pin); +#else + wifi_irq = irq_of_parse_and_map(node, 0);/* get wifi eint num */ +#endif +#if 1 + ret = request_irq(wifi_irq, mtk_wcn_cmb_sdio_eirq_handler_stub, IRQF_TRIGGER_LOW, + "WIFI-eint", NULL); + CMB_STUB_LOG_DBG("WIFI EINT irq %d !!\n", wifi_irq); +#endif + + if (ret) + CMB_STUB_LOG_WARN("WIFI EINT IRQ LINE NOT AVAILABLE!!\n"); + else + mtk_wcn_cmb_sdio_disable_eirq();/*not ,chip state is power off*/ + } else + CMB_STUB_LOG_WARN("[%s] can't find connectivity compatible node\n", __func__); + + CMB_STUB_LOG_INFO("exit %s\n", __func__); +} + +static void mtk_wcn_cmb_sdio_register_pm(pm_callback_t pm_cb, void *data) +{ + CMB_STUB_LOG_DBG("mtk_wcn_cmb_sdio_register_pm (0x%p, 0x%p)\n", pm_cb, data); + /* register pm change callback */ + mtk_wcn_cmb_sdio_pm_cb = pm_cb; + mtk_wcn_cmb_sdio_pm_data = data; +} + +static void mtk_wcn_cmb_sdio_on(int sdio_port_num) +{ + pm_message_t state = {.event = PM_EVENT_USER_RESUME }; + + CMB_STUB_LOG_INFO("mtk_wcn_cmb_sdio_on (%d)\n", sdio_port_num); + + /* 1. disable sdio eirq */ + mtk_wcn_cmb_sdio_disable_eirq(); + + /* 2. call sd callback */ + if (mtk_wcn_cmb_sdio_pm_cb) { + /* pr_warn("mtk_wcn_cmb_sdio_pm_cb(PM_EVENT_USER_RESUME, 0x%p, 0x%p)\n", + * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); */ + mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); + } else + CMB_STUB_LOG_WARN("mtk_wcn_cmb_sdio_on no sd callback!!\n"); +} + +static void mtk_wcn_cmb_sdio_off(int sdio_port_num) +{ + pm_message_t state = {.event = PM_EVENT_USER_SUSPEND }; + + CMB_STUB_LOG_INFO("mtk_wcn_cmb_sdio_off (%d)\n", sdio_port_num); + + /* 1. call sd callback */ + if (mtk_wcn_cmb_sdio_pm_cb) { + /* pr_warn("mtk_wcn_cmb_sdio_off(PM_EVENT_USER_SUSPEND, 0x%p, 0x%p)\n", + * mtk_wcn_cmb_sdio_pm_cb, mtk_wcn_cmb_sdio_pm_data); */ + mtk_wcn_cmb_sdio_pm_cb(state, mtk_wcn_cmb_sdio_pm_data); + } else + CMB_STUB_LOG_WARN("mtk_wcn_cmb_sdio_off no sd callback!!\n"); + + /* 2. disable sdio eirq */ + mtk_wcn_cmb_sdio_disable_eirq(); +} + +int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on) +{ + CMB_STUB_LOG_DBG("mt_mtk_wcn_cmb_sdio_ctrl (%d, %d)\n", sdio_port_num, on); + if (on) { +#if 1 + CMB_STUB_LOG_DBG("board_sdio_ctrl force off before on\n"); + mtk_wcn_cmb_sdio_off(sdio_port_num); +#else + CMB_STUB_LOG_WARN("skip sdio off before on\n"); +#endif + /* off -> on */ + mtk_wcn_cmb_sdio_on(sdio_port_num); + if (wifi_irq != 0xfffffff) + irq_set_irq_wake(wifi_irq, 1); + else + CMB_STUB_LOG_WARN("wifi_irq is not available\n"); + } else { + if (wifi_irq != 0xfffffff) + irq_set_irq_wake(wifi_irq, 0); + else + CMB_STUB_LOG_WARN("wifi_irq is not available\n"); + /* on -> off */ + mtk_wcn_cmb_sdio_off(sdio_port_num); + } + + return 0; +} +EXPORT_SYMBOL(board_sdio_ctrl); + +int mtk_wcn_sdio_irq_flag_set(int flag) +{ + if (0 != flag) + atomic_set(&sdio_claim_irq_enable_flag, 1); + else + atomic_set(&sdio_claim_irq_enable_flag, 0); + + CMB_STUB_LOG_DBG("sdio_claim_irq_enable_flag:%d\n", atomic_read(&sdio_claim_irq_enable_flag)); + + return atomic_read(&sdio_claim_irq_enable_flag); +} +EXPORT_SYMBOL(mtk_wcn_sdio_irq_flag_set); diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c new file mode 100644 index 0000000000000..7ac5ac73ef5d8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.c @@ -0,0 +1,269 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[SDIO-DETECT]" + +#include "wmt_detect.h" + +#if MTK_HIF_SDIO_AUTOK_ENABLED +#include +#endif + +unsigned int gComboChipId = -1; +struct sdio_func *g_func = NULL; + +MTK_WCN_HIF_SDIO_CHIP_INFO gChipInfoArray[] = { + /* MT6620 *//* Not an SDIO standard class device */ + {{SDIO_DEVICE(0x037A, 0x020A)}, 0x6620}, /* SDIO1:FUNC1:WIFI */ + {{SDIO_DEVICE(0x037A, 0x020B)}, 0x6620}, /* SDIO2:FUNC1:BT+FM+GPS */ + {{SDIO_DEVICE(0x037A, 0x020C)}, 0x6620}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {{SDIO_DEVICE(0x037A, 0x6628)}, 0x6628}, + + /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {{SDIO_DEVICE(0x037A, 0x6630)}, 0x6630}, + +}; + +/* Supported SDIO device table */ +static const struct sdio_device_id mtk_sdio_id_tbl[] = { + /* MT6618 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */ + {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */ + {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */ + + /* MT6619 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */ + + /* MT6620 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */ + {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */ + {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */ + + /* MT5921 *//* Not an SDIO standard class device */ + {SDIO_DEVICE(0x037A, 0x5921)}, + + /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6628)}, + + /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */ + {SDIO_DEVICE(0x037A, 0x6630)}, + { /* end: all zeroes */ }, +}; + +static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id); + +static void sdio_detect_remove(struct sdio_func *func); + +static struct sdio_driver mtk_sdio_client_drv = { + .name = "mtk_sdio_client", /* MTK SDIO Client Driver */ + .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */ + .probe = sdio_detect_probe, + .remove = sdio_detect_remove, +}; + +static int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id); + +int hif_sdio_is_chipid_valid(int chipId) +{ + int index = -1; + + int left = 0; + int middle = 0; + int right = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]) - 1; + + if ((chipId < gChipInfoArray[left].chipId) || (chipId > gChipInfoArray[right].chipId)) + return index; + + middle = (left + right) / 2; + + while (left <= right) { + if (chipId > gChipInfoArray[middle].chipId) { + left = middle + 1; + } else if (chipId < gChipInfoArray[middle].chipId) { + right = middle - 1; + } else { + index = middle; + break; + } + middle = (left + right) / 2; + } + + if (0 > index) + WMT_DETECT_ERR_FUNC("no supported chipid found\n"); + else + WMT_DETECT_INFO_FUNC("index:%d, chipId:0x%x\n", index, gChipInfoArray[index].chipId); + + return index; +} + +int hif_sdio_match_chipid_by_dev_id(const struct sdio_device_id *id) +{ + int maxIndex = sizeof(gChipInfoArray) / sizeof(gChipInfoArray[0]); + int index = 0; + struct sdio_device_id *localId = NULL; + int chipId = -1; + + for (index = 0; index < maxIndex; index++) { + localId = &(gChipInfoArray[index].deviceId); + if ((localId->vendor == id->vendor) && (localId->device == id->device)) { + chipId = gChipInfoArray[index].chipId; + WMT_DETECT_INFO_FUNC + ("valid chipId found, index(%d), vendor id(0x%x), device id(0x%x), chip id(0x%x)\n", index, + localId->vendor, localId->device, chipId); + gComboChipId = chipId; + mtk_wcn_wmt_set_chipid(gComboChipId); + break; + } + } + if (0 > chipId) { + WMT_DETECT_ERR_FUNC("No valid chipId found, vendor id(0x%x), device id(0x%x)\n", id->vendor, + id->device); + } + + return chipId; +} + +int sdio_detect_query_chipid(int waitFlag) +{ + unsigned int timeSlotMs = 200; + unsigned int maxTimeSlot = 15; + unsigned int counter = 0; + /* gComboChipId = 0x6628; */ + if (0 == waitFlag) + return gComboChipId; + if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) + return gComboChipId; + + while (counter < maxTimeSlot) { + if (0 <= hif_sdio_is_chipid_valid(gComboChipId)) + break; + msleep(timeSlotMs); + counter++; + } + + return gComboChipId; +} + +int sdio_detect_do_autok(int chipId) +{ + int i_ret = 0; + +#if MTK_HIF_SDIO_AUTOK_ENABLED +#if 0 + BOOTMODE boot_mode; + + boot_mode = get_boot_mode(); + + if (boot_mode == META_BOOT) { + WMT_DETECT_INFO_FUNC("omit autok in meta mode\n"); + return 0; + } +#endif + if (0x6630 == chipId) { +#ifdef CONFIG_SDIOAUTOK_SUPPORT + if (NULL != g_func) { + WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready++\n"); + i_ret = wait_sdio_autok_ready(g_func->card->host); + WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready--\n"); + if (0 == i_ret) { + WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return success\n"); + } else { + WMT_DETECT_INFO_FUNC("wait_sdio_autok_ready return fail, i_ret:%d\n", i_ret); + gComboChipId = -1; + } + } else { + WMT_DETECT_INFO_FUNC("g_func NULL, omit autok\n"); + } +#else + i_ret = 0; + WMT_DETECT_INFO_FUNC("MTK_SDIOAUTOK_SUPPORT not defined\n"); +#endif + } else { + WMT_DETECT_INFO_FUNC("MT%x does not support SDIO3.0 autoK is not needed\n", chipId); + } +#else + i_ret = 0; + WMT_DETECT_INFO_FUNC("MTK_HIF_SDIO_AUTOK_ENABLED is not defined\n"); +#endif + return i_ret; +} + +/*! + * \brief hif_sdio probe function + * + * hif_sdio probe function called by mmc driver when any matched SDIO function + * is detected by it. + * + * \param func + * \param id + * + * \retval 0 register successfully + * \retval < 0 list error code here + */ +static int sdio_detect_probe(struct sdio_func *func, const struct sdio_device_id *id) +{ + int chipId = 0; + + WMT_DETECT_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num); + chipId = hif_sdio_match_chipid_by_dev_id(id); + + if ((0x6630 == chipId) && (1 == func->num)) { + int ret = 0; + + g_func = func; + WMT_DETECT_INFO_FUNC("autok function detected, func:0x%p\n", g_func); + + sdio_claim_host(func); + ret = sdio_enable_func(func); + sdio_release_host(func); + if (ret) + WMT_DETECT_ERR_FUNC("sdio_enable_func failed!\n"); + } + + return 0; +} + +static void sdio_detect_remove(struct sdio_func *func) +{ + if (g_func == func) { + sdio_claim_host(func); + sdio_disable_func(func); + sdio_release_host(func); + g_func = NULL; + } + WMT_DETECT_INFO_FUNC("do sdio remove\n"); +} + +int sdio_detect_init(void) +{ + int ret = -1; + /* register to mmc driver */ + ret = sdio_register_driver(&mtk_sdio_client_drv); + WMT_DETECT_INFO_FUNC("sdio_register_driver() ret=%d\n", ret); + return 0; +} + +int sdio_detect_exit(void) +{ + g_func = NULL; + /* register to mmc driver */ + sdio_unregister_driver(&mtk_sdio_client_drv); + WMT_DETECT_INFO_FUNC("sdio_unregister_driver\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h new file mode 100644 index 0000000000000..3a0bff9def1b1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/sdio_detect.h @@ -0,0 +1,43 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _SDIO_DETECT_H_ +#define _SDIO_DETECT_H_ + +#include +#include +#include +#include +#include + +#ifdef CONFIG_SDIOAUTOK_SUPPORT +#define MTK_HIF_SDIO_AUTOK_ENABLED 1 +extern int wait_sdio_autok_ready(void *); +#else +#define MTK_HIF_SDIO_AUTOK_ENABLED 0 +#endif + +typedef struct _MTK_WCN_HIF_SDIO_CHIP_INFO_ { + struct sdio_device_id deviceId; + unsigned int chipId; +} MTK_WCN_HIF_SDIO_CHIP_INFO, *P_MTK_WCN_HIF_SDIO_CHIP_INFO; + +extern int sdio_detect_exit(void); +extern int sdio_detect_init(void); +extern int sdio_detect_query_chipid(int waitFlag); +extern int hif_sdio_is_chipid_valid(int chipId); + +extern int sdio_detect_do_autok(int chipId); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c new file mode 100644 index 0000000000000..487852df8f20f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.c @@ -0,0 +1,380 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DETECT]" + +#include "wmt_detect.h" +#include "wmt_gpio.h" + +#if MTK_WCN_REMOVE_KO +#include "conn_drv_init.h" +#endif +#ifdef CONFIG_COMPAT +#include +#endif + +#define WMT_DETECT_MAJOR 154 +#define WMT_DETECT_DEV_NUM 1 +#define WMT_DETECT_DRVIER_NAME "mtk_wcn_detect" +#define WMT_DETECT_DEVICE_NAME "wmtdetect" + +struct class *pDetectClass = NULL; +struct device *pDetectDev = NULL; +static int gWmtDetectMajor = WMT_DETECT_MAJOR; +static struct cdev gWmtDetectCdev; +unsigned int gWmtDetectDbgLvl = WMT_DETECT_LOG_INFO; + + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +inline unsigned int wmt_plat_get_soc_chipid(void) +{ + WMT_DETECT_INFO_FUNC("no soc chip supported, due to MTK_WCN_SOC_CHIP_SUPPORT is not set.\n"); + return -1; +} +#endif + +static int wmt_detect_open(struct inode *inode, struct file *file) +{ + WMT_DETECT_INFO_FUNC("open major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static int wmt_detect_close(struct inode *inode, struct file *file) +{ + WMT_DETECT_INFO_FUNC("close major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static ssize_t wmt_detect_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + WMT_DETECT_INFO_FUNC(" ++\n"); + WMT_DETECT_INFO_FUNC(" --\n"); + + return 0; +} + +ssize_t wmt_detect_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + WMT_DETECT_INFO_FUNC(" ++\n"); + WMT_DETECT_INFO_FUNC(" --\n"); + + return 0; +} + +static long wmt_detect_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + int retval = 0; + + WMT_DETECT_INFO_FUNC("cmd (%d),arg(%ld)\n", cmd, arg); + + switch (cmd) { + case COMBO_IOCTL_GET_CHIP_ID: + /*just get chipid from sdio-detect module */ + /*check if external combo chip exists or not */ + /*if yes, just return combo chip id */ + /*if no, get soc chipid */ + retval = mtk_wcn_wmt_chipid_query(); + break; + + case COMBO_IOCTL_SET_CHIP_ID: + mtk_wcn_wmt_set_chipid(arg); + + break; + + case COMBO_IOCTL_EXT_CHIP_PWR_ON: + retval = wmt_detect_ext_chip_pwr_on(); + break; + + case COMBO_IOCTL_EXT_CHIP_DETECT: + retval = wmt_detect_ext_chip_detect(); + break; + + case COMBO_IOCTL_EXT_CHIP_PWR_OFF: + retval = wmt_detect_ext_chip_pwr_off(); + break; + + case COMBO_IOCTL_DO_SDIO_AUDOK: + retval = sdio_detect_do_autok(arg); + break; + + case COMBO_IOCTL_GET_SOC_CHIP_ID: + retval = wmt_plat_get_soc_chipid(); + /*get soc chipid by HAL interface */ + break; + + case COMBO_IOCTL_MODULE_CLEANUP: +#if (MTK_WCN_REMOVE_KO) + /*deinit SDIO-DETECT module */ + retval = sdio_detect_exit(); +#else + WMT_DETECT_INFO_FUNC("no MTK_WCN_REMOVE_KO defined\n"); +#endif + break; + + case COMBO_IOCTL_DO_MODULE_INIT: +#if (MTK_WCN_REMOVE_KO) + /*deinit SDIO-DETECT module */ + retval = do_connectivity_driver_init(arg); +#else + WMT_DETECT_INFO_FUNC("no MTK_WCN_REMOVE_KO defined\n"); +#endif + break; + + default: + WMT_DETECT_WARN_FUNC("unknown cmd (%d)\n", cmd); + retval = 0; + break; + } + return retval; +} +#ifdef CONFIG_COMPAT +static long WMT_compat_detect_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + + WMT_DETECT_INFO_FUNC("cmd (%d)\n", cmd); + ret = wmt_detect_unlocked_ioctl(filp, cmd, arg); + return ret; +} +#endif +const struct file_operations gWmtDetectFops = { + .open = wmt_detect_open, + .release = wmt_detect_close, + .read = wmt_detect_read, + .write = wmt_detect_write, + .unlocked_ioctl = wmt_detect_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = WMT_compat_detect_ioctl, +#endif +}; + +int wmt_detect_ext_chip_pwr_on(void) +{ + /*pre power on external chip */ + /* wmt_plat_pwr_ctrl(FUNC_ON); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + WMT_DETECT_INFO_FUNC("++\n"); + if (0 != wmt_detect_chip_pwr_ctrl(1)) + return -1; + if (0 != wmt_detect_sdio_pwr_ctrl(1)) + return -2; + return 0; +#else + WMT_DETECT_INFO_FUNC("combo chip is not supported\n"); + return -1; +#endif +} + +int wmt_detect_ext_chip_pwr_off(void) +{ + /*pre power off external chip */ + /* wmt_plat_pwr_ctrl(FUNC_OFF); */ +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + WMT_DETECT_INFO_FUNC("--\n"); + wmt_detect_sdio_pwr_ctrl(0); + return wmt_detect_chip_pwr_ctrl(0); +#else + WMT_DETECT_INFO_FUNC("combo chip is not supported\n"); + return 0; +#endif +} + +int wmt_detect_ext_chip_detect(void) +{ + int iRet = -1; + unsigned int chipId = -1; + /*if there is no external combo chip, return -1 */ + int bgfEintStatus = -1; + + WMT_DETECT_INFO_FUNC("++\n"); + /*wait for a stable time */ + msleep(20); + + /*read BGF_EINT_PIN status */ + bgfEintStatus = wmt_detect_read_ext_cmb_status(); + + if (0 == bgfEintStatus) { + /*external chip does not exist */ + WMT_DETECT_INFO_FUNC("external combo chip not detected\n"); + } else if (1 == bgfEintStatus) { + /*combo chip exists */ + WMT_DETECT_INFO_FUNC("external combo chip detected\n"); + + /*detect chipid by sdio_detect module */ + chipId = sdio_detect_query_chipid(1); + if (0 <= hif_sdio_is_chipid_valid(chipId)) + WMT_DETECT_INFO_FUNC("valid external combo chip id (0x%x)\n", chipId); + else + WMT_DETECT_INFO_FUNC("invalid external combo chip id (0x%x)\n", chipId); + iRet = 0; + } else { + /*Error exists */ + WMT_DETECT_ERR_FUNC("error happens when detecting combo chip\n"); + } + WMT_DETECT_INFO_FUNC("--\n"); + /*return 0 */ + return iRet; + /*todo: if there is external combo chip, power on chip return 0 */ +} + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +static int wmt_detect_probe(struct platform_device *pdev) +{ + int ret = 0; + + WMT_DETECT_ERR_FUNC("platform name: %s\n", pdev->name); + ret = wmt_gpio_init(pdev); + if (-1 == ret) + WMT_DETECT_ERR_FUNC("gpio init fail ret:%d\n", ret); + return ret; +} + +static int wmt_detect_remove(struct platform_device *pdev) +{ + wmt_gpio_deinit(); + return 0; +} +#endif + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +static struct of_device_id wmt_detect_match[] = { + { .compatible = "mediatek,connectivity-combo", }, + {} +}; +MODULE_DEVICE_TABLE(of, wmt_detect_match); + +static struct platform_driver wmt_detect_driver = { + .probe = wmt_detect_probe, + .remove = wmt_detect_remove, + .driver = { + .owner = THIS_MODULE, + .name = "mediatek,connectivity-combo", + .of_match_table = wmt_detect_match, + }, +}; +#endif + +/*module_platform_driver(wmt_detect_driver);*/ +static int wmt_detect_driver_init(void) +{ + dev_t devID = MKDEV(gWmtDetectMajor, 0); + int cdevErr = -1; + int ret = -1; + + ret = register_chrdev_region(devID, WMT_DETECT_DEV_NUM, WMT_DETECT_DRVIER_NAME); + if (ret) { + WMT_DETECT_ERR_FUNC("fail to register chrdev\n"); + return ret; + } + + cdev_init(&gWmtDetectCdev, &gWmtDetectFops); + gWmtDetectCdev.owner = THIS_MODULE; + + cdevErr = cdev_add(&gWmtDetectCdev, devID, WMT_DETECT_DEV_NUM); + if (cdevErr) { + WMT_DETECT_ERR_FUNC("cdev_add() fails (%d)\n", cdevErr); + goto err1; + } + + pDetectClass = class_create(THIS_MODULE, WMT_DETECT_DEVICE_NAME); + if (IS_ERR(pDetectClass)) { + WMT_DETECT_ERR_FUNC("class create fail, error code(%ld)\n", PTR_ERR(pDetectClass)); + goto err1; + } + + pDetectDev = device_create(pDetectClass, NULL, devID, NULL, WMT_DETECT_DEVICE_NAME); + if (IS_ERR(pDetectDev)) { + WMT_DETECT_ERR_FUNC("device create fail, error code(%ld)\n", PTR_ERR(pDetectDev)); + goto err2; + } + + WMT_DETECT_INFO_FUNC("driver(major %d) installed success\n", gWmtDetectMajor); + + /*init SDIO-DETECT module */ + sdio_detect_init(); + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + ret = platform_driver_register(&wmt_detect_driver); + if (ret) + WMT_DETECT_ERR_FUNC("platform driver register fail ret:%d\n", ret); +#endif + + return 0; + +err2: + + if (pDetectClass) { + class_destroy(pDetectClass); + pDetectClass = NULL; + } + +err1: + + if (cdevErr == 0) + cdev_del(&gWmtDetectCdev); + + if (ret == 0) { + unregister_chrdev_region(devID, WMT_DETECT_DEV_NUM); + gWmtDetectMajor = -1; + } + + WMT_DETECT_ERR_FUNC("fail\n"); + + return -1; +} + +static void wmt_detect_driver_exit(void) +{ + dev_t dev = MKDEV(gWmtDetectMajor, 0); + + if (pDetectDev) { + device_destroy(pDetectClass, dev); + pDetectDev = NULL; + } + + if (pDetectClass) { + class_destroy(pDetectClass); + pDetectClass = NULL; + } + + cdev_del(&gWmtDetectCdev); + unregister_chrdev_region(dev, WMT_DETECT_DEV_NUM); + +#if !(MTK_WCN_REMOVE_KO) +/*deinit SDIO-DETECT module*/ + sdio_detect_exit(); +#endif + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + platform_driver_unregister(&wmt_detect_driver); +#endif + + WMT_DETECT_INFO_FUNC("done\n"); +} + +module_init(wmt_detect_driver_init); +module_exit(wmt_detect_driver_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Zhiguo.Niu & Chaozhong.Liang @ MBJ/WCNSE/SS1"); + +module_param(gWmtDetectMajor, uint, 0); diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h new file mode 100644 index 0000000000000..7e152bfd39ec9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect.h @@ -0,0 +1,114 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_DETECT_H_ +#define _WMT_DETECT_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE +#define MTK_WCN_REMOVE_KO 1 +#else +#define MTK_WCN_REMOVE_KO 0 +#endif + +#include "sdio_detect.h" +#include "wmt_detect_pwr.h" +#include + +#define WMT_DETECT_LOG_LOUD 4 +#define WMT_DETECT_LOG_DBG 3 +#define WMT_DETECT_LOG_INFO 2 +#define WMT_DETECT_LOG_WARN 1 +#define WMT_DETECT_LOG_ERR 0 + +extern unsigned int gWmtDetectDbgLvl; + +#define WMT_DETECT_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_LOUD) \ + pr_debug(DFT_TAG"[L]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_DETECT_DBG_FUNC(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_DBG) \ + pr_debug(DFT_TAG"[D]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_DETECT_INFO_FUNC(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_INFO) \ + pr_err(DFT_TAG"[I]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_DETECT_WARN_FUNC(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_WARN) \ + pr_warn(DFT_TAG"[W]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ +} while (0) +#define WMT_DETECT_ERR_FUNC(fmt, arg...) \ +do { \ + if (gWmtDetectDbgLvl >= WMT_DETECT_LOG_ERR) \ + pr_err(DFT_TAG"[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ +} while (0) + +#define WMT_IOC_MAGIC 'w' +#define COMBO_IOCTL_GET_CHIP_ID _IOR(WMT_IOC_MAGIC, 0, int) +#define COMBO_IOCTL_SET_CHIP_ID _IOW(WMT_IOC_MAGIC, 1, int) +#define COMBO_IOCTL_EXT_CHIP_DETECT _IOR(WMT_IOC_MAGIC, 2, int) +#define COMBO_IOCTL_GET_SOC_CHIP_ID _IOR(WMT_IOC_MAGIC, 3, int) +#define COMBO_IOCTL_DO_MODULE_INIT _IOR(WMT_IOC_MAGIC, 4, int) +#define COMBO_IOCTL_MODULE_CLEANUP _IOR(WMT_IOC_MAGIC, 5, int) +#define COMBO_IOCTL_EXT_CHIP_PWR_ON _IOR(WMT_IOC_MAGIC, 6, int) +#define COMBO_IOCTL_EXT_CHIP_PWR_OFF _IOR(WMT_IOC_MAGIC, 7, int) +#define COMBO_IOCTL_DO_SDIO_AUDOK _IOR(WMT_IOC_MAGIC, 8, int) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +********************************************************************************/ +extern int wmt_detect_ext_chip_detect(void); +extern int wmt_detect_ext_chip_pwr_on(void); +extern int wmt_detect_ext_chip_pwr_off(void); + +#ifdef MTK_WCN_SOC_CHIP_SUPPORT +extern unsigned int wmt_plat_get_soc_chipid(void); +#endif + +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT +/* mtk_uart_pdn_enable -- request uart port enter/exit deep idle mode, this API is defined in uart driver + * + * @ port - uart port name, Eg: "ttyMT0", "ttyMT1", "ttyMT2" + * @ enable - "1", enable deep idle; "0", disable deep idle + * + * Return 0 if success, else -1 + */ +extern unsigned int mtk_uart_pdn_enable(char *port, int enable); +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c new file mode 100644 index 0000000000000..1dcb7ed358bcf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.c @@ -0,0 +1,232 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DETECT]" + +#include "wmt_detect.h" +#include "wmt_gpio.h" + +#define INVALID_PIN_ID (0xFFFFFFFF) + +/*copied form WMT module*/ +static int wmt_detect_dump_pin_conf(void) +{ + WMT_DETECT_DBG_FUNC("[WMT-DETECT]=>dump wmt pin configuration start<=\n"); + + WMT_DETECT_INFO_FUNC("LDO(GPIO%d), PMU(GPIO%d), PMUV28(GPIO%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num); + + WMT_DETECT_INFO_FUNC("RST(GPIO%d), BGF_EINT(GPIO%d), BGF_EINT_NUM(%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num, + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num)); + + WMT_DETECT_INFO_FUNC("WIFI_EINT(GPIO%d), WIFI_EINT_NUM(%d)\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num, + gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)); + + WMT_DETECT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration ends<=\n"); + + return 0; +} + +int _wmt_detect_output_low(unsigned int id) +{ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 0); + WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); + } + + return 0; +} + +int _wmt_detect_output_high(unsigned int id) +{ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 1); + WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num)); + } + + return 0; +} + +int _wmt_detect_read_gpio_input(unsigned int id) +{ + int retval = 0; + + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) { + retval = gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num); + WMT_DETECT_DBG_FUNC("WMT-DETECT: get GPIO%d val%d\n", + gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, retval); + } + + return retval; +} + +/*This power on sequence must support all combo chip's basic power on sequence + * 1. LDO control is a must, if external LDO exist + * 2. PMU control is a must + * 3. RST control is a must + * 4. WIFI_EINT pin control is a must, used for GPIO mode for EINT status checkup + * 5. RTC32k clock control is a must + * */ +static int wmt_detect_chip_pwr_on(void) +{ + int retval = -1; + /*setting validiation check*/ + if ((INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) || + (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) || + (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)) { + WMT_DETECT_ERR_FUNC("WMT-DETECT: either PMU(%d) or RST(%d) or WIFI_EINT(%d) is not set\n", + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num); + + return retval; + } + /*set LDO/PMU/RST to output 0, no pull*/ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) + _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n"); + } else + WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); + WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n"); + } else + WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + _wmt_detect_output_low(GPIO_COMBO_RST_PIN); + +#if 0 + _wmt_detect_output_high(GPIO_WIFI_EINT_PIN); +#endif + + /*pull high LDO*/ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) + _wmt_detect_output_high(GPIO_COMBO_LDO_EN_PIN); + /*sleep for LDO stable time*/ + msleep(MAX_LDO_STABLE_TIME); + + /*export RTC clock, sleep for RTC stable time*/ + rtc_gpio_enable_32k(RTC_GPIO_USER_GPS); + msleep(MAX_RTC_STABLE_TIME); + /*PMU output low, RST output low, to make chip power off completely*/ + /*always done*/ + /*sleep for power off stable time*/ + msleep(MAX_OFF_STABLE_TIME); + /*PMU output high, and sleep for reset stable time*/ + _wmt_detect_output_high(GPIO_COMBO_PMU_EN_PIN); +#ifdef CONFIG_MTK_COMBO_COMM_NPWR + if ((gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num != INVALID_PIN_ID) && + (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num != INVALID_PIN_ID)) { + msleep(20); + _wmt_detect_output_high(GPIO_PCM_DAISYNC_PIN); + + msleep(20); + _wmt_detect_output_high(GPIO_COMBO_I2S_DAT_PIN); + + msleep(20); + _wmt_detect_output_low(GPIO_COMBO_I2S_DAT_PIN); + + msleep(20); + _wmt_detect_output_low(GPIO_PCM_DAISYNC_PIN); + + msleep(20); + } +#endif + msleep(MAX_RST_STABLE_TIME); + /*RST output high, and sleep for power on stable time */ + _wmt_detect_output_high(GPIO_COMBO_RST_PIN); + msleep(MAX_ON_STABLE_TIME); + + retval = 0; + return retval; +} + +static int wmt_detect_chip_pwr_off(void) +{ + + /*set RST pin to input low status*/ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) + _wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN); + /*set RST pin to input low status*/ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) + _wmt_detect_output_low(GPIO_COMBO_RST_PIN); + /*set PMU pin to input low status*/ + if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) + _wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN); + return 0; +} + +int wmt_detect_read_ext_cmb_status(void) +{ + int retval = 0; + /*read WIFI_EINT pin status*/ + if (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num) { + retval = 0; + WMT_DETECT_ERR_FUNC("WMT-DETECT: no WIFI_EINT pin set\n"); + } else { + retval = _wmt_detect_read_gpio_input(GPIO_WIFI_EINT_PIN); + WMT_DETECT_ERR_FUNC("WMT-DETECT: WIFI_EINT input status:%d\n", retval); + } + return retval; +} + +int wmt_detect_chip_pwr_ctrl(int on) +{ + int retval = -1; + + if (0 == on) { + /*power off combo chip */ + retval = wmt_detect_chip_pwr_off(); + } else { + wmt_detect_dump_pin_conf(); + /*power on combo chip */ + retval = wmt_detect_chip_pwr_on(); + } + return retval; +} + +int wmt_detect_sdio_pwr_ctrl(int on) +{ + int retval = -1; +#ifdef MTK_WCN_COMBO_CHIP_SUPPORT + if (0 == on) { + /*power off SDIO slot */ + retval = board_sdio_ctrl(1, 0); + } else { + /*power on SDIO slot */ + retval = board_sdio_ctrl(1, 1); + } +#else + WMT_DETECT_WARN_FUNC("WMT-DETECT: MTK_WCN_COMBO_CHIP_SUPPORT is not set\n"); +#endif + return retval; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h new file mode 100644 index 0000000000000..32e661520fd0d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_detect_pwr.h @@ -0,0 +1,29 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef __WMT_DETECT_PWR_H_ +#define __WMT_DETECT_PWR_H_ + +#define MAX_RTC_STABLE_TIME 100 +#define MAX_LDO_STABLE_TIME 100 +#define MAX_RST_STABLE_TIME 30 +#define MAX_OFF_STABLE_TIME 10 +#define MAX_ON_STABLE_TIME 30 + +extern int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on); +extern int wmt_detect_chip_pwr_ctrl(int on); +extern int wmt_detect_sdio_pwr_ctrl(int on); +extern int wmt_detect_read_ext_cmb_status(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c new file mode 100644 index 0000000000000..3a79e1e9d15a9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.c @@ -0,0 +1,371 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "wmt_gpio.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX] = {{"gpio_ldo_en_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_ldo_en_in_pulldown", + ""}, + {"gpio_pmuv28_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_pmuv28_in_pulldown", + ""}, + {"gpio_pmu_en_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "gpio_pmu_en_in_pulldown", + ""}, + {"gpio_rst_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"", + "", + "", + "", + "", + "", + "", + "", + "gpio_bgf_eint_in_pulldown", + "gpio_bgf_eint_in_pullup"}, + {"", + "", + "", + "", + "", + "", + "", + "gpio_wifi_eint_in_pull_dis", + "", + "gpio_wifi_eint_in_pullup"}, + {"", + "", + "", + "", + "", + "", + "", + "", + "gpio_all_eint_in_pulldown", + "gpio_all_eint_in_pullup"}, + {"gpio_urxd_uart_pull_dis", + "", + "", + "", + "", + "", + "", + "gpio_urxd_gpio_in_pull_dis", + "", + "gpio_urxd_gpio_in_pullup"}, + {"gpio_utxd_uart_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daiclk_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daipcmin_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daipcmout_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_pcm_daisync_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_ck_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_ws_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_i2s_dat_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_gps_sync_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""}, + {"gpio_gps_lna_pull_dis", + "", + "", + "", + "", + "", + "", + "", + "", + ""} +}; + +const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX] = {"gpio_combo_ldo_en_pin", + "gpio_combo_pmuv28_en_pin", + "gpio_combo_pmu_en_pin", + "gpio_combo_rst_pin", + "gpio_combo_bgf_eint_pin", + "gpio_wifi_eint_pin", + "gpio_all_eint_pin", + "gpio_combo_urxd_pin", + "gpio_combo_utxd_pin", + "gpio_pcm_daiclk_pin", + "gpio_pcm_daipcmin_pin", + "gpio_pcm_daipcmout_pin", + "gpio_pcm_daisync_pin", + "gpio_combo_i2s_ck_pin", + "gpio_combo_i2s_ws_pin", + "gpio_combo_i2s_dat_pin", + "gpio_gps_sync_pin", + "gpio_gps_lna_pin"}; + +GPIO_CTRL_INFO gpio_ctrl_info; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_gpio_init(struct platform_device *pdev) +{ + INT32 iret = 0; + UINT32 i, j; + struct device_node *node; + + node = of_find_compatible_node(NULL, NULL, "mediatek,connectivity-combo"); + if (!node) { + for (i = 0; i < GPIO_PIN_ID_MAX; i++) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + pr_err("wmt_gpio:can't find device tree node!\n"); + iret = -1; + goto err; + } + + gpio_ctrl_info.pinctrl_info = devm_pinctrl_get(&pdev->dev); + if (gpio_ctrl_info.pinctrl_info) { + for (i = 0; i < GPIO_PIN_ID_MAX; i++) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = of_get_named_gpio(node, + gpio_pin_name[i], 0); + if (gpio_ctrl_info.gpio_ctrl_state[i].gpio_num < 0) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[i].gpio_num) { + for (j = 0; j < GPIO_STATE_MAX; j++) { + if (0 != strlen(gpio_state_name[i][j])) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = + pinctrl_lookup_state(gpio_ctrl_info.pinctrl_info, + gpio_state_name[i][j]); + } else + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; + } + } + } + + pr_err("wmt_gpio: gpio init start!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN]. + gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num, + 0); + pr_err("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN out to 0: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)); + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) { + gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num, + 0); + pr_err("wmt_gpio:set GPIO_COMBO_RST_PIN out to 0: %d!\n", + gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)); + } + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_state[GPIO_IN_PULLUP]); + pr_err("wmt_gpio:set GPIO_WIFI_EINT_PIN to GPIO_IN_PULLUP done!\n"); + } else + pr_err("wmt_gpio:set GPIO_WIFI_EINT_PIN to GPIO_IN_PULLUP fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAICLK_PIN].gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_PCM_DAICLK_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAICLK_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMIN_PIN]. + gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMIN_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMIN_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAIPCMOUT_PIN]. + gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMOUT_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAIPCMOUT_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + if (gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_state[GPIO_PULL_DIS]) { + pinctrl_select_state(gpio_ctrl_info.pinctrl_info, + gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN]. + gpio_state[GPIO_PULL_DIS]); + pr_err("wmt_gpio:set GPIO_PCM_DAISYNC_PIN to GPIO_PULL_DIS done!\n"); + } else + pr_err("wmt_gpio:set GPIO_PCM_DAISYNC_PIN to GPIO_PULL_DIS fail, is NULL!\n"); + + pr_err("wmt_gpio: gpio init done!\n"); + } else { + pr_err("wmt_gpio:can't find pinctrl dev!\n"); + iret = -1; + } +err: + return iret; +} + +INT32 wmt_gpio_deinit(VOID) +{ + INT32 iret = 0; + UINT32 i; + UINT32 j; + + for (i = 0; i < GPIO_PIN_ID_MAX; i++) { + gpio_ctrl_info.gpio_ctrl_state[i].gpio_num = DEFAULT_PIN_ID; + if (DEFAULT_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[i].gpio_num) { + for (j = 0; j < GPIO_STATE_MAX; j++) { + if (0 != strlen(gpio_state_name[i][j])) + gpio_ctrl_info.gpio_ctrl_state[i].gpio_state[j] = NULL; + } + } + } + if (gpio_ctrl_info.pinctrl_info) { + devm_pinctrl_put(gpio_ctrl_info.pinctrl_info); + gpio_ctrl_info.pinctrl_info = NULL; + } + + return iret; +} diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h new file mode 100644 index 0000000000000..cd935bfddd994 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_gpio.h @@ -0,0 +1,103 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_GPIO_H_ +#define _WMT_GPIO_H_ + +#include +#include +#include +#include +#include +#include +#include "osal.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define DEFAULT_PIN_ID (0xffffffff) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_GPIO_PIN_ID { + GPIO_COMBO_LDO_EN_PIN = 0, + GPIO_COMBO_PMUV28_EN_PIN, + GPIO_COMBO_PMU_EN_PIN, + GPIO_COMBO_RST_PIN, + GPIO_COMBO_BGF_EINT_PIN, + GPIO_WIFI_EINT_PIN, + GPIO_COMBO_ALL_EINT_PIN, + GPIO_COMBO_URXD_PIN, + GPIO_COMBO_UTXD_PIN, + GPIO_PCM_DAICLK_PIN, + GPIO_PCM_DAIPCMIN_PIN, + GPIO_PCM_DAIPCMOUT_PIN, + GPIO_PCM_DAISYNC_PIN, + GPIO_COMBO_I2S_CK_PIN, + GPIO_COMBO_I2S_WS_PIN, + GPIO_COMBO_I2S_DAT_PIN, + GPIO_GPS_SYNC_PIN, + GPIO_GPS_LNA_PIN, + GPIO_PIN_ID_MAX +} ENUM_GPIO_PIN_ID, *P_ENUM_GPIO_PIN_ID; + +typedef enum _ENUM_GPIO_STATE_ID { + GPIO_PULL_DIS = 0, + GPIO_PULL_DOWN, + GPIO_PULL_UP, + GPIO_OUT_LOW, + GPIO_OUT_HIGH, + GPIO_IN_DIS, + GPIO_IN_EN, + GPIO_IN_PULL_DIS, + GPIO_IN_PULLDOWN, + GPIO_IN_PULLUP, + GPIO_STATE_MAX, +} ENUM_GPIO_STATE_ID, *P_ENUM_GPIO_STATE_ID; + +typedef struct _GPIO_CTRL_STATE { + INT32 gpio_num; + struct pinctrl_state *gpio_state[GPIO_STATE_MAX]; +} GPIO_CTRL_STATE, *P_GPIO_CTRL_STATE; + +typedef struct _GPIO_CTRL_INFO { + struct pinctrl *pinctrl_info; + GPIO_CTRL_STATE gpio_ctrl_state[GPIO_PIN_ID_MAX]; +} GPIO_CTRL_INFO, *P_GPIO_CTRL_INFO; + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern const PUINT8 gpio_state_name[GPIO_PIN_ID_MAX][GPIO_STATE_MAX]; +extern const PUINT8 gpio_pin_name[GPIO_PIN_ID_MAX]; +extern GPIO_CTRL_INFO gpio_ctrl_info; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +INT32 wmt_gpio_init(struct platform_device *pdev); + +INT32 wmt_gpio_deinit(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c new file mode 100644 index 0000000000000..4fc3144b3ba6c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.c @@ -0,0 +1,480 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +#include "osal_typedef.h" +#include "wmt_stp_exp.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-STP-EXP]" + +#define WMT_STP_EXP_INFO_FUNC(fmt, arg...) pr_debug(DFT_TAG "[I]%s: " fmt, __func__ , ##arg) +#define WMT_STP_EXP_WARN_FUNC(fmt, arg...) pr_warn(DFT_TAG "[W]%s: " fmt, __func__ , ##arg) +#define WMT_STP_EXP_ERR_FUNC(fmt, arg...) pr_err(DFT_TAG "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +/*STP exp*/ +MTK_WCN_STP_SEND_DATA mtk_wcn_stp_send_data_f = NULL; +MTK_WCN_STP_SEND_DATA mtk_wcn_stp_send_data_raw_f = NULL; +MTK_WCN_STP_PARSER_DATA mtk_wcn_stp_parser_data_f = NULL; +MTK_WCN_STP_RECV_DATA mtk_wcn_stp_receive_data_f = NULL; +MTK_WCN_STP_IS_RXQ_EMPTY mtk_wcn_stp_is_rxqueue_empty_f = NULL; +MTK_WCN_STP_IS_RDY mtk_wcn_stp_is_ready_f = NULL; +MTK_WCN_STP_SET_BLUEZ mtk_wcn_stp_set_bluez_f = NULL; +MTK_WCN_STP_REG_IF_TX mtk_wcn_stp_if_tx_f = NULL; +MTK_WCN_STP_REG_IF_RX mtk_wcn_stp_if_rx_f = NULL; +MTK_WCN_STP_REG_EVENT_CB mtk_wcn_stp_reg_event_cb_f = NULL; +MTK_WCN_STP_RGE_TX_EVENT_CB mtk_wcn_stp_reg_tx_event_cb_f = NULL; +MTK_WCN_STP_COREDUMP_START_GET mtk_wcn_stp_coredump_start_get_f = NULL; + +/*WMT exp*/ +MTK_WCN_WMT_FUNC_CTRL mtk_wcn_wmt_func_on_f = NULL; +MTK_WCN_WMT_FUNC_CTRL mtk_wcn_wmt_func_off_f = NULL; +MTK_WCN_WMT_THERM_CTRL mtk_wcn_wmt_therm_ctrl_f = NULL; +MTK_WCN_WMT_HWVER_GET mtk_wcn_wmt_hwver_get_f = NULL; +MTK_WCN_WMT_DSNS_CTRL mtk_wcn_wmt_dsns_ctrl_f = NULL; +MTK_WCN_WMT_MSGCB_REG mtk_wcn_wmt_msgcb_reg_f = NULL; +MTK_WCN_WMT_MSGCB_UNREG mtk_wcn_wmt_msgcb_unreg_f = NULL; +MTK_WCN_WMT_SDIO_OP_REG mtk_wcn_wmt_sdio_op_reg_f = NULL; +MTK_WCN_WMT_SDIO_HOST_AWAKE mtk_wcn_wmt_sdio_host_awake_f = NULL; +MTK_WCN_WMT_ASSERT mtk_wcn_wmt_assert_f = NULL; +MTK_WCN_WMT_ASSERT_TIMEOUT mtk_wcn_wmt_assert_timeout_f = NULL; +MTK_WCN_WMT_IC_INFO_GET mtk_wcn_wmt_ic_info_get_f = NULL; +MTK_WCN_WMT_PSM_CTRL mtk_wcn_wmt_psm_ctrl_f = NULL; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +UINT32 mtk_wcn_stp_exp_cb_reg(P_MTK_WCN_STP_EXP_CB_INFO pStpExpCb) +{ + WMT_STP_EXP_INFO_FUNC("call stp exp cb reg\n"); + + mtk_wcn_stp_send_data_f = pStpExpCb->stp_send_data_cb; + mtk_wcn_stp_send_data_raw_f = pStpExpCb->stp_send_data_raw_cb; + mtk_wcn_stp_parser_data_f = pStpExpCb->stp_parser_data_cb; + mtk_wcn_stp_receive_data_f = pStpExpCb->stp_receive_data_cb; + mtk_wcn_stp_is_rxqueue_empty_f = pStpExpCb->stp_is_rxqueue_empty_cb; + mtk_wcn_stp_is_ready_f = pStpExpCb->stp_is_ready_cb; + mtk_wcn_stp_set_bluez_f = pStpExpCb->stp_set_bluez_cb; + mtk_wcn_stp_if_tx_f = pStpExpCb->stp_if_tx_cb; + mtk_wcn_stp_if_rx_f = pStpExpCb->stp_if_rx_cb; + mtk_wcn_stp_reg_event_cb_f = pStpExpCb->stp_reg_event_cb; + mtk_wcn_stp_reg_tx_event_cb_f = pStpExpCb->stp_reg_tx_event_cb; + mtk_wcn_stp_coredump_start_get_f = pStpExpCb->stp_coredump_start_get_cb; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_stp_exp_cb_reg); + +UINT32 mtk_wcn_stp_exp_cb_unreg(VOID) +{ + WMT_STP_EXP_INFO_FUNC("call stp exp cb unreg\n"); + + mtk_wcn_stp_send_data_f = NULL; + mtk_wcn_stp_send_data_raw_f = NULL; + mtk_wcn_stp_parser_data_f = NULL; + mtk_wcn_stp_receive_data_f = NULL; + mtk_wcn_stp_is_rxqueue_empty_f = NULL; + mtk_wcn_stp_is_ready_f = NULL; + mtk_wcn_stp_set_bluez_f = NULL; + mtk_wcn_stp_if_tx_f = NULL; + mtk_wcn_stp_if_rx_f = NULL; + mtk_wcn_stp_reg_event_cb_f = NULL; + mtk_wcn_stp_reg_tx_event_cb_f = NULL; + mtk_wcn_stp_coredump_start_get_f = NULL; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_stp_exp_cb_unreg); + +INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_send_data_f) { + ret = (*mtk_wcn_stp_send_data_f) (buffer, length, type); + /* WMT_STP_EXP_INFO_FUNC("mtk_wcn_stp_send_data_f send data(%d)\n",ret); */ + } else { + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_send_data_f cb is null\n"); + } + + return ret; + +} +EXPORT_SYMBOL(mtk_wcn_stp_send_data); + +INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_send_data_raw_f) + ret = (*mtk_wcn_stp_send_data_raw_f) (buffer, length, type); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_send_data_raw_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); + +INT32 mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_parser_data_f) + ret = (*mtk_wcn_stp_parser_data_f) (buffer, length); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_parser_data_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_parser_data); + +INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_receive_data_f) + ret = (*mtk_wcn_stp_receive_data_f) (buffer, length, type); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_receive_data_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_receive_data); + +MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_stp_is_rxqueue_empty_f) + ret = (*mtk_wcn_stp_is_rxqueue_empty_f) (type); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_is_rxqueue_empty_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); + +MTK_WCN_BOOL mtk_wcn_stp_is_ready(void) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_stp_is_ready_f) + ret = (*mtk_wcn_stp_is_ready_f) (); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_is_ready_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_is_ready); + +void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL flags) +{ + + if (mtk_wcn_stp_set_bluez_f) + (*mtk_wcn_stp_set_bluez_f) (flags); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_set_bluez_f cb is null\n"); + +} +EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); + +INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_if_tx_f) + ret = (*mtk_wcn_stp_if_tx_f) (stp_if, func); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_if_tx_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); + +INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_if_rx_f) + ret = (*mtk_wcn_stp_if_rx_f) (func); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_if_rx_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); + +INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_reg_event_cb_f) + ret = (*mtk_wcn_stp_reg_event_cb_f) (type, func); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_reg_event_cb_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); + +INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_reg_tx_event_cb_f) + ret = (*mtk_wcn_stp_reg_tx_event_cb_f) (type, func); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_reg_tx_event_cb_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); + +INT32 mtk_wcn_stp_coredump_start_get(VOID) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_coredump_start_get_f) + ret = (*mtk_wcn_stp_coredump_start_get_f) (); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_stp_coredump_start_get_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_coredump_start_get); + +UINT32 mtk_wcn_wmt_exp_cb_reg(P_MTK_WCN_WMT_EXP_CB_INFO pWmtExpCb) +{ + WMT_STP_EXP_INFO_FUNC("call wmt exp cb reg\n"); + + mtk_wcn_wmt_func_on_f = pWmtExpCb->wmt_func_on_cb; + mtk_wcn_wmt_func_off_f = pWmtExpCb->wmt_func_off_cb; + mtk_wcn_wmt_therm_ctrl_f = pWmtExpCb->wmt_therm_ctrl_cb; + mtk_wcn_wmt_hwver_get_f = pWmtExpCb->wmt_hwver_get_cb; + mtk_wcn_wmt_dsns_ctrl_f = pWmtExpCb->wmt_dsns_ctrl_cb; + mtk_wcn_wmt_msgcb_reg_f = pWmtExpCb->wmt_msgcb_reg_cb; + mtk_wcn_wmt_msgcb_unreg_f = pWmtExpCb->wmt_msgcb_unreg_cb; + mtk_wcn_wmt_sdio_op_reg_f = pWmtExpCb->wmt_sdio_op_reg_cb; + mtk_wcn_wmt_sdio_host_awake_f = pWmtExpCb->wmt_sdio_host_awake_cb; + mtk_wcn_wmt_assert_f = pWmtExpCb->wmt_assert_cb; + mtk_wcn_wmt_assert_timeout_f = pWmtExpCb->wmt_assert_timeout_cb; + mtk_wcn_wmt_ic_info_get_f = pWmtExpCb->wmt_ic_info_get_cb; + mtk_wcn_wmt_psm_ctrl_f = pWmtExpCb->wmt_psm_ctrl_cb; + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_exp_cb_reg); + +UINT32 mtk_wcn_wmt_exp_cb_unreg(VOID) +{ + WMT_STP_EXP_INFO_FUNC("call wmt exp cb unreg\n"); + + mtk_wcn_wmt_func_on_f = NULL; + mtk_wcn_wmt_func_off_f = NULL; + mtk_wcn_wmt_therm_ctrl_f = NULL; + mtk_wcn_wmt_hwver_get_f = NULL; + mtk_wcn_wmt_dsns_ctrl_f = NULL; + mtk_wcn_wmt_msgcb_reg_f = NULL; + mtk_wcn_wmt_msgcb_unreg_f = NULL; + mtk_wcn_wmt_sdio_op_reg_f = NULL; + mtk_wcn_wmt_sdio_host_awake_f = NULL; + mtk_wcn_wmt_assert_f = NULL; + mtk_wcn_wmt_assert_timeout_f = NULL; + mtk_wcn_wmt_ic_info_get_f = NULL; + mtk_wcn_wmt_psm_ctrl_f = NULL; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_exp_cb_unreg); + +MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_wmt_func_off_f) + ret = (*mtk_wcn_wmt_func_off_f) (type); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_func_off_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_func_off); + +MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_wmt_func_on_f) { + ret = (*mtk_wcn_wmt_func_on_f) (type); + WMT_STP_EXP_INFO_FUNC("mtk_wcn_wmt_func_on_f type(%d)\n", type); + } else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_func_on_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_func_on); + +INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) +{ + INT32 ret = -1; + + if (mtk_wcn_wmt_therm_ctrl_f) + ret = (*mtk_wcn_wmt_therm_ctrl_f) (eType); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_therm_ctrl_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); + +ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID) +{ + ENUM_WMTHWVER_TYPE_T ret = WMTHWVER_INVALID; + + if (mtk_wcn_wmt_hwver_get_f) + ret = (*mtk_wcn_wmt_hwver_get_f) (); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_hwver_get_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); + +MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_wmt_dsns_ctrl_f) + ret = (*mtk_wcn_wmt_dsns_ctrl_f) (eType); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_dsns_ctrl_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); + +INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) +{ + INT32 ret = 0; + + if (mtk_wcn_wmt_msgcb_reg_f) + ret = (*mtk_wcn_wmt_msgcb_reg_f) (eType, pCb); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_msgcb_reg_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); + +INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) +{ + INT32 ret = 0; + + if (mtk_wcn_wmt_msgcb_unreg_f) + ret = (*mtk_wcn_wmt_msgcb_unreg_f) (eType); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_msgcb_unreg_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); + +INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) +{ + INT32 ret = -1; + + if (mtk_wcn_wmt_sdio_op_reg_f) + ret = (*mtk_wcn_wmt_sdio_op_reg_f) (own_cb); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_sdio_op_reg_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); + +INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID) +{ + INT32 ret = -1; + + if (mtk_wcn_wmt_sdio_host_awake_f) + ret = (*mtk_wcn_wmt_sdio_host_awake_f) (); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_sdio_host_awake_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); + +MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_wmt_assert_f) + ret = (*mtk_wcn_wmt_assert_f) (type, reason); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_assert_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_assert); + +MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, UINT32 reason, INT32 timeout) +{ + MTK_WCN_BOOL ret = MTK_WCN_BOOL_FALSE; + + if (mtk_wcn_wmt_assert_timeout_f) + ret = (*mtk_wcn_wmt_assert_timeout_f)(type, reason, timeout); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_assert_timeout_f cb is null\n"); + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_assert_timeout); + +UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type) +{ + UINT32 ret = 0; + + if (mtk_wcn_wmt_ic_info_get_f) + ret = (*mtk_wcn_wmt_ic_info_get_f) (type); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_ic_info_get_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_ic_info_get); + +INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag) +{ + UINT32 ret = 0; + + if (mtk_wcn_wmt_psm_ctrl_f) + ret = (*mtk_wcn_wmt_psm_ctrl_f)(flag); + else + WMT_STP_EXP_ERR_FUNC("mtk_wcn_wmt_psm_ctrl_f cb is null\n"); + + return ret; +} +EXPORT_SYMBOL(mtk_wcn_wmt_psm_ctrl); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h new file mode 100644 index 0000000000000..1c3dc89652981 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/common_detect/wmt_stp_exp.h @@ -0,0 +1,610 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_STP_EXP_H_ +#define _WMT_STP_EXP_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "osal_typedef.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 0 +#endif + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +#if (WMT_IDC_SUPPORT) +#define CFG_WMT_LTE_COEX_HANDLING 1 +#define CFG_WMT_LTE_ENABLE_MSGID_MAPPING 0 +#else +#define CFG_WMT_LTE_COEX_HANDLING 0 +#endif + +/*from stp_exp.h*/ +#define BT_TASK_INDX (0) +#define FM_TASK_INDX (1) +#define GPS_TASK_INDX (2) +#define WIFI_TASK_INDX (3) +#define WMT_TASK_INDX (4) +#define STP_TASK_INDX (5) +#define INFO_TASK_INDX (6) +#define ANT_TASK_INDX (7) +#if CFG_WMT_LTE_COEX_HANDLING +#define COEX_TASK_INDX (8) +#define MTKSTP_MAX_TASK_NUM (9) +#else +#define MTKSTP_MAX_TASK_NUM (8) +#endif + +#define MTKSTP_BUFFER_SIZE (16384) /* Size of RX Queue */ +/*end from stp_exp.h*/ + +/******************************************************************************* +* D A T A T Y P E S +********************************************************************************/ + +/*moved from stp_exp.h*/ +typedef void (*MTK_WCN_STP_EVENT_CB) (void); +typedef INT32(*MTK_WCN_STP_IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); +/* export for HIF driver */ +typedef void (*MTK_WCN_STP_IF_RX) (const PUINT8 data, INT32 size); + +typedef enum { + STP_UART_IF_TX = 0, + STP_SDIO_IF_TX = 1, + STP_BTIF_IF_TX = 2, + STP_MAX_IF_TX +} ENUM_STP_TX_IF_TYPE; + +/*end moved from stp_exp.h*/ + +typedef INT32(*MTK_WCN_STP_SEND_DATA) (const PUINT8 buffer, const UINT32 length, const UINT8 type); +typedef INT32(*MTK_WCN_STP_PARSER_DATA) (PUINT8 buffer, UINT32 length); +typedef INT32(*MTK_WCN_STP_RECV_DATA) (PUINT8 buffer, UINT32 length, UINT8 type); +typedef MTK_WCN_BOOL(*MTK_WCN_STP_IS_RXQ_EMPTY) (UINT8 type); +typedef MTK_WCN_BOOL(*MTK_WCN_STP_IS_RDY) (VOID); +typedef VOID(*MTK_WCN_STP_SET_BLUEZ) (MTK_WCN_BOOL flags); +typedef INT32(*MTK_WCN_STP_REG_IF_TX) (ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); +typedef INT32(*MTK_WCN_STP_REG_IF_RX) (MTK_WCN_STP_IF_RX func); +typedef INT32(*MTK_WCN_STP_REG_EVENT_CB) (INT32 type, MTK_WCN_STP_EVENT_CB func); +typedef INT32(*MTK_WCN_STP_RGE_TX_EVENT_CB) (INT32 type, MTK_WCN_STP_EVENT_CB func); +typedef INT32(*MTK_WCN_STP_COREDUMP_START_GET)(VOID); + +typedef struct _MTK_WCN_STP_EXP_CB_INFO_ { + MTK_WCN_STP_SEND_DATA stp_send_data_cb; + MTK_WCN_STP_SEND_DATA stp_send_data_raw_cb; + MTK_WCN_STP_PARSER_DATA stp_parser_data_cb; + MTK_WCN_STP_RECV_DATA stp_receive_data_cb; + MTK_WCN_STP_IS_RXQ_EMPTY stp_is_rxqueue_empty_cb; + MTK_WCN_STP_IS_RDY stp_is_ready_cb; + MTK_WCN_STP_SET_BLUEZ stp_set_bluez_cb; + MTK_WCN_STP_REG_IF_TX stp_if_tx_cb; + MTK_WCN_STP_REG_IF_RX stp_if_rx_cb; + MTK_WCN_STP_REG_EVENT_CB stp_reg_event_cb; + MTK_WCN_STP_RGE_TX_EVENT_CB stp_reg_tx_event_cb; + MTK_WCN_STP_COREDUMP_START_GET stp_coredump_start_get_cb; +} MTK_WCN_STP_EXP_CB_INFO, *P_MTK_WCN_STP_EXP_CB_INFO; + +/*moved from wmt_exp.h*/ + +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_ANT = 5, + WMTDRV_TYPE_STP = 6, + WMTDRV_TYPE_SDIO1 = 7, + WMTDRV_TYPE_SDIO2 = 8, + WMTDRV_TYPE_LPBK = 9, + WMTDRV_TYPE_COREDUMP = 10, +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK + WMTDRV_TYPE_AUTOK = 11, +#endif + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +typedef enum _ENUM_WMTDSNS_TYPE_T { + WMTDSNS_FM_DISABLE = 0, + WMTDSNS_FM_ENABLE = 1, + WMTDSNS_FM_GPS_DISABLE = 2, + WMTDSNS_FM_GPS_ENABLE = 3, + WMTDSNS_MAX +} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; + +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_E1 = 0x0, + WMTHWVER_E2 = 0x1, + WMTHWVER_E3 = 0x2, + WMTHWVER_E4 = 0x3, + WMTHWVER_E5 = 0x4, + WMTHWVER_E6 = 0x5, + WMTHWVER_E7 = 0x6, + WMTHWVER_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +typedef enum _ENUM_WMTTHERM_TYPE_T { + WMTTHERM_ZERO = 0, + WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, + WMTTHERM_READ = WMTTHERM_ENABLE + 1, + WMTTHERM_DISABLE = WMTTHERM_READ + 1, + WMTTHERM_MAX +} ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY = 3, + WMTMSG_TYPE_HW_FUNC_ON = 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + +typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + VOID *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client + can't touch this buffer after this function return. */ + UINT32 /* Buffer size in unit of byte */ +); + +typedef enum _SDIO_PS_OP { + OWN_SET = 0, + OWN_CLR = 1, + OWN_STATE = 2, +} SDIO_PS_OP; + +typedef INT32(*PF_WMT_SDIO_PSOP) (SDIO_PS_OP); + +typedef enum _ENUM_WMTCHIN_TYPE_T { + WMTCHIN_CHIPID = 0x0, + WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, + WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, + WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, + WMTCHIN_MAX, + +} ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; + +/*end moved from wmt_exp.h*/ + +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_FUNC_CTRL) (ENUM_WMTDRV_TYPE_T type); +typedef INT8(*MTK_WCN_WMT_THERM_CTRL) (ENUM_WMTTHERM_TYPE_T eType); +typedef ENUM_WMTHWVER_TYPE_T(*MTK_WCN_WMT_HWVER_GET) (VOID); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_DSNS_CTRL) (ENUM_WMTDSNS_TYPE_T eType); +typedef INT32(*MTK_WCN_WMT_MSGCB_REG) (ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); +typedef INT32(*MTK_WCN_WMT_MSGCB_UNREG) (ENUM_WMTDRV_TYPE_T eType); +typedef INT32(*MTK_WCN_WMT_SDIO_OP_REG) (PF_WMT_SDIO_PSOP own_cb); +typedef INT32(*MTK_WCN_WMT_SDIO_HOST_AWAKE) (VOID); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT) (ENUM_WMTDRV_TYPE_T type, UINT32 reason); +typedef MTK_WCN_BOOL(*MTK_WCN_WMT_ASSERT_TIMEOUT)(ENUM_WMTDRV_TYPE_T type, + UINT32 reason, INT32 timeout); +typedef UINT32(*MTK_WCN_WMT_IC_INFO_GET) (ENUM_WMT_CHIPINFO_TYPE_T type); +typedef INT32 (*MTK_WCN_WMT_PSM_CTRL)(MTK_WCN_BOOL flag); + +typedef struct _MTK_WCN_WMT_EXP_CB_INFO_ { + MTK_WCN_WMT_FUNC_CTRL wmt_func_on_cb; + MTK_WCN_WMT_FUNC_CTRL wmt_func_off_cb; + MTK_WCN_WMT_THERM_CTRL wmt_therm_ctrl_cb; + MTK_WCN_WMT_HWVER_GET wmt_hwver_get_cb; + MTK_WCN_WMT_DSNS_CTRL wmt_dsns_ctrl_cb; + MTK_WCN_WMT_MSGCB_REG wmt_msgcb_reg_cb; + MTK_WCN_WMT_MSGCB_UNREG wmt_msgcb_unreg_cb; + MTK_WCN_WMT_SDIO_OP_REG wmt_sdio_op_reg_cb; + MTK_WCN_WMT_SDIO_HOST_AWAKE wmt_sdio_host_awake_cb; + MTK_WCN_WMT_ASSERT wmt_assert_cb; + MTK_WCN_WMT_ASSERT_TIMEOUT wmt_assert_timeout_cb; + MTK_WCN_WMT_IC_INFO_GET wmt_ic_info_get_cb; + MTK_WCN_WMT_PSM_CTRL wmt_psm_ctrl_cb; +} MTK_WCN_WMT_EXP_CB_INFO, *P_MTK_WCN_WMT_EXP_CB_INFO; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*exp for WMT/STP register callback*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_exp_cb_reg +* DESCRIPTION +* stp driver reigster exp symbols +* PARAMETERS +* pStpExpCb [IN] stp callback structure pointer +* RETURNS +* UINT32 = 0: OK +*****************************************************************************/ +UINT32 mtk_wcn_stp_exp_cb_reg(P_MTK_WCN_STP_EXP_CB_INFO pStpExpCb); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_exp_cb_unreg +* DESCRIPTION +* stp driver unreigster exp symbols +* PARAMETERS +* VOID +* RETURNS +* UINT32 = 0: OK +*****************************************************************************/ +UINT32 mtk_wcn_stp_exp_cb_unreg(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_exp_cb_reg +* DESCRIPTION +* WMT driver reigster exp symbols +* PARAMETERS +* pStpExpCb [IN] wmt callback structure pointer +* RETURNS +* UINT32 = 0: OK +*****************************************************************************/ +UINT32 mtk_wcn_wmt_exp_cb_reg(P_MTK_WCN_WMT_EXP_CB_INFO pWmtExpCb); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_exp_cb_unreg +* DESCRIPTION +* wmt driver unreigster exp symbols +* PARAMETERS +* VOID +* RETURNS +* UINT32 = 0: OK +*****************************************************************************/ +UINT32 mtk_wcn_wmt_exp_cb_unreg(VOID); + +/*stp exp symbols*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* subfunction send data through STP without seq/ack +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +extern INT32 mtk_wcn_stp_parser_data(PUINT8 buffer, UINT32 length); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* Is STP ready? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:ready, FALSE:not ready +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(void); + +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL flags); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_tx +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_rx +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_event_cb +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* func +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_tx_event_cb +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* func +* RETURNS +* INT32: 0:successful , -1: fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get coredump flag is set or not +* PARAMETERS +* VOID +* RETURNS +* INT32: 0:coredump flag is not set , 1: coredump flag is set +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_get(VOID); + +/*wmt exp symbols*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_func_off +* DESCRIPTION +* wmt turn off subsystem +* PARAMETERS +* type [IN] subsystem type +* RETURNS +* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_func_on +* DESCRIPTION +* wmt turn on subsystem +* PARAMETERS +* type [IN] subsystem type +* RETURNS +* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_therm_ctrl +* DESCRIPTION +* query chip temperature by WMT CMD +* PARAMETERS +* eType [IN] thermal ctrl type +* RETURNS +* >=0: chip temperature; 0xff:error +*****************************************************************************/ +extern INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_hwver_get +* DESCRIPTION +* get chip hardware version +* PARAMETERS +* VOID +* RETURNS +* >=0: chip hw version; 0xff:error +*****************************************************************************/ +extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_ic_info_get +* DESCRIPTION +* get chip hardware version or f/w version +* PARAMETERS +* type : which kind of information is needed +* RETURNS +* f/w version or hw version information +*****************************************************************************/ +extern UINT32 mtk_wcn_wmt_ic_info_get(ENUM_WMT_CHIPINFO_TYPE_T type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_dsns_ctrl +* DESCRIPTION +* fm dsns cmd ctrl +* PARAMETERS +* eType [IN] fm dsns ctrl type +* RETURNS +* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_msgcb_reg +* DESCRIPTION +* used for subsystem register chip reset callback for received wmt reset msg. +* PARAMETERS +* eType [IN] subsystem type +* pCb [IN] rst callback +* RETURNS +* 1: OK; 0:error +*****************************************************************************/ +extern INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_msgcb_unreg +* DESCRIPTION +* used for subsystem unregister chip reset callback for received wmt reset msg. +* PARAMETERS +* eType [IN] subsystem type +* RETURNS +* 1: OK; 0:error +*****************************************************************************/ +extern INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_wmt_sdio_op_reg +* DESCRIPTION +* used to register callback for set sdio ownership. +* PARAMETERS +* own_cb [IN] set owner ship callback +* RETURNS +* always return 0; +*****************************************************************************/ +extern INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_wmt_sdio_host_awake +* DESCRIPTION +* handing host awake when link is stp sdio? +* PARAMETERS +* VOID +* RETURNS +* always return 0; +*****************************************************************************/ +extern INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_assert +* DESCRIPTION +* host trigger firmware assert +* PARAMETERS +* type [IN] subsystem driver type +* reason [IN] trigger assert reason +* RETURNS +* MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); + +/***************************************************************************** + * * FUNCTION + * * mtk_wcn_wmt_assert_timeout + * * DESCRIPTION + * * host trigger firmware assert + * * PARAMETERS + * * type [IN] subsystem driver type + * * reason [IN] trigger assert reason + * * timeout [IN] trigger assert timeout data + * * RETURNS + * * MTK_WCN_BOOL_TRUE: OK; MTK_WCN_BOOL_FALSE:error + * *****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_wmt_assert_timeout(ENUM_WMTDRV_TYPE_T type, + UINT32 reason, INT32 timeout); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmt_psm_ctrl +* DESCRIPTION +* disable/enable psm +* PARAMETERS +* flag [IN] disable:0, enable:1 +* RETURNS +* always return 0; +*****************************************************************************/ +extern INT32 mtk_wcn_wmt_psm_ctrl(MTK_WCN_BOOL flag); + +#endif + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile new file mode 100644 index 0000000000000..286bfd4bfed36 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/Makefile @@ -0,0 +1,65 @@ +subdir-ccflags-y += \ + -I$(src)/linux/include \ + -I$(src)/linux/pri/include \ + -I$(src)/core/include \ + -I$(src)/include \ + -I$(src)/../common_detect \ + -I$(srctree)/drivers/misc/mediatek/btif/common/inc + +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/ +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eccci/$(MTK_PLATFORM) +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/eemcs/ +subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/conn_md/include + +EXT_FLAG=_soc +COMMON_SRC_PATH := $(src) +COMMON_OBJ_PATH := $(src) + +ifeq ($(CONFIG_ARCH_MT6580), y) +subdir-ccflags-y += -D CFG_WMT_READ_EFUSE_VCN33 +endif + +ifeq ($(CONFIG_MTK_COMBO), m) +# WMT DRIVER +obj-$(CONFIG_MTK_COMBO) += mtk_stp_wmt$(EXT_FLAG).o +# WMT DRIVER-core part +mtk_stp_wmt$(EXT_FLAG)-objs := core/wmt_core.o core/wmt_ctrl.o core/wmt_func.o core/wmt_ic_soc.o core/wmt_lib.o core/wmt_conf.o + + +# WMT DRIVER-linux private part +mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/wmt_dev.o linux/pri/wmt_exp.o +mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/stp_btif.o + + +# WMT DRIVER-OSAL +mtk_stp_wmt$(EXT_FLAG)-objs += linux/pub/osal.o linux/pub/bgw_desense.o +# WMT DRIVER-platform implementation +# ccflags-y += -D WMT_PLAT_ALPS +# mtk_stp_wmt$(EXT_FLAG)-objs += platform/alps/wmt_plat_alps.o + +# mtk_stp_wmt$(EXT_FLAG)-objs += platform/alps/mtk_wcn_consys_hw.o + + +mtk_stp_wmt$(EXT_FLAG)-objs += linux/pri/stp_exp.o core/stp_core.o core/psm_core.o core/btm_core.o linux/pri/stp_dbg.o + +# WMT stub part (built-in kernel image) +# obj-y += platform/alps/mtk_wcn_consys_stub_alps.o + + + +obj-$(CONFIG_MTK_COMBO_BT) += mtk_stp_bt$(EXT_FLAG).o +mtk_stp_bt$(EXT_FLAG)-objs := linux/pub/stp_chrdev_bt.o + + +obj-$(CONFIG_MTK_COMBO_WIFI) += mtk_wmt_wifi$(EXT_FLAG).o +mtk_wmt_wifi$(EXT_FLAG)-objs := linux/pub/wmt_chrdev_wifi.o + +endif + +ifeq ($(CONFIG_MTK_COMBO), y) +# subdir-ccflags-y += -D WMT_PLAT_ALPS +obj-y += core/ +obj-y += linux/ +#obj-y += $(subst ",,$(CONFIG_MTK_PLATFORM))/ +obj-y += mt7623/ +endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile new file mode 100644 index 0000000000000..9df71b9e163ea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/Makefile @@ -0,0 +1,22 @@ +ifeq ($(CONFIG_MTK_COMBO), y) + +ccflags-y += \ + -I$(src)/../linux/include \ + -I$(src)/../linux/pri/include \ + -I$(src)/../core/include \ + -I$(src)/../include \ + -I$(src)/../../common_detect \ + -I$(srctree)/drivers/misc/mediatek/btif/common/inc \ + +obj-y += wmt_core.o \ + wmt_ctrl.o \ + wmt_func.o \ + wmt_ic_soc.o \ + wmt_lib.o \ + wmt_conf.o \ + btm_core.o \ + dbg_core.o \ + psm_core.o \ + stp_core.o + +endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c new file mode 100644 index 0000000000000..4946b682d8266 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/btm_core.c @@ -0,0 +1,1376 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +#include + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_dbg.h" +#include "stp_core.h" +#include "btm_core.h" +#include "wmt_plat.h" + +#define PFX_BTM "[STP-BTM] " +#define STP_BTM_LOG_LOUD 4 +#define STP_BTM_LOG_DBG 3 +#define STP_BTM_LOG_INFO 2 +#define STP_BTM_LOG_WARN 1 +#define STP_BTM_LOG_ERR 0 + +INT32 gBtmDbgLevel = STP_BTM_LOG_INFO; + +#define STP_BTM_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_LOUD) \ + pr_debug(PFX_BTM "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_BTM_DBG_FUNC(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_DBG) \ + pr_debug(PFX_BTM "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_BTM_INFO_FUNC(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_INFO) \ + pr_debug(PFX_BTM "[I]%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_BTM_WARN_FUNC(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_WARN) \ + pr_warn(PFX_BTM "[W]%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_BTM_ERR_FUNC(fmt, arg...) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_ERR) \ + pr_err(PFX_BTM "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg); \ +} while (0) +#define STP_BTM_TRC_FUNC(f) \ +do { \ + if (gBtmDbgLevel >= STP_BTM_LOG_DBG) \ + pr_debug(PFX_BTM "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +#define ASSERT(expr) + +MTKSTP_BTM_T stp_btm_i; +MTKSTP_BTM_T *stp_btm = &stp_btm_i; + +const char *g_btm_op_name[] = { + "STP_OPID_BTM_RETRY", + "STP_OPID_BTM_RST", + "STP_OPID_BTM_DBG_DUMP", + "STP_OPID_BTM_DUMP_TIMEOUT", + "STP_OPID_BTM_POLL_CPUPCR", + "STP_OPID_BTM_PAGED_DUMP", + "STP_OPID_BTM_FULL_DUMP", + "STP_OPID_BTM_PAGED_TRACE", + "STP_OPID_BTM_FORCE_FW_ASSERT", +#if CFG_WMT_LTE_COEX_HANDLING + "STP_OPID_BTM_WMT_LTE_COEX", +#endif + "STP_OPID_BTM_EXIT" +}; + +#if 0 +static char *_stp_pkt_type(int type) +{ + + static char s[10]; + + switch (type) { + case WMT_TASK_INDX: + osal_memcpy(s, "WMT", strlen("WMT") + 1); + break; + case BT_TASK_INDX: + osal_memcpy(s, "BT", strlen("BT") + 1); + break; + case GPS_TASK_INDX: + osal_memcpy(s, "GPS", strlen("GPS") + 1); + break; + case FM_TASK_INDX: + osal_memcpy(s, "FM", strlen("FM") + 1); + break; + default: + osal_memcpy(s, "UNKNOWN", strlen("UNKNOWN") + 1); + break; + } + + return s; +} +#endif + +static INT32 _stp_btm_put_dump_to_nl(void) +{ +#define NUM_FETCH_ENTRY 8 + + static UINT8 buf[2048]; + static UINT8 tmp[2048]; + + UINT32 buf_len; + STP_PACKET_T *pkt; + STP_DBG_HDR_T *hdr; + INT32 len; + INT32 remain = 0, index = 0; + INT32 retry = 0, rc = 0, nl_retry = 0; + + STP_BTM_INFO_FUNC("Enter..\n"); + + index = 0; + tmp[index++] = '['; + tmp[index++] = 'M'; + tmp[index++] = ']'; + + do { + index = 3; + remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); + if (buf_len > 0) { + pkt = (STP_PACKET_T *) buf; + hdr = &pkt->hdr; + len = pkt->hdr.len; + osal_memcpy(&tmp[index], &len, 2); + index += 2; + if (hdr->dbg_type == STP_DBG_FW_DMP) { + osal_memcpy(&tmp[index], pkt->raw, len); + + if (len <= 1500) { + /* pr_warn("\n%s\n+++\n", tmp); */ + /* pr_warn("send coredump len:%d\n", len); */ + /* pr_warn("send coredump:%s\n", tmp); */ + rc = stp_dbg_nl_send((PINT8)&tmp, 2, len+5); + + while (rc) { + nl_retry++; + if (nl_retry > 1000) + break; + STP_BTM_WARN_FUNC + ("**dump send fails, and retry again.**\n"); + osal_sleep_ms(3); + rc = stp_dbg_nl_send((PINT8)&tmp, 2, len+5); + if (!rc) + STP_BTM_WARN_FUNC("****retry again ok!**\n"); + } + /* schedule(); */ + } else { + STP_BTM_INFO_FUNC("dump entry length is over long\n"); + BUG_ON(0); + } + retry = 0; + } + } else { + retry++; + osal_sleep_ms(100); + } + } while ((remain > 0) || (retry < 2)); + + STP_BTM_INFO_FUNC("Exit..\n"); + return 0; +} + +#define SUB_PKT_SIZE 1024 +#define SUB_PKT_HEADER 5 /*'[M]',3Bytes; len,2Bytes*/ + +INT32 _stp_btm_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len) +{ + static UINT8 tmp[SUB_PKT_SIZE + SUB_PKT_HEADER]; + + INT32 remain = dump_len, index = 0; + INT32 rc = 0, nl_retry = 0; + INT32 len; + INT32 offset = 0; + + STP_BTM_INFO_FUNC("Enter..\n"); + + if (dump_len > 0) { + index = 0; + tmp[index++] = '['; + tmp[index++] = 'M'; + tmp[index++] = ']'; + + do { + index = 3; + if (remain >= SUB_PKT_SIZE) + len = SUB_PKT_SIZE; + else + len = remain; + remain -= len; + + osal_memcpy(&tmp[index], &len, 2); + index += 2; + osal_memcpy(&tmp[index], data_buf + offset, len); + offset += len; + STP_BTM_DBG_FUNC + ("send %d remain %d\n", len, remain); + + rc = stp_dbg_nl_send((PINT8)&tmp, 2, len + SUB_PKT_HEADER); + while (rc) { + nl_retry++; + if (nl_retry > 1000) + break; + STP_BTM_WARN_FUNC + ("**dump send fails, and retry again.**\n"); + osal_sleep_ms(3); + rc = stp_dbg_nl_send((PINT8)&tmp, 2, len + SUB_PKT_HEADER); + if (!rc) { + STP_BTM_WARN_FUNC + ("****retry again ok!**\n"); + } + } + /* schedule(); */ + } while (remain > 0); + } else + STP_BTM_INFO_FUNC("dump entry length is 0\n"); + + STP_BTM_INFO_FUNC("Exit..\n"); + return 0; +} + +static INT32 _stp_btm_put_dump_to_aee(void) +{ + static UINT8 buf[2048]; + static UINT8 tmp[2048]; + + UINT32 buf_len; + STP_PACKET_T *pkt; + STP_DBG_HDR_T *hdr; + INT32 remain = 0; + INT32 retry = 0; + INT32 ret = 0; + + STP_BTM_INFO_FUNC("Enter..\n"); + + do { + remain = stp_dbg_dmp_out_ex(&buf[0], &buf_len); + if (buf_len > 0) { + pkt = (STP_PACKET_T *) buf; + hdr = &pkt->hdr; + if (hdr->dbg_type == STP_DBG_FW_DMP) { + memcpy(&tmp[0], pkt->raw, pkt->hdr.len); + + if (pkt->hdr.len <= 1500) { + tmp[pkt->hdr.len] = '\n'; + tmp[pkt->hdr.len + 1] = '\0'; + + ret = stp_dbg_aee_send(tmp, pkt->hdr.len, 0); + } else { + STP_BTM_INFO_FUNC("dump entry length is over long\n"); + BUG_ON(0); + } + retry = 0; + } + } else { + retry++; + msleep(100); + } + } while ((remain > 0) || (retry < 2)); + + STP_BTM_INFO_FUNC("Exit..\n"); + return ret; +} + +#if 0 +INT32 _stp_trigger_firmware_assert_via_emi(VOID) +{ + PUINT8 p_virtual_addr = NULL; + INT32 status = -1; + INT32 i = 0, j = 0; + + do { + STP_BTM_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); + if (!p_virtual_addr) { + STP_BTM_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); + STP_BTM_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); +#if 1 + /* wait for firmware assert */ + osal_sleep_ms(50); + /* if firmware is not assert self, host driver helps it. */ + do { + if (0 != mtk_wcn_stp_coredump_start_get()) { + status = 0; + break; + } + + mtk_wcn_stp_wakeup_consys(); + STP_BTM_INFO_FUNC("[Force Assert] wakeup consys (%d)\n", i); + stp_dbg_poll_cpupcr(5, 1, 1); + osal_sleep_ms(5); + + i++; + if (i > 20) { + i = 0; + break; + } + } while (1); +#endif + + if (0 != mtk_wcn_stp_coredump_start_get()) { + status = 0; + break; + } + + j++; + if (j > 8) { + j = 0; + break; + } + } while (1); + + return status; +} +#else +INT32 _stp_trigger_firmware_assert_via_emi(VOID) +{ + INT32 status = -1; + INT32 j = 0; + + wmt_plat_force_trigger_assert(STP_FORCE_TRG_ASSERT_DEBUG_PIN); + + do { + if (0 != mtk_wcn_stp_coredump_start_get()) { + status = 0; + break; + } + + stp_dbg_poll_cpupcr(5, 1, 1); + stp_dbg_poll_dmaregs(5, 1); + j++; + STP_BTM_INFO_FUNC("Wait for assert message (%d)\n", j); + osal_sleep_ms(20); + if (j > 49) { /* wait for 1 second */ + stp_dbg_set_fw_info("host trigger fw assert timeout", + osal_strlen("host trigger fw assert timeout"), + STP_HOST_TRIGGER_ASSERT_TIMEOUT); + wcn_core_dump_timeout(); /* trigger collect SYS_FTRACE */ + break; + } + } while (1); + + return status; +} +#endif + +#define COMBO_DUMP2AEE +#if 1 +#define STP_DBG_PAGED_DUMP_BUFFER_SIZE (32*1024*sizeof(char)) +UINT8 g_paged_dump_buffer[STP_DBG_PAGED_DUMP_BUFFER_SIZE] = { 0 }; + +#define STP_DBG_PAGED_TRACE_SIZE (2048*sizeof(char)) +UINT8 g_paged_trace_buffer[STP_DBG_PAGED_TRACE_SIZE] = { 0 }; + +UINT32 g_paged_dump_len = 0; +UINT32 g_paged_trace_len = 0; +VOID _stp_dump_emi_dump_buffer(UINT8 *buffer, UINT32 len) +{ + UINT32 i = 0; + + if (len > 16) + len = 16; + for (i = 0; i < len; i++) { + if (i % 16 == 0 && i != 0) + pr_cont("\n "); + + if (buffer[i] == ']' || buffer[i] == '[' || buffer[i] == ',') + pr_cont("%c", buffer[i]); + else + pr_cont("0x%02x ", buffer[i]); + } +} +#endif +static INT32 _stp_btm_handler(MTKSTP_BTM_T *stp_btm, P_STP_BTM_OP pStpOp) +{ + INT32 ret = -1; + INT32 dump_sink = 1; /* core dump target, 0: aee; 1: netlink */ + INT32 Ret = 0; + static UINT32 counter; + UINT32 full_dump_left = STP_FULL_DUMP_TIME; + UINT32 page_counter = 0; + UINT32 packet_num = STP_PAGED_DUMP_TIME_LIMIT/100; + UINT32 dump_num = 0; + ENUM_STP_FW_ISSUE_TYPE issue_type; + P_CONSYS_EMI_ADDR_INFO p_ecsi; + + p_ecsi = wmt_plat_get_emi_phy_add(); + osal_assert(p_ecsi); + if (NULL == pStpOp) + return -1; + + switch (pStpOp->opId) { + case STP_OPID_BTM_EXIT: + /* TODO: clean all up? */ + ret = 0; + break; + + /*tx timeout retry */ + case STP_OPID_BTM_RETRY: + stp_do_tx_timeout(); + ret = 0; + + break; + + /*whole chip reset */ + case STP_OPID_BTM_RST: + STP_BTM_INFO_FUNC("whole chip reset start!\n"); + STP_BTM_INFO_FUNC("....+\n"); + if (stp_btm->wmt_notify) { + stp_btm->wmt_notify(BTM_RST_OP); + ret = 0; + } else { + STP_BTM_ERR_FUNC("stp_btm->wmt_notify is NULL."); + ret = -1; + } + + STP_BTM_INFO_FUNC("whole chip reset end!\n"); + + break; + + case STP_OPID_BTM_DBG_DUMP: + /*Notify the wmt to get dump data */ + STP_BTM_DBG_FUNC("wmt dmp notification\n"); + dump_sink = ((stp_btm->wmt_notify(BTM_GET_AEE_SUPPORT_FLAG) == MTK_WCN_BOOL_TRUE) ? 0 : 1); + + if (dump_sink == 0) + _stp_btm_put_dump_to_aee(); + else if (dump_sink == 1) + _stp_btm_put_dump_to_nl(); + else + STP_BTM_ERR_FUNC("unknown sink %d\n", dump_sink); + + break; + + case STP_OPID_BTM_DUMP_TIMEOUT: + /* Flush dump data, and reset compressor */ + STP_BTM_INFO_FUNC("Flush dump data\n"); + wcn_core_dump_flush(0, MTK_WCN_BOOL_TRUE); + break; + + case STP_OPID_BTM_POLL_CPUPCR: + do { + UINT32 times; + UINT32 sleep; + + times = pStpOp->au4OpData[0]; + sleep = pStpOp->au4OpData[1]; + + ret = stp_dbg_poll_cpupcr(times, sleep, 0); + ret += stp_dbg_poll_dmaregs(times, sleep); + } while (0); + break; + + case STP_OPID_BTM_PAGED_DUMP: + g_paged_dump_len = 0; + issue_type = STP_FW_ASSERT_ISSUE; + /*packet number depend on dump_num get from register:0xf0080044 ,support jade*/ + wcn_core_dump_deinit_gcoredump(); + dump_num = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_page_dump_num); + if (dump_num != 0) { + packet_num = dump_num; + STP_BTM_WARN_FUNC("get consys dump num packet_num(%d)\n", packet_num); + } else { + STP_BTM_ERR_FUNC("can not get consys dump num and default num is 35\n"); + } + Ret = wcn_core_dump_init_gcoredump(packet_num, STP_CORE_DUMP_TIMEOUT); + if (Ret) { + STP_BTM_ERR_FUNC("core dump init fail\n"); + break; + } + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + page_counter = 0; + do { + UINT32 loop_cnt1 = 0; + UINT32 loop_cnt2 = 0; + ENUM_HOST_DUMP_STATE host_state; + ENUM_CHIP_DUMP_STATE chip_state; + UINT32 dump_phy_addr = 0; + UINT8 *dump_vir_addr = NULL; + UINT32 dump_len = 0; + UINT32 isEnd = 0; + + host_state = (ENUM_HOST_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_state); + if (STP_HOST_DUMP_NOT_START == host_state) { + counter++; + STP_BTM_INFO_FUNC("counter(%d)\n", counter); + osal_sleep_ms(100); + } else { + counter = 0; + } + while (1) { + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (STP_CHIP_DUMP_PUT_DONE == chip_state) { + STP_BTM_INFO_FUNC("chip put done\n"); + break; + } + STP_BTM_INFO_FUNC("waiting chip put done\n"); + STP_BTM_INFO_FUNC("chip_state: %d\n", chip_state); + loop_cnt1++; + osal_sleep_ms(5); + + if (loop_cnt1 > 10) + goto paged_dump_end; + + } + + wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET); + + dump_phy_addr = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_addr); + + if (!dump_phy_addr) { + STP_BTM_ERR_FUNC("get paged dump phy address fail\n"); + ret = -1; + break; + } + + dump_vir_addr = wmt_plat_get_emi_virt_add(dump_phy_addr - p_ecsi->emi_phy_addr); + if (!dump_vir_addr) { + STP_BTM_ERR_FUNC("get paged dump phy address fail\n"); + ret = -2; + break; + } + dump_len = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_len); + STP_BTM_INFO_FUNC("dump_phy_ddr(%08x),dump_vir_add(0x%p),dump_len(%d)\n", + dump_phy_addr, dump_vir_addr, dump_len); + + /*move dump info according to dump_addr & dump_len */ +#if 1 + osal_memcpy(&g_paged_dump_buffer[0], dump_vir_addr, dump_len); + _stp_dump_emi_dump_buffer(&g_paged_dump_buffer[0], dump_len); + + if (0 == page_counter) { /* do fw assert infor paser in first paged dump */ + if (1 == stp_dbg_get_host_trigger_assert()) + issue_type = STP_HOST_TRIGGER_FW_ASSERT; + + ret = stp_dbg_set_fw_info(&g_paged_dump_buffer[0], 512, issue_type); + if (ret) { + STP_BTM_ERR_FUNC("set fw issue infor fail(%d),maybe fw warm reset...\n", ret); + stp_dbg_set_fw_info("Fw Warm reset", osal_strlen("Fw Warm reset"), + STP_FW_WARM_RST_ISSUE); + } + } + + if (dump_len <= 32 * 1024) { + pr_err("g_coredump_mode: %d!\n", g_coredump_mode); + if (1 == g_coredump_mode) + ret = stp_dbg_aee_send(&g_paged_dump_buffer[0], dump_len, 0); + else if (2 == g_coredump_mode) + ret = _stp_btm_put_emi_dump_to_nl(&g_paged_dump_buffer[0], dump_len); + else{ + STP_BTM_INFO_FUNC("coredump is disabled!\n"); + return 0; + } + if (ret == 0) + STP_BTM_INFO_FUNC("aee send ok!\n"); + else if (ret == 1) + STP_BTM_INFO_FUNC("aee send fisish!\n"); + else + STP_BTM_ERR_FUNC("aee send error!\n"); + } else + STP_BTM_ERR_FUNC("dump len is over than 32K(%d)\n", dump_len); + + g_paged_dump_len += dump_len; + STP_BTM_INFO_FUNC("dump len update(%d)\n", g_paged_dump_len); +#endif + wmt_plat_update_host_sync_num(); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET_DONE); + + STP_BTM_INFO_FUNC("host sync num(%d),chip sync num(%d)\n", + wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_num), + wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_num)); + + page_counter++; + STP_BTM_INFO_FUNC("\n\n++ paged dump counter(%d) ++\n\n\n", page_counter); + + while (1) { + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (STP_CHIP_DUMP_END == chip_state) { + STP_BTM_INFO_FUNC("chip put end\n"); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_END); + break; + } + STP_BTM_INFO_FUNC("waiting chip put end\n"); + + loop_cnt2++; + osal_sleep_ms(10); + + if (loop_cnt2 > 10) + goto paged_dump_end; + } + +paged_dump_end: + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + + if (counter > packet_num) { + isEnd = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_paded_dump_end); + + if (isEnd) { + STP_BTM_INFO_FUNC("paged dump end\n"); + + STP_BTM_INFO_FUNC("\n\n paged dump print ++\n\n"); + _stp_dump_emi_dump_buffer(&g_paged_dump_buffer[0], g_paged_dump_len); + STP_BTM_INFO_FUNC("\n\n paged dump print --\n\n"); + STP_BTM_INFO_FUNC("\n\n paged dump size = %d, paged dump page number = %d\n\n", + g_paged_dump_len, page_counter); + counter = 0; + ret = 0; + } else { + STP_BTM_ERR_FUNC("paged dump fail\n"); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + stp_dbg_poll_cpupcr(5, 5, 0); + stp_dbg_poll_dmaregs(5, 1); + counter = 0; + ret = -1; + } + break; + } + + } while (1); + + break; + + case STP_OPID_BTM_FULL_DUMP: + + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + do { + UINT32 loop_cnt1 = 0; + UINT32 loop_cnt2 = 0; + ENUM_CHIP_DUMP_STATE chip_state; + UINT32 dump_phy_addr = 0; + UINT8 *dump_vir_addr = NULL; + UINT32 dump_len = 0; + UINT32 isFail = 0; + + while (1) { + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (STP_CHIP_DUMP_PUT_DONE == chip_state) + break; + + loop_cnt1++; + osal_sleep_ms(10); + + if (loop_cnt1 > 10) { + isFail = 1; + goto full_dump_end; + } + } + + wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET); + + dump_phy_addr = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_addr); + if (!dump_phy_addr) { + STP_BTM_ERR_FUNC("get phy dump address fail\n"); + ret = -1; + break; + } + + dump_vir_addr = wmt_plat_get_emi_virt_add(dump_phy_addr - p_ecsi->emi_phy_addr); + if (!dump_vir_addr) { + STP_BTM_ERR_FUNC("get vir dump address fail\n"); + ret = -2; + break; + } + dump_len = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_len); + /*move dump info according to dump_addr & dump_len */ + wmt_plat_update_host_sync_num(); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_GET_DONE); + + STP_BTM_INFO_FUNC("host sync num(%d),chip sync num(%d)\n", + wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_host_sync_num), + wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_num)); + + while (1) { + chip_state = (ENUM_CHIP_DUMP_STATE)wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_sync_state); + if (STP_CHIP_DUMP_END == chip_state) { + wmt_plat_set_host_dump_state(STP_HOST_DUMP_END); + break; + } + loop_cnt2++; + osal_sleep_ms(10); + + if (loop_cnt2 > 10) { + isFail = 1; + goto full_dump_end; + } + } + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); +full_dump_end: + if (isFail) { + STP_BTM_ERR_FUNC("full dump fail\n"); + wmt_plat_set_host_dump_state(STP_HOST_DUMP_NOT_START); + ret = -1; + break; + } + } while (--full_dump_left > 0); + if (0 == full_dump_left) { + STP_BTM_INFO_FUNC("full dump end\n"); + ret = 0; + } + break; + case STP_OPID_BTM_PAGED_TRACE: + g_paged_trace_len = 0; + do { + UINT32 ctrl_val = 0; + UINT32 loop_cnt1 = 0; + UINT32 buffer_start = 0; + UINT32 buffer_idx = 0; + UINT8 *dump_vir_addr = NULL; + + while (loop_cnt1 < 10) { + ctrl_val = wmt_plat_get_dump_info(p_ecsi->p_ecso->emi_apmem_ctrl_state); + if (0x8 == ctrl_val) + break; + osal_sleep_ms(10); + loop_cnt1++; + } + + if (loop_cnt1 >= 10) { + STP_BTM_ERR_FUNC("polling CTRL STATE fail\n"); + ret = -1; + break; + } + + buffer_start = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_start); + buffer_idx = wmt_plat_get_dump_info( + p_ecsi->p_ecso->emi_apmem_ctrl_chip_print_buff_idx); + /* buffer_len = buffer_idx - buffer_start; */ + g_paged_trace_len = buffer_idx; + STP_BTM_INFO_FUNC("paged trace buffer addr(%08x),buffer_len(%d)\n", buffer_start, buffer_idx); + dump_vir_addr = wmt_plat_get_emi_virt_add(buffer_start - p_ecsi->emi_phy_addr); + if (!dump_vir_addr) { + STP_BTM_ERR_FUNC("get vir dump address fail\n"); + ret = -2; + break; + } + osal_memcpy(&g_paged_trace_buffer[0], dump_vir_addr, + buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE); + /*moving paged trace according to buffer_start & buffer_len */ + do { + int i = 0; + int dump_len = 0; + + dump_len = + buffer_idx < STP_DBG_PAGED_TRACE_SIZE ? buffer_idx : STP_DBG_PAGED_TRACE_SIZE; + pr_warn("\n\n -- paged trace hex output --\n\n"); + for (i = 0; i < dump_len; i++) { + if (i % 16 == 0) + pr_cont("\n"); + + pr_cont("%02x ", g_paged_trace_buffer[i]); + } + pr_warn("\n\n -- paged trace ascii output --\n\n"); + for (i = 0; i < dump_len; i++) { + if (i % 64 == 0) + pr_cont("\n"); + pr_cont("%c", g_paged_trace_buffer[i]); + } + } while (0); + /*move parser fw assert infor to paged dump in the one paged dump */ + /* ret = stp_dbg_set_fw_info(&g_paged_trace_buffer[0],g_paged_trace_len,issue_type); */ + ret = 0; + + } while (0); + mtk_wcn_stp_ctx_restore(); + break; + +#if CFG_WMT_LTE_COEX_HANDLING + case STP_OPID_BTM_WMT_LTE_COEX: + ret = wmt_idc_msg_to_lte_handing(); + break; +#endif + default: + ret = -1; + break; + } + + return ret; +} + +static P_OSAL_OP _stp_btm_get_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ) +{ + P_OSAL_OP pOp; + /* INT32 ret = 0; */ + + if (!pOpQ) { + STP_BTM_WARN_FUNC("!pOpQ\n"); + return NULL; + } + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* acquire lock success */ + RB_GET(pOpQ, pOp); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + + if (!pOp) + STP_BTM_WARN_FUNC("RB_GET fail\n"); + + return pOp; +} + +static INT32 _stp_btm_put_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + INT32 ret; + + if (!pOpQ || !pOp) { + STP_BTM_WARN_FUNC("invalid input param: 0x%p, 0x%p\n", pOpQ, pOp); + return 0; /* ;MTK_WCN_BOOL_FALSE; */ + } + + ret = 0; + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else + ret = -1; + + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + + if (ret) { + STP_BTM_WARN_FUNC("RB_FULL(0x%p) %d ,rFreeOpQ = %p, rActiveOpQ = %p\n", + pOpQ, + RB_COUNT(pOpQ), + &stp_btm->rFreeOpQ, + &stp_btm->rActiveOpQ); + return 0; + } + /* STP_BTM_WARN_FUNC("RB_COUNT = %d\n",RB_COUNT(pOpQ)); */ + return 1; + +} + +P_OSAL_OP _stp_btm_get_free_op(MTKSTP_BTM_T *stp_btm) +{ + P_OSAL_OP pOp; + + if (stp_btm) { + pOp = _stp_btm_get_op(stp_btm, &stp_btm->rFreeOpQ); + if (pOp) + osal_memset(&pOp->op, 0, sizeof(pOp->op)); + + return pOp; + } else + return NULL; +} + +INT32 _stp_btm_put_act_op(MTKSTP_BTM_T *stp_btm, P_OSAL_OP pOp) +{ + INT32 bRet = 0; + INT32 bCleanup = 0; + long wait_ret = -1; + + P_OSAL_SIGNAL pSignal = NULL; + + if (!stp_btm || !pOp) { + STP_BTM_ERR_FUNC("Input NULL pointer\n"); + return bRet; + } + do { + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* put to active Q */ + bRet = _stp_btm_put_op(stp_btm, &stp_btm->rActiveOpQ, pOp); + if (0 == bRet) { + STP_BTM_WARN_FUNC("put active queue fail\n"); + bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ + break; + } + + /* wake up wmtd */ + osal_trigger_event(&stp_btm->STPd_event); + + if (pSignal->timeoutValue == 0) { + bRet = 1; /* MTK_WCN_BOOL_TRUE; */ + /* clean it in wmtd */ + break; + } + + /* wait result, clean it here */ + bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal); + + STP_BTM_DBG_FUNC("wait completion:%ld\n", wait_ret); + if (!wait_ret) { + STP_BTM_ERR_FUNC("wait completion timeout\n"); + /* TODO: how to handle it? retry? */ + } else { + if (pOp->result) + STP_BTM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); + + bRet = (pOp->result) ? 0 : 1; + } + } while (0); + + if (bCleanup) { + /* put Op back to freeQ */ + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } + bRet = (pOp->result) ? 0 : 1; + return bRet; +} + +static INT32 _stp_btm_wait_for_msg(void *pvData) +{ + MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData; + + return (!RB_EMPTY(&stp_btm->rActiveOpQ)) || osal_thread_should_stop(&stp_btm->BTMd); +} + +static INT32 _stp_btm_proc(void *pvData) +{ + MTKSTP_BTM_T *stp_btm = (MTKSTP_BTM_T *) pvData; + P_OSAL_OP pOp; + INT32 id; + INT32 result; + + if (!stp_btm) { + STP_BTM_WARN_FUNC("!stp_btm\n"); + return -1; + } + + for (;;) { + pOp = NULL; + + osal_wait_for_event(&stp_btm->STPd_event, _stp_btm_wait_for_msg, (void *)stp_btm); + + if (osal_thread_should_stop(&stp_btm->BTMd)) { + STP_BTM_INFO_FUNC("should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + + /* get Op from activeQ */ + pOp = _stp_btm_get_op(stp_btm, &stp_btm->rActiveOpQ); + + if (!pOp) { + STP_BTM_WARN_FUNC("get_lxop activeQ fail\n"); + continue; + } + + id = osal_op_get_id(pOp); + + STP_BTM_DBG_FUNC("======> lxop_get_opid = %d, %s, remaining count = *%d*\n", + id, (id >= osal_array_size(g_btm_op_name)) ? ("???") : (g_btm_op_name[id]), + RB_COUNT(&stp_btm->rActiveOpQ)); + + if (id >= STP_OPID_BTM_NUM) { + STP_BTM_WARN_FUNC("abnormal opid id: 0x%x\n", id); + result = -1; + goto handler_done; + } + + result = _stp_btm_handler(stp_btm, &pOp->op); + +handler_done: + + if (result) { + STP_BTM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, + (id >= osal_array_size(g_btm_op_name)) ? ("???") : (g_btm_op_name[id]), + result); + } + + if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, result); + } else { + /* put Op back to freeQ */ + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, pOp); + } + + if (STP_OPID_BTM_EXIT == id) { + break; + } else if (STP_OPID_BTM_RST == id) { + /* prevent multi reset case */ + stp_btm_reset_btm_wq(stp_btm); + mtk_wcn_stp_coredump_start_ctrl(0); + } + } + + STP_BTM_INFO_FUNC("exits\n"); + + return 0; +}; + +static inline INT32 _stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_RST; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_RETRY; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_DUMP_TIMEOUT; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_dump_type(MTKSTP_BTM_T *stp_btm, ENUM_STP_BTM_OPID_T opid) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + STP_BTM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + + pOp->op.opId = opid; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) +{ + + INT32 retval; +#if 0 + UINT32 dump_type; + UINT8 *virtual_addr = NULL; +#endif + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + +#if 1 /* Paged dump */ + STP_BTM_INFO_FUNC("paged dump start++\n"); + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_PAGED_DUMP); + if (retval) + STP_BTM_ERR_FUNC("paged dump fail\n"); +#else + virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_CHIP_SYNC_ADDR); + if (!virtual_addr) { + STP_BTM_ERR_FUNC("get dump type virtual addr fail\n"); + return -1; + } + dump_type = CONSYS_REG_READ(virtual_addr); + STP_BTM_INFO_FUNC("dump type:%08x\n", dump_type); + + if ((dump_type & 0xfffff) == (CONSYS_PAGED_DUMP_START_ADDR & 0xfffff)) { + STP_BTM_INFO_FUNC("do paged dump\n"); + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_PAGED_DUMP); + if (retval) { + STP_BTM_ERR_FUNC("paged dump fail,do full dump\n"); + _stp_btm_dump_type(stp_btm, STP_OPID_BTM_FULL_DUMP); + } + } else if ((dump_type & 0xfffff) == (CONSYS_FULL_DUMP_START_ADDR & 0xfffff)) { + STP_BTM_INFO_FUNC("do full dump\n"); + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_FULL_DUMP); + } else { + STP_BTM_INFO_FUNC("do normal dump\n"); + retval = _stp_btm_dump_type(stp_btm, STP_OPID_BTM_DBG_DUMP); + } +#endif + + return retval; +} + +static inline INT32 _stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_POLL_CPUPCR; + pOp->signal.timeoutValue = 0; + pOp->op.au4OpData[0] = times; + pOp->op.au4OpData[1] = sleep; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_PAGED_TRACE; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm) +{ + INT32 ret = -1; + + ret = _stp_trigger_firmware_assert_via_emi(); + + return ret; + +} + +INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_rst_wq(stp_btm); +} + +INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_stp_retry_wq(stp_btm); +} + +INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_coredump_timeout_wq(stp_btm); +} + +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_dmp_wq(stp_btm); +} + +INT32 stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm) +{ + return _stp_btm_notify_wmt_trace_wq(stp_btm); +} + +INT32 stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep) +{ + return _stp_notify_btm_poll_cpupcr(stp_btm, times, sleep); +} + +INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en) +{ + return stp_dbg_poll_cuppcr_ctrl(en); +} + +INT32 stp_notify_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm) +{ + INT32 ret = -1; +#if BTIF_RXD_BE_BLOCKED_DETECT + if (is_btif_rxd_be_blocked()) + ret = wcn_btif_rxd_blocked_collect_ftrace(); /* trigger collect SYS_FTRACE */ + else +#endif + ret = _stp_btm_do_fw_assert_via_emi(stp_btm); + return ret; +} + +#if CFG_WMT_LTE_COEX_HANDLING + +static inline INT32 _stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_btm == NULL) + return STP_BTM_OPERATION_FAIL; + + pOp = _stp_btm_get_free_op(stp_btm); + if (!pOp) { + /* STP_BTM_WARN_FUNC("get_free_lxop fail\n"); */ + return -1; /* break; */ + } + pOp->op.opId = STP_OPID_BTM_WMT_LTE_COEX; + pOp->signal.timeoutValue = 0; + bRet = _stp_btm_put_act_op(stp_btm, pOp); + STP_BTM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + retval = (0 == bRet) ? STP_BTM_OPERATION_FAIL : STP_BTM_OPERATION_SUCCESS; + + return retval; +} + +INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm) +{ + return _stp_notify_btm_handle_wmt_lte_coex(stp_btm); +} + +#endif +MTKSTP_BTM_T *stp_btm_init(void) +{ + INT32 i = 0x0; + INT32 ret = -1; + + osal_unsleepable_lock_init(&stp_btm->wq_spinlock); + osal_event_init(&stp_btm->STPd_event); + stp_btm->wmt_notify = wmt_lib_btm_cb; + + RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); + RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); + + /* Put all to free Q */ + for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) { + osal_signal_init(&(stp_btm->arQue[i].signal)); + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); + } + + /*Generate PSM thread, to servie STP-CORE for packet retrying and core dump receiving */ + stp_btm->BTMd.pThreadData = (VOID *) stp_btm; + stp_btm->BTMd.pThreadFunc = (VOID *) _stp_btm_proc; + osal_memcpy(stp_btm->BTMd.threadName, BTM_THREAD_NAME, osal_strlen(BTM_THREAD_NAME)); + + ret = osal_thread_create(&stp_btm->BTMd); + if (ret < 0) { + STP_BTM_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT1; + } + + /* Start STPd thread */ + ret = osal_thread_run(&stp_btm->BTMd); + if (ret < 0) { + STP_BTM_ERR_FUNC("osal_thread_run FAILS\n"); + goto ERR_EXIT1; + } + + return stp_btm; + +ERR_EXIT1: + + return NULL; + +} + +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm) +{ + + INT32 ret = -1; + + STP_BTM_INFO_FUNC("btm deinit\n"); + + if (!stp_btm) + return STP_BTM_OPERATION_FAIL; + + ret = osal_thread_destroy(&stp_btm->BTMd); + if (ret < 0) { + STP_BTM_ERR_FUNC("osal_thread_destroy FAILS\n"); + return STP_BTM_OPERATION_FAIL; + } + + return STP_BTM_OPERATION_SUCCESS; +} + +INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm) +{ + UINT32 i = 0; + + osal_lock_unsleepable_lock(&(stp_btm->wq_spinlock)); + RB_INIT(&stp_btm->rFreeOpQ, STP_BTM_OP_BUF_SIZE); + RB_INIT(&stp_btm->rActiveOpQ, STP_BTM_OP_BUF_SIZE); + osal_unlock_unsleepable_lock(&(stp_btm->wq_spinlock)); + /* Put all to free Q */ + for (i = 0; i < STP_BTM_OP_BUF_SIZE; i++) { + osal_signal_init(&(stp_btm->arQue[i].signal)); + _stp_btm_put_op(stp_btm, &stp_btm->rFreeOpQ, &(stp_btm->arQue[i])); + } + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c new file mode 100644 index 0000000000000..246448b38b315 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/dbg_core.c @@ -0,0 +1,13 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h new file mode 100644 index 0000000000000..9a429b4af1e30 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/btm_core.h @@ -0,0 +1,133 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _BTM_CORE_H +#define _BTM_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_wmt.h" +#include "wmt_plat.h" +#include "wmt_idc.h" +#include "mtk_btif_exp.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define STP_BTM_OPERATION_FAIL (-1) +#define STP_BTM_OPERATION_SUCCESS (0) + +#define STP_BTM_OP_BUF_SIZE (64) + +#define BTM_THREAD_NAME "mtk_stp_btm" + +#define STP_PAGED_DUMP_TIME_LIMIT 3500 +#define STP_FULL_DUMP_TIME 3 +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_STP_BTM_OPID_T { + STP_OPID_BTM_RETRY = 0x0, + STP_OPID_BTM_RST = 0x1, + STP_OPID_BTM_DBG_DUMP = 0x2, + STP_OPID_BTM_DUMP_TIMEOUT = 0x3, + STP_OPID_BTM_POLL_CPUPCR = 0x4, + STP_OPID_BTM_PAGED_DUMP = 0x5, + STP_OPID_BTM_FULL_DUMP = 0x6, + STP_OPID_BTM_PAGED_TRACE = 0x7, + STP_OPID_BTM_FORCE_FW_ASSERT = 0x8, +#if CFG_WMT_LTE_COEX_HANDLING + STP_OPID_BTM_WMT_LTE_COEX = 0x9, +#endif + STP_OPID_BTM_EXIT, + STP_OPID_BTM_NUM +} ENUM_STP_BTM_OPID_T, *P_ENUM_STP_BTM_OPID_T; + +typedef OSAL_OP_DAT STP_BTM_OP; +typedef P_OSAL_OP_DAT P_STP_BTM_OP; + +typedef struct mtk_stp_btm { + OSAL_THREAD BTMd; /* main thread (wmtd) handle */ + OSAL_EVENT STPd_event; + OSAL_UNSLEEPABLE_LOCK wq_spinlock; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[STP_BTM_OP_BUF_SIZE]; /* real op instances */ + + /*wmt_notify */ + INT32 (*wmt_notify)(MTKSTP_BTM_WMT_OP_T); +} MTKSTP_BTM_T; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 stp_btm_notify_wmt_rst_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_stp_retry_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_coredump_timeout_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_notify_wmt_dmp_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_deinit(MTKSTP_BTM_T *stp_btm); +INT32 stp_btm_reset_btm_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_poll_cpupcr(MTKSTP_BTM_T *stp_btm, UINT32 times, UINT32 sleep); +INT32 stp_notify_btm_poll_cpupcr_ctrl(UINT32 en); +INT32 stp_btm_notify_wmt_trace_wq(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_do_fw_assert_via_emi(MTKSTP_BTM_T *stp_btm); +INT32 stp_notify_btm_handle_wmt_lte_coex(MTKSTP_BTM_T *stp_btm); +INT32 wcn_psm_flag_trigger_collect_ftrace(void); +#if BTIF_RXD_BE_BLOCKED_DETECT +INT32 wcn_btif_rxd_blocked_collect_ftrace(void); +MTK_WCN_BOOL is_btif_rxd_be_blocked(void); +#endif +MTKSTP_BTM_T *stp_btm_init(void); +extern unsigned int g_coredump_mode; +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h new file mode 100644 index 0000000000000..d8c6ebe9c4b06 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/dbg_core.h @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _DBG_CORE_H +#define _DBG_CORE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h new file mode 100644 index 0000000000000..fe92f25e92c18 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/psm_core.h @@ -0,0 +1,251 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _PSM_CORE_H +#define _PSM_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_wmt.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define PFX_PSM "[STP-PSM] " +#define STP_PSM_LOG_LOUD 4 +#define STP_PSM_LOG_DBG 3 +#define STP_PSM_LOG_INFO 2 +#define STP_PSM_LOG_WARN 1 +#define STP_PSM_LOG_ERR 0 + +#define ASSERT(expr) +#define STP_PSM_FIFO_SIZE 0x2000 /* 8kbytes */ +#define STP_PSM_TX_SIZE 0x800 /* 2kbytes */ + +#define STP_PSM_OPERATION_FAIL (-1) +#define STP_PSM_OPERATION_SUCCESS (0) + +#define STP_PSM_PACKET_SIZE_MAX (2000) + +#define PSM_HANDLING 127 + +#define STP_PSM_WMT_PS_TASK_HANDLING_TIME 30 /* 20 milli-seconds */ +#define STP_PSM_IDLE_TIME_SLEEP 30 /* temporary for stress testing */ +#define STP_PSM_IDLE_TIME_SLEEP_1000 1000 /* for high speed transmission e.g. BT OPP*/ +#define STP_PSM_SDIO_IDLE_TIME_SLEEP 100 /* temporary for SDIO stress testing */ +#define STP_PSM_WAIT_EVENT_TIMEOUT 6000 +#if 0 +#define STP_PSM_WMT_EVENT_SLEEP_EN (0x1UL << 0) +#define STP_PSM_WMT_EVENT_WAKEUP_EN (0x1UL << 1) +#define STP_PSM_BLOCK_DATA_EN (0x1UL << 2) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (0x1UL << 3) +#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (0x1UL << 4) +#define STP_PSM_RESET_EN (0x1UL << 5) +#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (0x1UL << 6) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (0x1UL << 7) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (0x1UL << 8) +#endif + +#define STP_PSM_WMT_EVENT_SLEEP_EN (0) +#define STP_PSM_WMT_EVENT_WAKEUP_EN (1) +#define STP_PSM_BLOCK_DATA_EN (2) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR (3) +#define STP_PSM_WMT_EVENT_ROLL_BACK_EN (4) +#define STP_PSM_RESET_EN (5) +#define STP_PSM_WMT_EVENT_HOST_WAKEUP_EN (6) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY (7) +#define STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY (8) + +#define STP_PSM_DBG_SIZE (16) + +/* OP command ring buffer : must be power of 2 */ +#define STP_OP_BUF_SIZE (16) + +#define PSM_THREAD_NAME "mtk_stp_psm" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum { + ACT = 0, + ACT_INACT, + INACT, + INACT_ACT, + STP_PSM_MAX_STATE, +} MTKSTP_PSM_STATE_T; + +typedef enum _ENUM_STP_OPID_T { + STP_OPID_PSM_SLEEP = 0, + STP_OPID_PSM_WAKEUP, + STP_OPID_PSM_HOST_AWAKE, + STP_OPID_PSM_EXIT, + STP_OPID_PSM_NUM, + STP_OPID_PSM_INALID = STP_OPID_PSM_NUM, +} ENUM_STP_OPID_T, *P_ENUM_STP_OPID_T; + +typedef enum { + MON = 0, + UNMON, +} MTKSTP_PSM_MONSTATE_T; + +typedef INT32(*wmt_notify_t) (MTKSTP_PSM_ACTION_T action); +typedef INT32(*stp_tx_cb_t) (unsigned char *buffer, UINT32 length, UINT8 type); + +typedef OSAL_OP_DAT STP_OP; +typedef P_OSAL_OP_DAT P_STP_OP; + +typedef struct mtk_stp_psm { + OSAL_THREAD PSMd; /* main thread (wmtd) handle */ + OSAL_EVENT STPd_event; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[STP_OP_BUF_SIZE]; /* real op instances */ + + /* OSAL_OP current_active_op; */ + /* P_OSAL_OP current_active_op; */ + UINT32 last_active_opId; + MTKSTP_PSM_STATE_T work_state; /*working state */ + OSAL_BIT_OP_VAR flag; + + /* in normal cases, sleep op is always enabled; + * but in error cases, we can't execute sleep cmd, + * Eg: FW assert, core dump + */ + INT32 sleep_en; + +/* OSAL_UNSLEEPABLE_LOCK flagSpinlock; */ + INT32 idle_time_to_sleep; + OSAL_WAKE_LOCK wake_lock; + OSAL_TIMER psm_timer; /*monitor if active */ + OSAL_EVENT wait_wmt_q; + OSAL_FIFO hold_fifo; + OSAL_SLEEPABLE_LOCK hold_fifo_spinlock_global; + OSAL_UNSLEEPABLE_LOCK wq_spinlock; + OSAL_SLEEPABLE_LOCK stp_psm_lock; + INT32 (*wmt_notify)(MTKSTP_PSM_ACTION_T action); + INT32 (*stp_tx_cb)(unsigned char *buffer, UINT32 length, UINT8 type); + + MTK_WCN_BOOL (*is_wmt_quick_ps_support)(VOID); + UINT8 out_buf[STP_PSM_TX_SIZE]; +} MTKSTP_PSM_T; + +typedef struct { + UINT32 prev_flag; + UINT32 cur_flag; + UINT32 line_num; + UINT32 package_no; + UINT32 sec; + UINT32 usec; + UINT32 pid; +} STP_PSM_ENTRY_T; + +typedef struct stp_psm_record { + STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; + UINT32 in; + UINT32 out; + UINT32 size; + OSAL_UNSLEEPABLE_LOCK lock; +} STP_PSM_RECORD_T; + +typedef struct stp_psm_opid_record { + STP_PSM_ENTRY_T queue[STP_PSM_DBG_SIZE]; + UINT32 in; + UINT32 out; + UINT32 size; + OSAL_UNSLEEPABLE_LOCK lock; +} STP_PSM_OPID_RECORD, *P_STP_PSM_OPID_RECORD; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define PSM_USE_COUNT_PACKAGE 0 + +#if PSM_USE_COUNT_PACKAGE +#define MTK_COMBO_PSM_RX_TH_DEFAULT (1600) +#define MTK_COMBO_PSM_TX_TH_DEFAULT (300) +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir); +#else +#define SAMPLE_DURATION 1 /*1 second */ +#define RTX_SPEED_THRESHOLD 50000 /*50KB/s */ +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length); +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*stp-psm external function*/ +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm); + +INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type); +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep); +struct mtk_stp_psm *stp_psm_init(void); +INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm); +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel); +INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state); +MTK_WCN_BOOL stp_psm_is_quick_ps_support(VOID); + +INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm); +INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h new file mode 100644 index 0000000000000..eaa5ce773e332 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_core.h @@ -0,0 +1,629 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _STP_CORE_H +#define _STP_CORE_H + +#include "osal_typedef.h" +#include "osal.h" +#include "stp_exp.h" +#include "psm_core.h" +#include "btm_core.h" +#include "stp_btif.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CFG_STP_CORE_CTX_SPIN_LOCK (0) + +#define WMT_LTE_COEX_FLAG (0x16) + +/*configure using SPINLOCK or just mutex for STP-CORE tx*/ +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define CONFIG_POWER_SAVING_SUPPORT + +#ifdef PFX +#undef PFX +#endif +#define PFX "[STP] " + +#define STP_LOG_DBG 4 +#define STP_LOG_PKHEAD 3 +#define STP_LOG_INFO 2 +#define STP_LOG_WARN 1 +#define STP_LOG_ERR 0 + +extern unsigned int gStpDbgLvl; + +#define STP_DBG_FUNC(fmt, arg...)\ +do { \ + if (gStpDbgLvl >= STP_LOG_DBG) \ + osal_dbg_print(PFX "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_INFO_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgLvl >= STP_LOG_INFO) \ + osal_dbg_print(PFX "%s:[I] " fmt, __func__ , ##arg); \ +} while (0) +#define STP_WARN_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgLvl >= STP_LOG_WARN) \ + osal_warn_print(PFX "%s:[W] " fmt, __func__ , ##arg); \ +} while (0) +#define STP_ERR_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgLvl >= STP_LOG_ERR) \ + osal_err_print(PFX "%s:[E] " fmt, __func__ , ##arg); \ +} while (0) +#define STP_TRC_FUNC(f) \ +do { \ + if (gStpDbgLvl >= STP_LOG_DBG) \ + osal_dbg_print(PFX "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +#define STP_DUMP_PACKET_HEAD(a, b, c) \ +do { \ + if (gStpDbgLvl >= STP_LOG_PKHEAD) \ + stp_dump_data(a, b, c); \ +} while (0) +#define STP_TRACE_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgLvl >= STP_LOG_DBG) \ + osal_dbg_print(PFX "%s: " fmt, __func__ , ##arg); \ +} while (0) + +#define STP_MODE_BIT(x) (0x1UL << x) +#define MTKSTP_UART_FULL_MODE STP_MODE_BIT(0) +#define MTKSTP_UART_MAND_MODE STP_MODE_BIT(1) +#define MTKSTP_BTIF_FULL_MODE STP_MODE_BIT(2) +#define MTKSTP_BTIF_MAND_MODE STP_MODE_BIT(3) +#define MTKSTP_SDIO_MODE STP_MODE_BIT(4) + +#define MTKSTP_BUFFER_SIZE (16384) + +/*To check function driver's status by the the interface*/ +/*Operation definition*/ +#define OP_FUNCTION_ACTIVE 0 + +/*Driver's status*/ +#define STATUS_OP_INVALID 0 +#define STATUS_FUNCTION_INVALID 1 + +#define STATUS_FUNCTION_ACTIVE 31 +#define STATUS_FUNCTION_INACTIVE 32 + +#define MTKSTP_CRC_SIZE (2) +#define MTKSTP_HEADER_SIZE (4) +#define MTKSTP_SEQ_SIZE (8) + +/*#define MTKSTP_WINSIZE (4)*/ +#define MTKSTP_WINSIZE (7) +#define MTKSTP_TX_TIMEOUT (180) /*TODO: Baudrate to decide this */ +#define MTKSTP_RETRY_LIMIT (10) + +#define INDEX_INC(idx) \ +{ \ + idx++; \ + idx &= 0x7; \ +} + +#define INDEX_DEC(idx) \ +{ \ + idx--; \ + idx &= 0x7; \ +} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef INT32(*IF_TX) (const PUINT8 data, const UINT32 size, PUINT32 written_size); +/* event/signal */ +typedef INT32(*EVENT_SET) (UINT8 function_type); +typedef INT32(*EVENT_TX_RESUME) (UINT8 winspace); +typedef INT32(*FUNCTION_STATUS) (UINT8 type, UINT8 op); +typedef INT32(*WMT_NOTIFY_FUNC_T) (UINT32 action); +typedef INT32(*BTM_NOTIFY_WMT_FUNC_T) (INT32); + +#if CFG_STP_CORE_CTX_SPIN_LOCK +typedef OSAL_UNSLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; +#else +typedef OSAL_SLEEPABLE_LOCK STP_CTX_LOCK, *PSTP_CTX_LOCK; +#endif + +typedef struct { + /* common interface */ + IF_TX cb_if_tx; + /* event/signal */ + EVENT_SET cb_event_set; + EVENT_TX_RESUME cb_event_tx_resume; + FUNCTION_STATUS cb_check_funciton_status; +} mtkstp_callback; + +typedef enum { + MTKSTP_SYNC = 0, + MTKSTP_SEQ, + MTKSTP_ACK, + MTKSTP_NAK, + MTKSTP_TYPE, + MTKSTP_LENGTH, + MTKSTP_CHECKSUM, + MTKSTP_DATA, + MTKSTP_CRC1, + MTKSTP_CRC2, + MTKSTP_RESYNC1, + MTKSTP_RESYNC2, + MTKSTP_RESYNC3, + MTKSTP_RESYNC4, + MTKSTP_FW_MSG, +} mtkstp_parser_state; + +typedef struct { + mtkstp_parser_state state; + UINT8 seq; + UINT8 ack; + UINT8 nak; + UINT8 type; + UINT16 length; + UINT8 checksum; + UINT16 crc; +#if 1 + UINT8 wmtsubtype; +#endif +} mtkstp_parser_context_struct; + +typedef struct { + UINT8 txseq; /* last tx pkt's seq + 1 */ + UINT8 txack; /* last tx pkt's ack */ + UINT8 rxack; /* last rx pkt's ack */ + UINT8 winspace; /* current sliding window size */ + UINT8 expected_rxseq; /* last rx pkt's seq + 1 */ + UINT8 retry_times; +} mtkstp_sequence_context_struct; + +typedef struct { + /* MTK_WCN_MUTEX mtx; */ + OSAL_UNSLEEPABLE_LOCK mtx; + UINT8 buffer[MTKSTP_BUFFER_SIZE]; + UINT32 read_p; + UINT32 write_p; +} mtkstp_ring_buffer_struct; + +typedef struct { + UINT8 inband_rst_set; + UINT32 rx_counter; /* size of current processing pkt in rx_buf[] */ + UINT8 rx_buf[MTKSTP_BUFFER_SIZE]; /* input buffer of STP, room for current processing pkt */ + UINT32 tx_read; /* read ptr of tx_buf[] */ + UINT32 tx_write; /* write ptr of tx_buf[] */ + UINT8 tx_buf[MTKSTP_BUFFER_SIZE]; /* output buffer of STP */ + UINT32 tx_start_addr[MTKSTP_SEQ_SIZE]; /* ptr of each pkt in tx_buf[] */ + UINT32 tx_length[MTKSTP_SEQ_SIZE]; /* length of each pkt in tx_buf[] */ + mtkstp_ring_buffer_struct ring[MTKSTP_MAX_TASK_NUM]; /* ring buffers for each function driver */ + mtkstp_parser_context_struct parser; /* current rx pkt's content */ + mtkstp_sequence_context_struct sequence; /* state machine's current status */ + /* MTK_WCN_MUTEX stp_mutex; */ + /* OSAL_UNSLEEPABLE_LOCK stp_mutex; */ + STP_CTX_LOCK stp_mutex; + /* MTK_WCN_TIMER tx_timer; // timer for tx timeout handling */ + OSAL_TIMER tx_timer; + + MTKSTP_PSM_T *psm; + MTKSTP_BTM_T *btm; + UINT8 f_enable; /* default disabled */ + UINT8 f_ready; /* default non-ready */ + UINT8 f_pending_type; + UINT8 f_coredump; /*block tx flag, for now, only when f/w assert happens, we will set this bit on */ + UINT8 en_coredump; + /* Flag to identify Blueztooth is Bluez/or MTK Stack */ + MTK_WCN_BOOL f_bluez; + MTK_WCN_BOOL f_dbg_en; + MTK_WCN_BOOL f_autorst_en; + + /* Flag to identify STP by SDIO or UART */ + UINT32 f_mode; + + /* Flag to indicate the last WMT CLOSE */ + UINT32 f_wmt_last_close; + + /* Flag to indicate evt err has triggered assert or not */ + UINT32 f_evt_err_assert; +} mtkstp_context_struct; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_init +* DESCRIPTION +* init STP kernel +* PARAMETERS +* cb_func [IN] function pointers of system APIs +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_deinit +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 mtk_wcn_stp_deinit(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_enable +* DESCRIPTION +* enable/disable STP +* PARAMETERS +* value [IN] 0 = disable, others = enable +* RETURNS +* INT32 0 = success, others = error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_enable(INT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/non-ready STP +* PARAMETERS +* value [IN] 0 = non-ready, others = ready +* RETURNS +* INT32 0 = success, others = error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_ready(INT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get f/w assert flag in STP context +* PARAMETERS +* VOID +* RETURNS +* INT32 0= f/w assert flag is not set, others=f/w assert flag is set +*****************************************************************************/ +extern INT32 mtk_wcn_stp_coredump_start_get(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 length transmitted +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_mode(UINT32 sdio_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART Fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Fullset, FALSE:UART Fullset +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART Mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:UART Mandatory, FALSE:UART Mandatory +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void); +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_fullset_mode +* DESCRIPTION +* Is stp use BTIF Fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Fullset, FALSE:BTIF Fullset +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_mand_mode +* DESCRIPTION +* Is stp use BTIF Mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Mandatory, FALSE:BTIF Mandatory +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_sdio_mode +* DESCRIPTION +* Is stp use SDIO mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To sync to oringnal stp state with f/w stp +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_inband_reset(void); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To send testing command to chip +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_test_cmd(INT32 no); + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To control STP debugging mechanism +* PARAMETERS +* func_no: function control, func_op: dumpping filer, func_param: dumpping parameter +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_debug_ctrl(INT32 func_no, INT32 func_op, INT32 func_param); +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush +* DESCRIPTION +* flush all stp context +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_flush_context(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_rx_queue +* DESCRIPTION +* flush all stp rx queue +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +extern void mtk_wcn_stp_flush_rx_queue(UINT32 type); + +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode); + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst); + +/*stp_psm support*/ + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_notify_stp +* DESCRIPTION +* WMT notification to STP that power saving job is done or not +* PARAMETERS +* +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_notify_stp(const UINT32 action); + +extern int mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_enabla +* DESCRIPTION +* enable STP PSM +* PARAMETERS +* int idle_time_to_sleep: IDLE time to sleep +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_enable(int idle_time_to_sleep); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP PSM +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_disable(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_reset +* DESCRIPTION +* reset STP PSM (used on whole chip reset) +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_psm_reset(void); +extern void stp_do_tx_timeout(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_btm_get_dmp +* DESCRIPTION +* get stp dump related information +* PARAMETERS +* buffer: dump placement, len: dump size +* RETURNS +* 0: Success Negative Value: Fail +*****************************************************************************/ +extern int mtk_wcn_stp_btm_get_dmp(char *buf, int *len); + +extern int mtk_wcn_stp_dbg_enable(void); + +extern int mtk_wcn_stp_dbg_disable(void); + +extern void mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type); + +extern int mtk_wcn_sys_if_rx(UINT8 *data, INT32 size); + +extern MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel); + +extern INT32 mtk_wcn_stp_dbg_dump_package(VOID); + +extern int stp_drv_init(void); + +extern void stp_drv_exit(void); + +extern INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on); + +extern INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on); + +extern INT32 mtk_wcn_stp_coredump_flag_get(VOID); +extern INT32 mtk_wcn_stp_notify_sleep_for_thermal(void); + +extern INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value); + +/*stp btif API declared*/ +extern INT32 mtk_wcn_stp_open_btif(VOID); +extern INT32 mtk_wcn_stp_close_btif(VOID); +extern INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb); +extern INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len); +extern INT32 mtk_wcn_stp_wakeup_consys(VOID); +extern INT32 mtk_wcn_stp_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag); +extern INT32 mtk_wcn_stp_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode); +extern INT32 mtk_wcn_stp_logger_ctrl(ENUM_BTIF_DBG_ID flag); +extern VOID mtk_wcn_stp_ctx_save(VOID); +extern VOID mtk_wcn_stp_ctx_restore(VOID); +extern INT32 mtk_wcn_stp_wmt_evt_err_trg_assert(VOID); +extern VOID mtk_wcn_stp_set_wmt_evt_err_trg_assert(UINT32 value); +extern UINT32 mtk_wcn_stp_get_wmt_evt_err_trg_assert(VOID); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_CORE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h new file mode 100644 index 0000000000000..94b3d8a597ac3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/stp_wmt.h @@ -0,0 +1,89 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _STP_WMT_H +#define _STP_WMT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum { + BTM_RST_OP = 0, + BTM_DMP_OP = 1, + BTM_GET_AEE_SUPPORT_FLAG = 2, + BTM_MAX_OP, +} MTKSTP_BTM_WMT_OP_T; + +typedef enum { + SLEEP = 0, + HOST_AWAKE, + WAKEUP, + EIRQ, + ROLL_BACK, + STP_PSM_MAX_ACTION +} MTKSTP_PSM_ACTION_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +extern MTK_WCN_BOOL wmt_lib_btm_cb(MTKSTP_BTM_WMT_OP_T op); + +extern INT32 wmt_lib_ps_stp_cb(MTKSTP_PSM_ACTION_T action); +extern MTK_WCN_BOOL wmt_lib_is_quick_ps_support(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _STP_WMT_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h new file mode 100644 index 0000000000000..4c64b6b5e65bb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_conf.h @@ -0,0 +1,74 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_CONF_H_ +#define _WMT_CONF_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CUST_CFG_WMT "WMT_SOC.cfg" +#define CUST_CFG_WMT_PREFIX "/system/etc/firmware/" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_conf_read_file(VOID); +P_WMT_GEN_CONF wmt_conf_get_cfg(VOID); +INT32 wmt_conf_set_cfg_file(const char *name); + +#endif /* _WMT_CONF_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h new file mode 100644 index 0000000000000..cca52a15cc982 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_core.h @@ -0,0 +1,428 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_CORE_H_ +#define _WMT_CORE_H_ + +#include "osal.h" +#include "wmt_ctrl.h" +#include "wmt_exp.h" +#include "wmt_plat.h" +/* TODO: [GeorgeKuo][FixMe] remove temporarily */ +/* for AIF state definition */ +/* #include "mtk_wcn_cmb_stub.h" */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +#define CFG_CORE_MT6620_SUPPORT 0 /* whether MT6620 is supported or not */ + +#define CFG_CORE_MT6628_SUPPORT 0 /* whether MT6628 is supported or not */ + +#define CFG_CORE_SOC_SUPPORT 1 + +/* TODO:[ChangeFeature][George] move this definition outside so that wmt_dev can remove wmt_core.h inclusion. */ +#define defaultPatchName "mt66xx_patch_hdr.bin" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define BCNT_PATCH_BUF_HEADROOM (8) + +#define DWCNT_HIF_CONF (4) +#define DWCNT_STRAP_CONF (4) +#define DWCNT_RESERVED (8) +#define DWCNT_CTRL_DATA (16) + +#if 0 /* TODO: [obsolete][GeorgeKuo]: remove ubsolete definitions */ +#define WMT_SET (1) +#define WMT_QUERY (0) +#define WMT_PKT_FMT_RAW (1) +#define WMT_PKT_FMT_STP (0) +#endif + +#define WMT_FUNC_CTRL_ON (MTK_WCN_BOOL_TRUE) +#define WMT_FUNC_CTRL_OFF (MTK_WCN_BOOL_FALSE) + +#define WMT_HDR_LEN (4) /* header length */ +#define WMT_STS_LEN (1) /* status length */ +#define WMT_FLAG_LEN (1) +#define WMT_HIF_UART_INFO_LEN (4) +#define WMT_FUNC_CTRL_PARAM_LEN (1) + +#define WMT_DEFAULT_BAUD_RATE (115200) + +#define INIT_CMD(c, e, s) {.cmd = c, .cmdSz = sizeof(c), .evt = e, .evtSz = sizeof(e), .str = s} + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_WMT_FM_T { + WMT_FM_INVALID = 0, + WMT_FM_I2C = 1, + WMT_FM_COMM = 2, + WMT_FM_MAX +} ENUM_WMT_FM_T, *P_ENUM_WMT_FM_T; + +typedef enum _ENUM_WMT_HIF_T { + WMT_HIF_UART = 0, + WMT_HIF_SDIO = 1, + WMT_HIF_BTIF = 2, + WMT_HIF_MAX +} ENUM_WMT_HIF_T, *P_ENUM_WMT_HIF_T; + +#if 0 /* [George] moved to wmt_exp.h for hif_sdio's use */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +typedef enum _ENUM_WMT_OPID_T { + WMT_OPID_HIF_CONF = 0, + WMT_OPID_PWR_ON = 1, + WMT_OPID_PWR_OFF = 2, + WMT_OPID_FUNC_ON = 3, + WMT_OPID_FUNC_OFF = 4, + WMT_OPID_REG_RW = 5, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ + WMT_OPID_EXIT = 6, + WMT_OPID_PWR_SV = 7, + WMT_OPID_DSNS = 8, + WMT_OPID_LPBK = 9, + WMT_OPID_CMD_TEST = 10, + WMT_OPID_HW_RST = 11, + WMT_OPID_SW_RST = 12, + WMT_OPID_BAUD_RST = 13, + WMT_OPID_STP_RST = 14, + WMT_OPID_THERM_CTRL = 15, + WMT_OPID_EFUSE_RW = 16, + WMT_OPID_GPIO_CTRL = 17, + WMT_OPID_FW_COREDMP = 18, + WMT_OPID_GPIO_STATE = 19, + WMT_OPID_BGW_DS = 20, + WMT_OPID_SET_MCU_CLK = 21, + WMT_OPID_ADIE_LPBK_TEST = 22, +#if CFG_WMT_LTE_COEX_HANDLING + WMT_OPID_IDC_MSG_HANDLING = 23, +#endif +#ifdef CONFIG_MTK_COMBO_ANT + WMT_OPID_ANT_RAM_DOWN = 24, + WMT_OPID_ANT_RAM_STA_GET = 25, +#endif + WMT_OPID_MAX +} ENUM_WMT_OPID_T, *P_ENUM_WMT_OPID_T; + +typedef OSAL_OP_DAT WMT_OP; +typedef P_OSAL_OP_DAT P_WMT_OP; + +typedef struct _WMT_HIF_CONF { + UINT32 hifType; /* HIF Type */ + UINT32 au4HifConf[DWCNT_HIF_CONF]; /* HIF Config */ + UINT32 au4StrapConf[DWCNT_STRAP_CONF]; /* Strap Config */ +} WMT_HIF_CONF, *P_WMT_HIF_CONF; + +typedef INT32(*WMT_OPID_FUNC) (P_WMT_OP); + +typedef struct _WMT_GEN_CONF { + UINT8 cfgExist; + + UINT8 coex_wmt_ant_mode; + UINT8 coex_wmt_ext_component; + UINT8 coex_wmt_wifi_time_ctl; + UINT8 coex_wmt_ext_pta_dev_on; + /*mt6592 and LTE coex filter mode setting */ + UINT8 coex_wmt_filter_mode; + + UINT8 coex_bt_rssi_upper_limit; + UINT8 coex_bt_rssi_mid_limit; + UINT8 coex_bt_rssi_lower_limit; + UINT8 coex_bt_pwr_high; + UINT8 coex_bt_pwr_mid; + UINT8 coex_bt_pwr_low; + + UINT8 coex_wifi_rssi_upper_limit; + UINT8 coex_wifi_rssi_mid_limit; + UINT8 coex_wifi_rssi_lower_limit; + UINT8 coex_wifi_pwr_high; + UINT8 coex_wifi_pwr_mid; + UINT8 coex_wifi_pwr_low; + + UINT8 coex_ext_pta_hi_tx_tag; + UINT8 coex_ext_pta_hi_rx_tag; + UINT8 coex_ext_pta_lo_tx_tag; + UINT8 coex_ext_pta_lo_rx_tag; + UINT16 coex_ext_pta_sample_t1; + UINT16 coex_ext_pta_sample_t2; + UINT8 coex_ext_pta_wifi_bt_con_trx; + + UINT32 coex_misc_ext_pta_on; + UINT32 coex_misc_ext_feature_set; + /*GPS LNA setting */ + UINT8 wmt_gps_lna_pin; + UINT8 wmt_gps_lna_enable; + /*Power on sequence */ + UINT8 pwr_on_rtc_slot; + UINT8 pwr_on_ldo_slot; + UINT8 pwr_on_rst_slot; + UINT8 pwr_on_off_slot; + UINT8 pwr_on_on_slot; + UINT8 co_clock_flag; + + /* Combo chip side SDIO driving setting */ + UINT32 sdio_driving_cfg; + +} WMT_GEN_CONF, *P_WMT_GEN_CONF; + +typedef enum _ENUM_DRV_STS_ { +#if 0 + DRV_STS_INVALID = 0, + DRV_STS_UNREG = 1, /* Initial State */ +#endif + DRV_STS_POWER_OFF = 0, /* initial state */ + DRV_STS_POWER_ON = 1, /* powered on, only WMT */ + DRV_STS_FUNC_ON = 2, /* FUNC ON */ + DRV_STS_MAX +} ENUM_DRV_STS, *P_ENUM_DRV_STS; + +typedef enum _WMT_IC_PIN_ID_ { + WMT_IC_PIN_AUDIO = 0, + WMT_IC_PIN_EEDI = 1, + WMT_IC_PIN_EEDO = 2, + WMT_IC_PIN_GSYNC = 3, + WMT_IC_PIN_MAX +} WMT_IC_PIN_ID, *P_WMT_IC_PIN_ID; + +typedef enum _WMT_IC_PIN_STATE_ { + WMT_IC_PIN_EN = 0, + WMT_IC_PIN_DIS = 1, + WMT_IC_AIF_0 = 2, /* = CMB_STUB_AIF_0, */ + WMT_IC_AIF_1 = 3, /* = CMB_STUB_AIF_1, */ + WMT_IC_AIF_2 = 4, /* = CMB_STUB_AIF_2, */ + WMT_IC_AIF_3 = 5, /* = CMB_STUB_AIF_3, */ + WMT_IC_PIN_MUX = 6, + WMT_IC_PIN_GPIO = 7, + WMT_IC_PIN_GPIO_HIGH = 8, + WMT_IC_PIN_GPIO_LOW = 9, + WMT_IC_PIN_STATE_MAX +} WMT_IC_PIN_STATE, *P_WMT_IC_PIN_STATE; + +typedef enum _WMT_CO_CLOCK_ { + WMT_CO_CLOCK_DIS = 0, + WMT_CO_CLOCK_EN = 1, + WMT_CO_CLOCK_MAX +} WMT_CO_CLOCK, *P_WMT_CO_CLOCK; + +typedef INT32(*SW_INIT) (P_WMT_HIF_CONF pWmtHifConf); +typedef INT32(*SW_DEINIT) (P_WMT_HIF_CONF pWmtHifConf); +typedef INT32(*IC_PIN_CTRL) (WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); +typedef INT32(*IC_VER_CHECK) (VOID); +typedef INT32(*CO_CLOCK_CTRL) (WMT_CO_CLOCK on); +typedef MTK_WCN_BOOL(*IS_QUICK_SLEEP_SUPPORT) (VOID); +typedef MTK_WCN_BOOL(*IS_AEE_DUMP_SUPPORT) (VOID); + +typedef struct _WMT_IC_OPS_ { + UINT32 icId; + SW_INIT sw_init; + SW_DEINIT sw_deinit; + IC_PIN_CTRL ic_pin_ctrl; + IC_VER_CHECK ic_ver_check; + CO_CLOCK_CTRL co_clock_ctrl; + IS_QUICK_SLEEP_SUPPORT is_quick_sleep; + IS_AEE_DUMP_SUPPORT is_aee_dump_support; +} WMT_IC_OPS, *P_WMT_IC_OPS; + +typedef struct _WMT_CTX_ { + ENUM_DRV_STS eDrvStatus[WMTDRV_TYPE_MAX]; /* Controlled driver status */ + UINT32 wmtInfoBit; /* valid info bit */ + WMT_HIF_CONF wmtHifConf; /* HIF information */ + + /* Pointer to WMT_IC_OPS. Shall be assigned to a correct table in stp_init + * if and only if getting chip id successfully. hwver and fwver are kept in + * WMT-IC module only. + */ + P_WMT_IC_OPS p_ic_ops; +} WMT_CTX, *P_WMT_CTX; + +/* TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. */ +/* Using this struct relies on compiler's implementation and pack() settings */ +typedef struct _WMT_PKT_ { + UINT8 eType; /* PKT_TYPE_* */ + UINT8 eOpCode; /* OPCODE_* */ + UINT16 u2SduLen; /* 2 bytes length, little endian */ + UINT8 aucParam[32]; +} WMT_PKT, *P_WMT_PKT; + +/* WMT Packet Format */ +typedef enum _ENUM_PKT_TYPE { + PKT_TYPE_INVALID = 0, + PKT_TYPE_CMD = 1, + PKT_TYPE_EVENT = 2, + _PKT_TYPE_MAX +} ENUM_PKT_TYPE, *P_ENUM_PKT_TYPE; + +typedef enum _ENUM_OPCODE { + OPCODE_INVALID = 0, + OPCODE_PATCH = 1, + OPCODE_TEST = 2, + OPCODE_WAKEUP = 3, + OPCODE_HIF = 4, + OPCODE_STRAP_CONF = 5, + OPCODE_FUNC_CTRL = 6, + OPCODE_RESET = 7, + OPCODE_INT = 8, + OPCODE_MAX +} ENUM_OPCODE, *P_ENUM_OPCODE; + +typedef enum { + WMT_STP_CONF_EN = 0, + WMT_STP_CONF_RDY = 1, + WMT_STP_CONF_MODE = 2, + WMT_STP_CONF_MAX +} WMT_STP_CONF_TYPE; + +struct init_script { + UINT8 *cmd; + UINT32 cmdSz; + UINT8 *evt; + UINT32 evtSz; + UINT8 *str; +}; + +typedef struct _WMT_PATCH { + UINT8 ucDateTime[16]; + UINT8 ucPLat[4]; + UINT16 u2HwVer; + UINT16 u2SwVer; + UINT32 u4PatchVer; +} WMT_PATCH, *P_WMT_PATCH; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_CORE_MT6620_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6620; +#endif + +#if CFG_CORE_MT6628_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_mt6628; +#endif + +#if CFG_CORE_SOC_SUPPORT +extern WMT_IC_OPS wmt_ic_ops_soc; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern INT32 wmt_core_init(VOID); +extern INT32 wmt_core_deinit(VOID); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_wmtd +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +extern INT32 wmt_core_opid(P_WMT_OP pWmtOp); + +extern INT32 wmt_core_ctrl(ENUM_WMT_CTRL_T ctrId, unsigned long *pPa1, unsigned long *pPa2); + +extern INT32 wmt_core_func_ctrl_cmd(ENUM_WMTDRV_TYPE_T type, MTK_WCN_BOOL fgEn); + +extern INT32 wmt_core_reg_rw_raw(UINT32 isWrite, UINT32 offset, PUINT32 pVal, UINT32 mask); + +extern VOID wmt_core_dump_data(PUINT8 pData, PUINT8 pTitle, UINT32 len); + +extern MTK_WCN_BOOL wmt_core_patch_check(UINT32 u4PatchVer, UINT32 u4HwVer); + +extern INT32 wmt_core_init_script(struct init_script *script, INT32 count); + +extern INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, UINT32 *readSize); + +extern INT32 wmt_core_tx(const PUINT8 pData, UINT32 size, PUINT32 writtenSize, MTK_WCN_BOOL bRawFlag); +extern MTK_WCN_BOOL wmt_core_is_quick_ps_support(void); + +extern MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void); + +#if CFG_CORE_INTERNAL_TXRX +extern INT32 wmt_core_lpbk_do_stp_init(void); +extern INT32 wmt_core_lpbk_do_stp_deinit(void); +#endif + +extern VOID wmt_core_set_coredump_state(ENUM_DRV_STS state); +#if CFG_WMT_LTE_COEX_HANDLING +extern VOID wmt_core_set_flag_for_test(UINT32 enable); +extern UINT32 wmt_core_get_flag_for_test(VOID); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static _osal_inline_ MTK_WCN_BOOL wmt_core_ic_ops_check(P_WMT_IC_OPS p_ops) +{ + if (!p_ops) + return MTK_WCN_BOOL_FALSE; + + if ((NULL == p_ops->sw_init) + || (NULL == p_ops->sw_deinit) + || (NULL == p_ops->ic_ver_check) + || (NULL == p_ops->ic_pin_ctrl)) + return MTK_WCN_BOOL_FALSE; + else + return MTK_WCN_BOOL_TRUE; +} + +#endif /* _WMT_CORE_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h new file mode 100644 index 0000000000000..0ff3d6058c394 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ctrl.h @@ -0,0 +1,120 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_CTRL_H_ +#define _WMT_CTRL_H_ + +#include "osal.h" +#include "wmt_stp_exp.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define DWCNT_CTRL_DATA (16) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _WMT_CTRL_DATA_ { + SIZE_T ctrlId; + SIZE_T au4CtrlData[DWCNT_CTRL_DATA]; +} WMT_CTRL_DATA, *P_WMT_CTRL_DATA; + +typedef enum _ENUM_WMT_CTRL_T { + WMT_CTRL_HW_PWR_OFF = 0, /* whole chip power off */ + WMT_CTRL_HW_PWR_ON = 1, /* whole chip power on */ + WMT_CTRL_HW_RST = 2, /* whole chip rst */ + WMT_CTRL_STP_CLOSE = 3, + WMT_CTRL_STP_OPEN = 4, + WMT_CTRL_STP_CONF = 5, + WMT_CTRL_FREE_PATCH = 6, + WMT_CTRL_GET_PATCH = 7, + WMT_CTRL_GET_PATCH_NAME = 8, + WMT_CTRL_HWIDVER_SET = 9, /* TODO: rename this and add chip id information in addition to chip version */ + WMT_CTRL_STP_RST = 10, + WMT_CTRL_GET_WMT_CONF = 11, + WMT_CTRL_TX = 12, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ + WMT_CTRL_RX = 13, /* [FixMe][GeorgeKuo]: to be removed by Sean's stp integration */ + WMT_CTRL_RX_FLUSH = 14, /* [FixMe][SeanWang]: to be removed by Sean's stp integration */ + WMT_CTRL_GPS_SYNC_SET = 15, + WMT_CTRL_GPS_LNA_SET = 16, + WMT_CTRL_PATCH_SEARCH = 17, + WMT_CTRL_CRYSTAL_TRIMING_GET = 18, + WMT_CTRL_CRYSTAL_TRIMING_PUT = 19, + WMT_CTRL_HW_STATE_DUMP = 20, + WMT_CTRL_GET_PATCH_NUM = 21, + WMT_CTRL_GET_PATCH_INFO = 22, + WMT_CTRL_SOC_PALDO_CTRL = 23, + WMT_CTRL_SOC_WAKEUP_CONSYS = 24, + WMT_CTRL_SET_STP_DBG_INFO = 25, + WMT_CTRL_BGW_DESENSE_CTRL = 26, + WMT_CTRL_EVT_ERR_TRG_ASSERT = 27, +#if CFG_WMT_LTE_COEX_HANDLING + WMT_CTRL_GET_TDM_REQ_ANTSEL = 28, +#endif + WMT_CTRL_EVT_PARSER = 29, + WMT_CTRL_MAX +} ENUM_WMT_CTRL_T, *P_ENUM_WMT_CTRL_T; + +typedef INT32(*WMT_CTRL_FUNC) (P_WMT_CTRL_DATA); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData); + +extern INT32 wmt_ctrl_tx_ex(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_CTRL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h new file mode 100644 index 0000000000000..d586f442e7ef0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_func.h @@ -0,0 +1,140 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_FUNC_H_ +#define _WMT_FUNC_H_ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_core.h" +#include "wmt_plat.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if 1 /* defined(CONFIG_MTK_COMBO_HCI_DRIVER) || defined(CONFIG_MTK_COMBO_BT) */ +#define CFG_FUNC_BT_SUPPORT 1 +#else +#define CFG_FUNC_BT_SUPPORT 0 +#endif + +#if 1 /* defined(CONFIG_MTK_COMBO_FM) */ +#define CFG_FUNC_FM_SUPPORT 1 +#else +#define CFG_FUNC_FM_SUPPORT 0 +#endif + +#if 1 /* defined(CONFIG_MTK_COMBO_GPS) */ +#define CFG_FUNC_GPS_SUPPORT 1 +#else +#define CFG_FUNC_GPS_SUPPORT 0 +#endif + +#if 1 /* defined(CONFIG_MTK_COMBO_WIFI) */ +#define CFG_FUNC_WIFI_SUPPORT 1 +#else +#define CFG_FUNC_WIFI_SUPPORT 0 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef INT32(*SUBSYS_FUNC_ON) (P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +typedef INT32(*SUBSYS_FUNC_OFF) (P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +typedef struct _WMT_FUNC_OPS_ { + SUBSYS_FUNC_ON func_on; + SUBSYS_FUNC_OFF func_off; +} WMT_FUNC_OPS, *P_WMT_FUNC_OPS; + +typedef struct _CMB_PIN_CTRL_REG_ { + UINT32 regAddr; + UINT32 regValue; + UINT32 regMask; + +} CMB_PIN_CTRL_REG, *P_CMB_PIN_CTRL_REG; + +typedef struct _CMB_PIN_CTRL_ { + UINT32 pinId; + UINT32 regNum; + P_CMB_PIN_CTRL_REG pFuncOnArray; + P_CMB_PIN_CTRL_REG pFuncOffArray; + +} CMB_PIN_CTRL, *P_CMB_PIN_CTRL; + +typedef enum _ENUM_CMP_PIN_ID_ { + CMB_PIN_EEDI_ID = 0, + CMB_PIN_EEDO_ID = 1, + CMB_PIN_GSYNC_ID = 2, +} ENUM_CMP_PIN_ID, *P_ENUM_CMP_PIN_ID; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_FUNC_BT_SUPPORT +extern WMT_FUNC_OPS wmt_func_bt_ops; +#endif + +#if CFG_FUNC_FM_SUPPORT +extern WMT_FUNC_OPS wmt_func_fm_ops; +#endif + +#if CFG_FUNC_GPS_SUPPORT +extern WMT_FUNC_OPS wmt_func_gps_ops; +#endif + +#if CFG_FUNC_WIFI_SUPPORT +extern WMT_FUNC_OPS wmt_func_wifi_ops; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_FUNC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h new file mode 100644 index 0000000000000..901becfdb92f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_ic.h @@ -0,0 +1,122 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_IC_H_ +#define _WMT_IC_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "wmt_core.h" +#include "wmt_exp.h" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WMT_IC_NAME_MT6620 "MT6620" +#define WMT_IC_NAME_MT6628 "MT6628" +#define WMT_IC_NAME_DEFAULT "SOC_CONSYS" + +#define WMT_IC_VER_E1 "E1" +#define WMT_IC_VER_E2 "E2" +#define WMT_IC_VER_E3 "E3" +#define WMT_IC_VER_E4 "E4" +#define WMT_IC_VER_E5 "E5" +#define WMT_IC_VER_E6 "E6" + +#define WMT_IC_PATCH_DUMMY_EXT "_ex" +#define WMT_IC_PATCH_NO_EXT "" +#define WMT_IC_PATCH_E1_EXT "_e1" +#define WMT_IC_PATCH_E2_EXT "_e2" +#define WMT_IC_PATCH_E3_EXT "_e3" +#define WMT_IC_PATCH_E4_EXT "_e4" +#define WMT_IC_PATCH_E5_EXT "_e5" +#define WMT_IC_PATCH_E6_EXT "_e6" + +#define WMT_IC_PATCH_TAIL "_hdr.bin" + +#define WMT_IC_INVALID_CHIP_ID 0xFFFF + +#define MAJORNUM(x) (x & 0x00F0) +#define MINORNUM(x) (x & 0x000F) + +/******************************************************************************* +* R E G I S T E R M A P +******************************************************************************** +*/ +/* General definition used for ALL/UNKNOWN CHIPS */ +/* Now MT6620 uses these definitions */ +#define GEN_CONFG_BASE (0x80000000UL) +#define GEN_HVR (GEN_CONFG_BASE + 0x0UL) /* HW_VER */ +#define GEN_FVR (GEN_CONFG_BASE + 0x4UL) /* FW_VER */ +#define GEN_VER_MASK (0x0000FFFFUL) /* HW_VER and FW_VER valid bits mask */ +#define GEN_HCR (GEN_CONFG_BASE + 0x8UL) /* HW_CODE, chip id */ +#define GEN_HCR_MASK (0x0000FFFFUL) /* HW_CODE valid bits mask */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _WMT_IC_INFO_S { + UINT32 u4HwVer; /* u4HwId */ + PUINT8 cChipName; + PUINT8 cChipVersion; + PUINT8 cPatchNameExt; + MTK_WCN_BOOL bPsmSupport; + MTK_WCN_BOOL bWorkWithoutPatch; + ENUM_WMTHWVER_TYPE_T eWmtHwVer; +} WMT_IC_INFO_S, *P_WMT_IC_INFO_S; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_IC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h new file mode 100644 index 0000000000000..b0c05cf3a2529 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/include/wmt_lib.h @@ -0,0 +1,300 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_LIB_H_ +#define _WMT_LIB_H_ + +#include "osal.h" +#include "wmt_core.h" +#include "wmt_exp.h" +#include +#include "stp_wmt.h" +#include "wmt_plat.h" +#include "wmt_idc.h" +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define WMT_OP_BUF_SIZE (16) + +typedef enum _ENUM_WMTRSTRET_TYPE_T { + WMTRSTRET_SUCCESS = 0x0, + WMTRSTRET_FAIL = 0x1, + WMTRSTRET_ONGOING = 0x2, + WMTRSTRET_MAX +} ENUM_WMTRSTRET_TYPE_T, *P_ENUM_WMTRSTRET_TYPE_T; + +/* +3(retry times) * 180 (STP retry time out) ++ 10 (firmware process time) + +10 (transmit time) + +10 (uart process -> WMT response pool) + +230 (others) +*/ +#define WMT_LIB_RX_TIMEOUT 20000 /*800-->cover v1.2phone BT function on time (~830ms) */ +/* +open wifi during wifi power on procedure +(because wlan is insert to system after mtk_hif_sdio module, +so wifi card is not registered to hif module +when mtk_wcn_wmt_func_on is called by wifi through rfkill) +*/ +#define MAX_WIFI_ON_TIME 55000 + +#define WMT_PWRON_RTY_DFT 2 +#define MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT (WMT_PWRON_RTY_DFT * WMT_LIB_RX_TIMEOUT) +#define MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY WMT_LIB_RX_TIMEOUT /*each WMT command */ +#define MAX_FUNC_ON_TIME \ + (MAX_WIFI_ON_TIME + MAX_RETRY_TIME_DUE_TO_RX_TIMEOUT + MAX_EACH_FUNC_ON_WHEN_CHIP_POWER_ON_ALREADY * 3) + +#define MAX_EACH_FUNC_OFF (WMT_LIB_RX_TIMEOUT + 1000) /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ +#define MAX_FUNC_OFF_TIME (MAX_EACH_FUNC_OFF * 4) + +#define MAX_EACH_WMT_CMD (WMT_LIB_RX_TIMEOUT + 1000) /*1000->WMT_LIB_RX_TIMEOUT + 1000, logical judgement */ + +#define MAX_GPIO_CTRL_TIME (2000) /* [FixMe][GeorgeKuo] a temp value */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* AIF FLAG definition */ +/* bit(0): share pin or not */ +#define WMT_LIB_AIF_FLAG_MASK (0x1UL) +#define WMT_LIB_AIF_FLAG_SHARE (0x1UL << 0) +#define WMT_LIB_AIF_FLAG_SEPARATE (0x0UL << 0) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* bit field offset definition */ +typedef enum { + WMT_STAT_PWR = 0, /* is powered on */ + WMT_STAT_STP_REG = 1, /* is STP driver registered: */ + WMT_STAT_STP_OPEN = 2, /* is STP opened: default FALSE */ + WMT_STAT_STP_EN = 3, /* is STP enabled: default FALSE */ + WMT_STAT_STP_RDY = 4, /* is STP ready for client: default FALSE */ + WMT_STAT_RX = 5, /* is rx data available */ + WMT_STAT_CMD = 6, /* is cmd string to be read */ + WMT_STAT_RST_ON = 7, + WMT_STAT_MAX +} WMT_STAT; + +typedef enum _ENUM_WMTRSTSRC_TYPE_T { + WMTRSTSRC_RESET_BT = 0x0, + WMTRSTSRC_RESET_FM = 0x1, + WMTRSTSRC_RESET_GPS = 0x2, + WMTRSTSRC_RESET_WIFI = 0x3, + WMTRSTSRC_RESET_STP = 0x4, + WMTRSTSRC_RESET_TEST = 0x5, + WMTRSTSRC_RESET_MAX +} ENUM_WMTRSTSRC_TYPE_T, *P_ENUM_WMTRSTSRC_TYPE_T; + +typedef struct { + PF_WMT_CB fDrvRst[4]; +} WMT_FDRV_CB, *P_WMT_FDRV_CB; + +typedef struct { + UINT32 dowloadSeq; + UINT8 addRess[4]; + UINT8 patchName[256]; +} WMT_PATCH_INFO, *P_WMT_PATCH_INFO; + +/* OS independent wrapper for WMT_OP */ +typedef struct _DEV_WMT_ { + + OSAL_SLEEPABLE_LOCK psm_lock; + OSAL_SLEEPABLE_LOCK idc_lock; + /* WMTd thread information */ + /* struct task_struct *pWmtd; */ + OSAL_THREAD thread; /* main thread (wmtd) handle */ + /* wait_queue_head_t rWmtdWq; */ + OSAL_EVENT rWmtdWq; /*WMTd command wait queue */ + /* ULONG state; */ + OSAL_BIT_OP_VAR state; /* bit field of WMT_STAT */ + + /* STP context information */ + /* wait_queue_head_t rWmtRxWq; */ + OSAL_EVENT rWmtRxWq; /* STP Rx wait queue */ + /* WMT_STP_FUNC rStpFunc; */ + WMT_FDRV_CB rFdrvCb; /* STP functions */ + + /* WMT Configurations */ + WMT_HIF_CONF rWmtHifConf; + WMT_GEN_CONF rWmtGenConf; + + /* Patch information */ + UINT8 cPatchName[NAME_MAX + 1]; + UINT8 cFullPatchName[NAME_MAX + 1]; + UINT32 patchNum; + + const osal_firmware *pPatch; + + UINT8 cWmtcfgName[NAME_MAX + 1]; + const osal_firmware *pWmtCfg; + + const osal_firmware *pNvram; + + /* Current used UART port description */ + INT8 cUartName[NAME_MAX + 1]; + + OSAL_OP_Q rFreeOpQ; /* free op queue */ + OSAL_OP_Q rActiveOpQ; /* active op queue */ + OSAL_OP arQue[WMT_OP_BUF_SIZE]; /* real op instances */ + P_OSAL_OP pCurOP; /* current op */ + + /* cmd str buffer */ + UINT8 cCmd[NAME_MAX + 1]; + INT32 cmdResult; + /* struct completion cmd_comp; */ + /* wait_queue_head_t cmd_wq; */ + OSAL_SIGNAL cmdResp; /* read command queues */ + OSAL_EVENT cmdReq; + + /* WMT loopback Thread Information */ + /* WMT_CMB_VER combo_ver; */ + /* P_WMT_CMB_CHIP_INFO_S pChipInfo; */ + UINT32 chip_id; + UINT32 hw_ver; + UINT32 fw_ver; + /* TODO: [FixMe][GeorgeKuo] remove this translated version code in the */ + /* future. Just return the above 3 info to querist */ + ENUM_WMTHWVER_TYPE_T eWmtHwVer; + + P_WMT_PATCH_INFO pWmtPatchInfo; +} DEV_WMT, *P_DEV_WMT; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern DEV_WMT gDevWmt; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +extern INT32 wmt_lib_init(VOID); +extern INT32 wmt_lib_deinit(VOID); +extern INT32 wmt_lib_tx(PUINT8 data, UINT32 size, PUINT32 writtenSize); +extern INT32 wmt_lib_tx_raw(PUINT8 data, UINT32 size, PUINT32 writtenSize); +extern INT32 wmt_lib_rx(PUINT8 buff, UINT32 buffLen, PUINT32 readSize); +extern VOID wmt_lib_flush_rx(VOID); + +#if CFG_WMT_PS_SUPPORT +extern INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime); +extern INT32 wmt_lib_ps_init(VOID); +extern INT32 wmt_lib_ps_deinit(VOID); +extern INT32 wmt_lib_ps_enable(VOID); +extern INT32 wmt_lib_ps_ctrl(UINT32 state); + +extern INT32 wmt_lib_ps_disable(VOID); +extern VOID wmt_lib_ps_irq_cb(VOID); +#endif +extern VOID wmt_lib_ps_set_sdio_psop(PF_WMT_SDIO_PSOP own_cb); + +/* LXOP functions: */ +extern P_OSAL_OP wmt_lib_get_free_op(VOID); +extern INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp); +extern MTK_WCN_BOOL wmt_lib_put_act_op(P_OSAL_OP pOp); + +/* extern ENUM_WMTHWVER_TYPE_T wmt_lib_get_hwver (VOID); */ +extern UINT32 wmt_lib_get_icinfo(ENUM_WMT_CHIPINFO_TYPE_T type); + +extern MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support(VOID); +extern MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support(VOID); +extern INT32 wmt_lib_trigger_cmd_signal(INT32 result); +extern PUINT8 wmt_lib_get_cmd(VOID); +extern P_OSAL_EVENT wmt_lib_get_cmd_event(VOID); +extern INT32 wmt_lib_set_patch_name(PUINT8 cPatchName); +extern INT32 wmt_lib_set_hif(unsigned long hifconf); +extern P_WMT_HIF_CONF wmt_lib_get_hif(VOID); +extern MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID); + +/* GeorgeKuo: replace set_chip_gpio() with more specific ones */ +#if 0 /* moved to wmt_exp.h */ +extern INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ +#endif +extern INT32 wmt_lib_host_awake_get(VOID); +extern INT32 wmt_lib_host_awake_put(VOID); +extern UINT32 wmt_lib_dbg_level_set(UINT32 level); + +extern INT32 wmt_lib_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); + +extern INT32 wmt_lib_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); +ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src); +MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst); +MTK_WCN_BOOL wmt_lib_hw_rst(VOID); +INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask); +INT32 wmt_lib_efuse_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask); + +extern INT32 DISABLE_PSM_MONITOR(void); +extern VOID ENABLE_PSM_MONITOR(void); +extern INT32 wmt_lib_notify_stp_sleep(void); +extern void wmt_lib_psm_lock_release(void); +extern INT32 wmt_lib_psm_lock_aquire(void); +extern VOID wmt_lib_idc_lock_release(VOID); +extern INT32 wmt_lib_idc_lock_aquire(VOID); +extern INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value); + +extern VOID wmt_lib_set_patch_num(UINT32 num); +extern VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo); +extern INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp); +extern P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev); +extern PUINT8 wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, PUINT8 buff, UINT32 len); +extern INT32 wmt_lib_poll_cpupcr(UINT32 count, UINT16 sleep, UINT16 toAee); +extern PUINT8 wmt_lib_get_cpupcr_xml_format(PUINT32 len); +extern INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl); +extern UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en); +extern INT8 wmt_lib_co_clock_get(VOID); +extern UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver); + +#if CFG_WMT_LTE_COEX_HANDLING +extern MTK_WCN_BOOL wmt_lib_handle_idc_msg(ipc_ilm_t *idc_infor); +#endif +#if CFG_WMT_PS_SUPPORT +extern UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en); +#endif +#if CONSYS_ENALBE_SET_JTAG +extern UINT32 wmt_lib_jtag_flag_set(UINT32 en); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_LIB_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c new file mode 100644 index 0000000000000..c826c513e2bd8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/psm_core.c @@ -0,0 +1,1890 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +#include "osal_typedef.h" +#include "osal.h" +#include "psm_core.h" +#include "stp_core.h" +#include + +INT32 gPsmDbgLevel = STP_PSM_LOG_INFO; +MTKSTP_PSM_T stp_psm_i; +MTKSTP_PSM_T *stp_psm = &stp_psm_i; + +STP_PSM_RECORD_T *g_stp_psm_dbg = NULL; +static UINT32 g_record_num; + +P_STP_PSM_OPID_RECORD g_stp_psm_opid_dbg = NULL; +static UINT32 g_opid_record_num; + +#define STP_PSM_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) \ + pr_debug(PFX_PSM "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_PSM_DBG_FUNC(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_DBG) \ + pr_debug(PFX_PSM "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_PSM_INFO_FUNC(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_INFO) \ + pr_debug(PFX_PSM "[I]%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_PSM_WARN_FUNC(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_WARN) \ + pr_warn(PFX_PSM "[W]%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_PSM_ERR_FUNC(fmt, arg...) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_ERR) \ + pr_err(PFX_PSM "[E]%s(%d):ERROR! " fmt, __func__ , __LINE__, ##arg); \ +} while (0) +#define STP_PSM_TRC_FUNC(f) \ +do { \ + if (gPsmDbgLevel >= STP_PSM_LOG_DBG) \ + pr_debug(PFX_PSM "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action); +static INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm); +static INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm); +static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num); +static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg); + +static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num); +static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg); + +static const char *g_psm_state[STP_PSM_MAX_STATE] = { + "ACT", + "ACT_INACT", + "INACT", + "INACT_ACT" +}; + +static const char *g_psm_action[STP_PSM_MAX_ACTION] = { + "SLEEP", + "HOST_AWAKE", + "WAKEUP", + "EIRQ", + "ROLL_BACK" +}; + +static const char *g_psm_op_name[STP_OPID_PSM_NUM] = { + "STP_OPID_PSM_SLEEP", + "STP_OPID_PSM_WAKEUP", + "STP_OPID_PSM_HOST_AWAKE", + "STP_OPID_PSM_EXIT" +}; + +static int _stp_psm_release_data(MTKSTP_PSM_T *stp_psm); + +static inline int _stp_psm_get_state(MTKSTP_PSM_T *stp_psm); + +static int _stp_psm_is_redundant_active_op(P_OSAL_OP pOp, P_OSAL_OP_Q pOpQ); + +static int _stp_psm_clean_up_redundant_active_op(P_OSAL_OP_Q pOpQ); +static MTK_WCN_BOOL _stp_psm_is_quick_ps_support(VOID); + +MTK_WCN_BOOL mtk_wcn_stp_psm_dbg_level(UINT32 dbglevel) +{ + if (dbglevel <= 4) { + gPsmDbgLevel = dbglevel; + STP_PSM_INFO_FUNC("gPsmDbgLevel = %d\n", gPsmDbgLevel); + return true; + } + STP_PSM_INFO_FUNC("invalid psm debug level. gPsmDbgLevel = %d\n", gPsmDbgLevel); + + return false; +} + +static INT32 _stp_psm_handler(MTKSTP_PSM_T *stp_psm, P_STP_OP pStpOp) +{ + INT32 ret = -1; + + /* if (NULL == pStpOp) */ + /* { */ + /* return -1; */ + /* } */ + ret = _stp_psm_thread_lock_aquire(stp_psm); + if (ret) { + STP_PSM_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + switch (pStpOp->opId) { + case STP_OPID_PSM_EXIT: + /* TODO: clean all up? */ + ret = 0; + break; + + case STP_OPID_PSM_SLEEP: + if (stp_psm_check_sleep_enable(stp_psm) > 0) + ret = _stp_psm_notify_wmt(stp_psm, SLEEP); + else + STP_PSM_INFO_FUNC("cancel sleep request\n"); + + break; + + case STP_OPID_PSM_WAKEUP: + ret = _stp_psm_notify_wmt(stp_psm, WAKEUP); + break; + + case STP_OPID_PSM_HOST_AWAKE: + ret = _stp_psm_notify_wmt(stp_psm, HOST_AWAKE); + break; + + default: + STP_PSM_ERR_FUNC("invalid operation id (%d)\n", pStpOp->opId); + ret = -1; + break; + } + _stp_psm_thread_lock_release(stp_psm); + return ret; +} + +static P_OSAL_OP _stp_psm_get_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP_Q pOpQ) +{ + P_OSAL_OP pOp; + + if (!pOpQ) { + STP_PSM_WARN_FUNC("pOpQ == NULL\n"); + return NULL; + } + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* acquire lock success */ + RB_GET(pOpQ, pOp); + + if ((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) { + /* stp_psm->current_active_op = pOp; */ + stp_psm->last_active_opId = pOp->op.opId; + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + if ((pOpQ == &stp_psm->rActiveOpQ) && (NULL != pOp)) + STP_PSM_DBG_FUNC("last_active_opId(%d)\n", stp_psm->last_active_opId); + + if (!pOp) + STP_PSM_WARN_FUNC("RB_GET fail\n"); + + return pOp; +} + +static INT32 _stp_psm_dump_active_q(P_OSAL_OP_Q pOpQ) +{ + UINT32 read_idx; + UINT32 write_idx; + UINT32 opId; + + if (pOpQ == &stp_psm->rActiveOpQ) { + read_idx = stp_psm->rActiveOpQ.read; + write_idx = stp_psm->rActiveOpQ.write; + + STP_PSM_DBG_FUNC("Active op list:++\n"); + while ((read_idx & RB_MASK(pOpQ)) != (write_idx & RB_MASK(pOpQ))) { + opId = pOpQ->queue[read_idx & RB_MASK(pOpQ)]->op.opId; + if (opId < STP_OPID_PSM_NUM) + STP_PSM_DBG_FUNC("%s\n", g_psm_op_name[opId]); + else + STP_PSM_WARN_FUNC("Unknown OP Id\n"); + + ++read_idx; + } + STP_PSM_DBG_FUNC("Active op list:--\n"); + } else { + STP_PSM_DBG_FUNC("%s: not active queue, dont dump\n", __func__); + } + + return 0; +} + +static int _stp_psm_is_redundant_active_op(P_OSAL_OP pOp, P_OSAL_OP_Q pOpQ) +{ + unsigned int opId = 0; + unsigned int prev_opId = 0; + + /* if((pOpQ == &stp_psm->rActiveOpQ) && (NULL != stp_psm->current_active_op)) */ + if ((pOpQ == &stp_psm->rActiveOpQ) && (STP_OPID_PSM_INALID != stp_psm->last_active_opId)) { + opId = pOp->op.opId; + + if (opId == STP_OPID_PSM_SLEEP) { + if (RB_EMPTY(pOpQ)) { + /* prev_opId = stp_psm->current_active_op->op.opId; */ + prev_opId = stp_psm->last_active_opId; + } else { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + } + + if (prev_opId == STP_OPID_PSM_SLEEP) { + STP_PSM_DBG_FUNC("redundant sleep opId found\n"); + return 1; + } else { + return 0; + } + } else { + if (RB_EMPTY(pOpQ)) { + /* prev_opId = stp_psm->current_active_op->op.opId; */ + prev_opId = stp_psm->last_active_opId; + } else { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + } + + if (((opId == STP_OPID_PSM_WAKEUP) && (prev_opId == STP_OPID_PSM_WAKEUP)) || + ((opId == STP_OPID_PSM_HOST_AWAKE) && (prev_opId == STP_OPID_PSM_WAKEUP)) || + ((opId == STP_OPID_PSM_HOST_AWAKE) && (prev_opId == STP_OPID_PSM_HOST_AWAKE)) || + ((opId == STP_OPID_PSM_WAKEUP) && (prev_opId == STP_OPID_PSM_HOST_AWAKE)) + ) { + STP_PSM_DBG_FUNC("redundant opId found, opId(%d), preOpid(%d)\n", opId, prev_opId); + return 1; + } else { + return 0; + } + } + } else { + return 0; + } + +} + +static int _stp_psm_clean_up_redundant_active_op(P_OSAL_OP_Q pOpQ) +{ + unsigned int prev_opId = 0; + unsigned int prev_prev_opId = 0; + + P_OSAL_OP pOp; + P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ; + + if (pOpQ == &stp_psm->rActiveOpQ) { + /* sleep , wakeup | sleep, --> null | sleep (x) */ + /* wakeup , sleep , wakeup | sleep --> wakeup | sleep (v) */ + /* sleep , wakeup , sleep | wakeup --> sleep | wakeup (v) */ + /* xxx, sleep | sleep --> xxx, sleep (v) */ + /* xxx, wakeup | wakeup --> xxx, wakeup (v) */ + /* xxx, awake | awake --> xxx, awake (v) --> should never happen */ + while (RB_COUNT(pOpQ) > 2) { + prev_opId = pOpQ->queue[(pOpQ->write - 1) & RB_MASK(pOpQ)]->op.opId; + prev_prev_opId = pOpQ->queue[(pOpQ->write - 2) & RB_MASK(pOpQ)]->op.opId; + + if ((prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_WAKEUP) || + (prev_opId == STP_OPID_PSM_SLEEP && prev_prev_opId == STP_OPID_PSM_HOST_AWAKE) || + (prev_opId == STP_OPID_PSM_WAKEUP && prev_prev_opId == STP_OPID_PSM_SLEEP) || + (prev_opId == STP_OPID_PSM_HOST_AWAKE && prev_prev_opId == STP_OPID_PSM_SLEEP) + ) { + RB_GET(pOpQ, pOp); + RB_PUT(pFreeOpQ, pOp); + RB_GET(pOpQ, pOp); + RB_PUT(pFreeOpQ, pOp); + } else if (prev_opId == prev_prev_opId) { + RB_GET(pOpQ, pOp); + STP_PSM_DBG_FUNC("redundant opId(%d) found, remove it\n", pOp->op.opId); + RB_PUT(pFreeOpQ, pOp); + } + } + } + + return 0; +} + +static INT32 _stp_psm_put_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + INT32 ret; + + /* if (!pOpQ || !pOp) */ + /* { */ + /* STP_PSM_WARN_FUNC("pOpQ = 0x%p, pLxOp = 0x%p\n", pOpQ, pOp); */ + /* return 0; */ + /* } */ + ret = 0; + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* acquire lock success */ + if (pOpQ == &stp_psm->rActiveOpQ) { + if (!_stp_psm_is_redundant_active_op(pOp, pOpQ)) { + /* acquire lock success */ + if (!RB_FULL(pOpQ)) { + RB_PUT(pOpQ, pOp); + STP_PSM_DBG_FUNC("opId(%d) enqueue\n", pOp->op.opId); + } else { + STP_PSM_INFO_FUNC("************ Active Queue Full ************\n"); + ret = -1; + } + + _stp_psm_clean_up_redundant_active_op(pOpQ); + } else { + /*redundant opId, mark ret as success */ + P_OSAL_OP_Q pFreeOpQ = &stp_psm->rFreeOpQ; + + if (!RB_FULL(pFreeOpQ)) + RB_PUT(pFreeOpQ, pOp); + else + osal_assert(!RB_FULL(pFreeOpQ)); + + ret = 0; + } + } else { + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else + ret = -1; + + } + + if (pOpQ == &stp_psm->rActiveOpQ) + _stp_psm_dump_active_q(&stp_psm->rActiveOpQ); + + + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + STP_PSM_DBG_FUNC("stp_psm do unlock,active queue? (%s)\n", (pOpQ == &stp_psm->rActiveOpQ) ? "y" : "n"); + + if (ret) { + STP_PSM_WARN_FUNC("RB_FULL, RB_COUNT=%d , RB_SIZE=%d\n", RB_COUNT(pOpQ), RB_SIZE(pOpQ)); + return 0; + } else + return 1; + +} + +P_OSAL_OP _stp_psm_get_free_op(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + + if (stp_psm) { + pOp = _stp_psm_get_op(stp_psm, &stp_psm->rFreeOpQ); + if (pOp) + osal_memset(&pOp->op, 0, sizeof(pOp->op)); + + return pOp; + } else + return NULL; + +} + +INT32 _stp_psm_put_act_op(MTKSTP_PSM_T *stp_psm, P_OSAL_OP pOp) +{ + INT32 bRet = 0; /* MTK_WCN_BOOL_FALSE; */ + INT32 bCleanup = 0; /* MTK_WCN_BOOL_FALSE; */ + INT32 wait_ret = -1; + P_OSAL_SIGNAL pSignal = NULL; + + do { + if (!stp_psm || !pOp) { + STP_PSM_ERR_FUNC("stp_psm = %p, pOp = %p\n", stp_psm, pOp); + break; + } + + pSignal = &pOp->signal; + + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(&pOp->signal); + } + + /* put to active Q */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rActiveOpQ, pOp); + + if (0 == bRet) { + STP_PSM_WARN_FUNC("+++++++++++ Put op Active queue Fail\n"); + bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ + break; + } + _stp_psm_opid_dbg_dmp_in(g_stp_psm_opid_dbg, pOp->op.opId, __LINE__); + + /* wake up wmtd */ + osal_trigger_event(&stp_psm->STPd_event); + + if (pSignal->timeoutValue == 0) { + bRet = 1; /* MTK_WCN_BOOL_TRUE; */ + /* clean it in wmtd */ + break; + } + + /* wait result, clean it here */ + bCleanup = 1; /* MTK_WCN_BOOL_TRUE; */ + + /* check result */ + wait_ret = osal_wait_for_signal_timeout(&pOp->signal); + STP_PSM_DBG_FUNC("wait completion:%d\n", wait_ret); + if (!wait_ret) { + STP_PSM_ERR_FUNC("wait completion timeout\n"); + /* TODO: how to handle it? retry? */ + } else { + if (pOp->result) + STP_PSM_WARN_FUNC("op(%d) result:%d\n", pOp->op.opId, pOp->result); + /* op completes, check result */ + bRet = (pOp->result) ? 0 : 1; + } + } while (0); + + if (bCleanup) { + /* put Op back to freeQ */ + bRet = _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp); + if (bRet == 0) + STP_PSM_WARN_FUNC("+++++++++++ Put op active free fail, maybe disable/enable psm\n"); + } + + return bRet; +} + +static INT32 _stp_psm_wait_for_msg(void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; + + STP_PSM_DBG_FUNC("%s: stp_psm->rActiveOpQ = %d\n", __func__, RB_COUNT(&stp_psm->rActiveOpQ)); + + return (!RB_EMPTY(&stp_psm->rActiveOpQ)) || osal_thread_should_stop(&stp_psm->PSMd); +} + +static INT32 _stp_psm_proc(void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; + P_OSAL_OP pOp; + UINT32 id; + INT32 result; + + if (!stp_psm) { + STP_PSM_WARN_FUNC("!stp_psm\n"); + return -1; + } +/* STP_PSM_INFO_FUNC("wmtd starts running: pWmtDev(0x%p) [pol, rt_pri, n_pri, pri]=[%d, %d, %d, %d]\n", */ +/* stp_psm, current->policy, current->rt_priority, current->normal_prio, current->prio); */ + + for (;;) { + + pOp = NULL; + + osal_wait_for_event(&stp_psm->STPd_event, _stp_psm_wait_for_msg, (void *)stp_psm); + + /* we set reset flag when calling stp_reset after cleanup all op. */ + if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_RESET_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + if (osal_thread_should_stop(&stp_psm->PSMd)) { + STP_PSM_INFO_FUNC("should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + + /* get Op from activeQ */ + pOp = _stp_psm_get_op(stp_psm, &stp_psm->rActiveOpQ); + if (!pOp) { + STP_PSM_WARN_FUNC("+++++++++++ Get op from activeQ fail, maybe disable/enable psm\n"); + continue; + } + + id = osal_op_get_id(pOp); + + if (id >= STP_OPID_PSM_NUM) { + STP_PSM_WARN_FUNC("abnormal opid id: 0x%x\n", id); + result = -1; + goto handler_done; + } + + result = _stp_psm_handler(stp_psm, &pOp->op); + +handler_done: + + if (result) { + STP_PSM_WARN_FUNC("opid id(0x%x)(%s) error(%d)\n", id, + (id >= 4) ? ("???") : (g_psm_op_name[id]), result); + } + + if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, result); + else { + /* put Op back to freeQ */ + if (_stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, pOp) == 0) + STP_PSM_WARN_FUNC("+++++++++++ Put op to FreeOpQ fail, maybe disable/enable psm\n"); + } + + if (STP_OPID_PSM_EXIT == id) + break; + } + STP_PSM_INFO_FUNC("exits\n"); + + return 0; +}; + +static inline INT32 _stp_psm_get_time(void) +{ + if (gPsmDbgLevel >= STP_PSM_LOG_LOUD) + osal_printtimeofday(">>>"); + + return 0; +} + +static inline INT32 _stp_psm_get_state(MTKSTP_PSM_T *stp_psm) +{ + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + if (stp_psm->work_state < STP_PSM_MAX_STATE) + return stp_psm->work_state; + STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); + + return STP_PSM_OPERATION_FAIL; +} + +static inline INT32 _stp_psm_set_state(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_STATE_T state) +{ + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + if (stp_psm->work_state < STP_PSM_MAX_STATE) { + _stp_psm_get_time(); + /* STP_PSM_INFO_FUNC("work_state = %s --> %s\n", + * g_psm_state[stp_psm->work_state], g_psm_state[state]); + */ + + stp_psm->work_state = state; + if (stp_psm->work_state != ACT) { + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + osal_set_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + } + } else + STP_PSM_ERR_FUNC("work_state = %d, invalid\n", stp_psm->work_state); + + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_DBG_FUNC("STP-PSM DISABLE, DONT restart monitor!\n\r"); + return STP_PSM_OPERATION_SUCCESS; + } + + STP_PSM_LOUD_FUNC("start monitor\n"); + osal_timer_modify(&stp_psm->psm_timer, stp_psm->idle_time_to_sleep); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_stop_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + STP_PSM_DBG_FUNC("stop monitor\n"); + osal_timer_stop_sync(&stp_psm->psm_timer); + + return STP_PSM_OPERATION_SUCCESS; +} + +INT32 _stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type) +{ + INT32 available_space = 0; + INT32 needed_space = 0; + UINT8 delimiter[] = { 0xbb, 0xbb }; + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + available_space = STP_PSM_FIFO_SIZE - osal_fifo_len(&stp_psm->hold_fifo); + needed_space = len + sizeof(UINT8) + sizeof(UINT32) + 2; + + /* STP_PSM_INFO_FUNC("*******FIFO Available(%d), Need(%d)\n", available_space, needed_space); */ + + if (available_space < needed_space) { + STP_PSM_ERR_FUNC("FIFO Available!! Reset FIFO\n"); + osal_fifo_reset(&stp_psm->hold_fifo); + } + /* type */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &type, sizeof(UINT8)); + /* length */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) &len, sizeof(UINT32)); + /* buffer */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) buffer, len); + /* delimiter */ + osal_fifo_in(&stp_psm->hold_fifo, (PUINT8) delimiter, 2); + + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + return len; + +} + +INT32 _stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) +{ + return osal_fifo_len(&stp_psm->hold_fifo); +} + +INT32 _stp_psm_release_data(MTKSTP_PSM_T *stp_psm) +{ + + INT32 i = 20; /*Max buffered packet number */ + INT32 ret = 0; + UINT8 type = 0; + UINT32 len = 0; + UINT8 delimiter[2]; + + /* STP_PSM_ERR_FUNC("++++++++++release data++len=%d\n", osal_fifo_len(&stp_psm->hold_fifo)); */ + while (osal_fifo_len(&stp_psm->hold_fifo) && i > 0) { + /* acquire spinlock */ + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) &type, sizeof(UINT8)); + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) &len, sizeof(UINT32)); + + if (len > STP_PSM_PACKET_SIZE_MAX) { + STP_PSM_ERR_FUNC("***psm packet's length too Long!****\n"); + STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); + } else { + osal_memset(stp_psm->out_buf, 0, STP_PSM_TX_SIZE); + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) stp_psm->out_buf, len); + } + + ret = osal_fifo_out(&stp_psm->hold_fifo, (PUINT8) delimiter, 2); + + if (delimiter[0] == 0xbb && delimiter[1] == 0xbb) { + /* osal_buffer_dump(stp_psm->out_buf, "psm->out_buf", len, 32); */ + stp_send_data_no_ps(stp_psm->out_buf, len, type); + } else { + STP_PSM_ERR_FUNC("***psm packet fifo parsing fail****\n"); + STP_PSM_INFO_FUNC("***reset psm's fifo***\n"); + + osal_fifo_reset(&stp_psm->hold_fifo); + } + i--; + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + } + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_notify_wmt_host_awake_wq(MTKSTP_PSM_T *stp_psm) +{ + + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + + pOp->op.opId = STP_OPID_PSM_HOST_AWAKE; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + + STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 0; + + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_wakeup_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + + pOp->op.opId = STP_OPID_PSM_WAKEUP; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + if (0 == bRet) { + STP_PSM_WARN_FUNC("OPID(%d) type(%zd) bRet(%s)\n\n", + pOp->op.opId, pOp->op.au4OpData[0], "fail"); + } + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : (STP_PSM_OPERATION_SUCCESS); + + return retval; +} + +static inline INT32 _stp_psm_notify_wmt_sleep_wq(MTKSTP_PSM_T *stp_psm) +{ + P_OSAL_OP pOp; + INT32 bRet; + INT32 retval; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag)) + return 0; +#if PSM_USE_COUNT_PACKAGE + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag)) + return 0; +#endif + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) + return 0; + + pOp = _stp_psm_get_free_op(stp_psm); + if (!pOp) { + STP_PSM_WARN_FUNC("get_free_lxop fail\n"); + return -1; /* break; */ + } + + pOp->op.opId = STP_OPID_PSM_SLEEP; + pOp->signal.timeoutValue = 0; + bRet = _stp_psm_put_act_op(stp_psm, pOp); + + STP_PSM_DBG_FUNC("OPID(%d) type(%zd) bRet(%d)\n\n", pOp->op.opId, pOp->op.au4OpData[0], bRet); + + retval = (0 == bRet) ? (STP_PSM_OPERATION_FAIL) : 1; + + return retval; +} + +/*internal function*/ + +static inline INT32 _stp_psm_reset(MTKSTP_PSM_T *stp_psm) +{ + INT32 i = 0; + P_OSAL_OP_Q pOpQ; + P_OSAL_OP pOp; + + STP_PSM_DBG_FUNC("PSM MODE RESET=============================>\n\r"); + + STP_PSM_DBG_FUNC("_stp_psm_reset\n"); + STP_PSM_DBG_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("reset-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + /* --> disable psm <--// */ + stp_psm->flag.data = 0; + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_stop_monitor(stp_psm); + + /* --> prepare the op list <--// */ + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); + RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); + + /* stp_psm->current_active_op = NULL; */ + stp_psm->last_active_opId = STP_OPID_PSM_INALID; + + pOpQ = &stp_psm->rFreeOpQ; + for (i = 0; i < STP_OP_BUF_SIZE; i++) { + if (!RB_FULL(pOpQ)) { + pOp = &stp_psm->arQue[i]; + RB_PUT(pOpQ, pOp); + } + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + /* --> clean up interal data structure<--// */ + _stp_psm_set_state(stp_psm, ACT); + + osal_lock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + osal_fifo_reset(&stp_psm->hold_fifo); + osal_unlock_sleepable_lock(&stp_psm->hold_fifo_spinlock_global); + + /* --> stop psm thread wait <--// */ + osal_set_bit(STP_PSM_RESET_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_trigger_event(&stp_psm->wait_wmt_q); + + STP_PSM_DBG_FUNC("PSM MODE RESET<============================\n\r"); + + return STP_PSM_OPERATION_SUCCESS; +} + +static INT32 _stp_psm_wait_wmt_event(void *pvData) +{ + MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) pvData; + + STP_PSM_DBG_FUNC("%s, stp_psm->flag= %ld\n", __func__, stp_psm->flag.data); + + return (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) || + (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)); +} + +static inline INT32 _stp_psm_wait_wmt_event_wq(MTKSTP_PSM_T *stp_psm) +{ + + INT32 retval = 0; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + osal_wait_for_event_timeout(&stp_psm->wait_wmt_q, _stp_psm_wait_wmt_event, (void *)stp_psm); + + if (osal_test_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); +/* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + /* STP send data here: STP enqueue data to psm buffer. */ + _stp_psm_release_data(stp_psm); + /* STP send data here: STP enqueue data to psm buffer. We release packet by the next one. */ + osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* STP send data here: STP sends data directly without PSM. */ + _stp_psm_set_state(stp_psm, ACT); +/* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + + if (stp_psm_is_quick_ps_support()) + stp_psm_notify_wmt_sleep(stp_psm); + else + _stp_psm_start_monitor(stp_psm); + } else if (osal_test_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_set_state(stp_psm, INACT); + + STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle++\n"); + mt_combo_plt_enter_deep_idle(COMBO_IF_BTIF); + STP_PSM_DBG_FUNC("mt_combo_plt_enter_deep_idle--\n"); + + STP_PSM_DBG_FUNC("sleep-wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_unlock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("sleep-wake_lock#(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + } else if (osal_test_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + if (_stp_psm_get_state(stp_psm) == ACT_INACT) { + /* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + _stp_psm_release_data(stp_psm); + osal_clear_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + _stp_psm_set_state(stp_psm, ACT); + /* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + } else if (_stp_psm_get_state(stp_psm) == INACT_ACT) { + _stp_psm_set_state(stp_psm, INACT); + STP_PSM_INFO_FUNC("[WARNING]PSM state rollback due too wakeup fail\n"); + } + } else if (osal_test_bit(STP_PSM_RESET_EN, &stp_psm->flag)) { + osal_clear_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } else { + STP_PSM_ERR_FUNC("flag = %ld<== Abnormal flag be set!!\n\r", stp_psm->flag.data); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + wcn_psm_flag_trigger_collect_ftrace(); /* trigger collect SYS_FTRACE */ + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + } + retval = STP_PSM_OPERATION_SUCCESS; + + return retval; +} + +static inline INT32 _stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + + INT32 retval = 0; + + if (action == EIRQ) { + STP_PSM_DBG_FUNC("Call _stp_psm_notify_wmt_host_awake_wq\n\r"); + + _stp_psm_notify_wmt_host_awake_wq(stp_psm); + + return STP_PSM_OPERATION_FAIL; + } + + if ((_stp_psm_get_state(stp_psm) < STP_PSM_MAX_STATE) && (_stp_psm_get_state(stp_psm) >= 0)) { + STP_PSM_DBG_FUNC("state = %s, action=%s\n\r", g_psm_state[_stp_psm_get_state(stp_psm)], + g_psm_action[action]); + } + /* If STP trigger WAKEUP and SLEEP, to do the job below */ + switch (_stp_psm_get_state(stp_psm)) { + /* stp trigger */ + case ACT_INACT: + + if (action == SLEEP) { + STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, ready to INACT\n\r", g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == ROLL_BACK) { + STP_PSM_LOUD_FUNC("Action = %s, ACT_INACT state, back to ACT\n\r", g_psm_action[action]); + /* stp_psm->flag &= ~STP_PSM_WMT_EVENT_ROLL_BACK_EN; */ + osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else { + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_ERR_FUNC("Action = %s, ACT_INACT state, the case should not happens\n\r", + g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = STP_PSM_OPERATION_FAIL; + } + break; + /* stp trigger */ + + case INACT_ACT: + + if (action == WAKEUP) { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == HOST_AWAKE) { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, ready to ACT\n\r", g_psm_action[action]); + osal_clear_bit(STP_PSM_WMT_EVENT_SLEEP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_set_bit(STP_PSM_WMT_EVENT_WAKEUP_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else if (action == ROLL_BACK) { + STP_PSM_LOUD_FUNC("Action = %s, INACT_ACT state, back to INACT\n\r", g_psm_action[action]); + osal_set_bit(STP_PSM_WMT_EVENT_ROLL_BACK_EN, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + /* wake_up(&stp_psm->wait_wmt_q); */ + osal_trigger_event(&stp_psm->wait_wmt_q); + } else { + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_ERR_FUNC("Action = %s, INACT_ACT state, the case should not happens\n\r", + g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = STP_PSM_OPERATION_FAIL; + } + break; + + case INACT: + + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_ERR_FUNC("Action = %s, INACT state, the case should not happens\n\r", + g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = -1; + + break; + + case ACT: + + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_ERR_FUNC("Action = %s, ACT state, the case should not happens\n\r", + g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = STP_PSM_OPERATION_FAIL; + + break; + + default: + + /*invalid */ + if (action < STP_PSM_MAX_ACTION) { + STP_PSM_ERR_FUNC("Action = %s, Invalid state, the case should not happens\n\r", + g_psm_action[action]); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + } else { + STP_PSM_ERR_FUNC("Invalid Action!!\n\r"); + } + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + retval = STP_PSM_OPERATION_FAIL; + + break; + } + + return retval; + +} + +static inline INT32 _stp_psm_notify_wmt(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + INT32 ret = 0; + + if (stp_psm == NULL) + return STP_PSM_OPERATION_FAIL; + + switch (_stp_psm_get_state(stp_psm)) { + case ACT: + + if (action == SLEEP) { + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_ERR_FUNC("psm monitor disabled, can't do sleep op\n"); + return STP_PSM_OPERATION_FAIL; + } + + _stp_psm_set_state(stp_psm, ACT_INACT); + + _stp_psm_release_data(stp_psm); + + if (stp_psm->wmt_notify) { + stp_psm->wmt_notify(SLEEP); + _stp_psm_wait_wmt_event_wq(stp_psm); + } else { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } else if (action == WAKEUP || action == HOST_AWAKE) { + STP_PSM_INFO_FUNC("In ACT state, dont do WAKEUP/HOST_AWAKE again\n"); + _stp_psm_release_data(stp_psm); + } else { + STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + + } + + break; + + case INACT: + + if (action == WAKEUP) { + _stp_psm_set_state(stp_psm, INACT_ACT); + + if (stp_psm->wmt_notify) { + STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("wakeup +wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); + mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); + + stp_psm->wmt_notify(WAKEUP); + _stp_psm_wait_wmt_event_wq(stp_psm); + } else { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } else if (action == HOST_AWAKE) { + _stp_psm_set_state(stp_psm, INACT_ACT); + + if (stp_psm->wmt_notify) { + STP_PSM_DBG_FUNC("host awake +wake_lock(%d)\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("host awake +wake_lock(%d)#\n", + osal_wake_lock_count(&stp_psm->wake_lock)); + + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle++\n"); + mt_combo_plt_exit_deep_idle(COMBO_IF_BTIF); + STP_PSM_DBG_FUNC("mt_combo_plt_exit_deep_idle--\n"); + + stp_psm->wmt_notify(HOST_AWAKE); + _stp_psm_wait_wmt_event_wq(stp_psm); + } else { + STP_PSM_ERR_FUNC("stp_psm->wmt_notify = NULL\n"); + ret = STP_PSM_OPERATION_FAIL; + } + } else if (action == SLEEP) { + STP_PSM_INFO_FUNC("In INACT state, dont do SLEEP again\n"); + } else { + STP_PSM_ERR_FUNC("invalid operation, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + } + + break; + + default: + + /*invalid */ + STP_PSM_ERR_FUNC("invalid state, the case should not happen\n"); + STP_PSM_ERR_FUNC("state = %d, flag = %ld\n", stp_psm->work_state, stp_psm->flag.data); + _stp_psm_dbg_out_printk(g_stp_psm_dbg); + ret = STP_PSM_OPERATION_FAIL; + + break; + } + return ret; +} + +static inline void _stp_psm_stp_is_idle(/*unsigned long data*/struct timer_list *t) +{ + //MTKSTP_PSM_T *stp_psm = (MTKSTP_PSM_T *) data; + MTKSTP_PSM_T *stp_psm = from_timer(stp_psm,t,psm_timer.timer); + + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) { + STP_PSM_DBG_FUNC("STP-PSM DISABLE!\n"); + return; + } + + if (1 == _stp_psm_notify_wmt_sleep_wq(stp_psm)) + STP_PSM_INFO_FUNC("**IDLE is over %d msec, go to sleep!!!**\n", stp_psm->idle_time_to_sleep); +} + +static inline INT32 _stp_psm_init_monitor(MTKSTP_PSM_T *stp_psm) +{ + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + STP_PSM_INFO_FUNC("init monitor\n"); + + stp_psm->psm_timer.timeoutHandler = _stp_psm_stp_is_idle; + stp_psm->psm_timer.timeroutHandlerData = (unsigned long)stp_psm; + osal_timer_create(&stp_psm->psm_timer); + + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_deinit_monitor(MTKSTP_PSM_T *stp_psm) +{ + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + STP_PSM_INFO_FUNC("deinit monitor\n"); + + osal_timer_stop_sync(&stp_psm->psm_timer); + + return 0; +} + +static inline INT32 _stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) +{ + INT32 iRet = -1; + +/* osal_lock_unsleepable_lock(&stp_psm->flagSpinlock); */ + + if (osal_test_bit(STP_PSM_BLOCK_DATA_EN, &stp_psm->flag)) + iRet = 1; + else + iRet = 0; + +/* osal_unlock_unsleepable_lock(&stp_psm->flagSpinlock); */ + return iRet; +} + +static inline INT32 _stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) +{ + if (osal_test_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag)) + return 1; + else + return 0; +} + +static inline INT32 _stp_psm_do_wait(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) +{ + +#define POLL_WAIT 20 /* 200 */ +#define POLL_WAIT_TIME 2000 + + INT32 i = 0; + INT32 limit = POLL_WAIT_TIME / POLL_WAIT; + + while (_stp_psm_get_state(stp_psm) != state && i < limit) { + osal_sleep_ms(POLL_WAIT); + i++; + STP_PSM_INFO_FUNC("STP is waiting state for %s, i=%d, state = %d\n", g_psm_state[state], i, + _stp_psm_get_state(stp_psm)); + } + + if (i == limit) { + STP_PSM_WARN_FUNC("-Wait for %s takes %d msec\n", g_psm_state[state], i * POLL_WAIT); + _stp_psm_opid_dbg_out_printk(g_stp_psm_opid_dbg); + return STP_PSM_OPERATION_FAIL; + } + STP_PSM_DBG_FUNC("+Total waits for %s takes %d msec\n", g_psm_state[state], i * POLL_WAIT); + /* _stp_psm_dbg_out_printk(g_stp_psm_opid_dbg); */ + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) +{ + + INT32 ret = 0; + INT32 retry = 10; + P_OSAL_OP_Q pOpQ; + P_OSAL_OP pOp; + + STP_PSM_LOUD_FUNC("*** Do Force Wakeup!***\n\r"); + + /* <1>If timer is active, we will stop it. */ + _stp_psm_stop_monitor(stp_psm); + + osal_lock_unsleepable_lock(&(stp_psm->wq_spinlock)); + + pOpQ = &stp_psm->rFreeOpQ; + + while (!RB_EMPTY(&stp_psm->rActiveOpQ)) { + RB_GET(&stp_psm->rActiveOpQ, pOp); + if (NULL != pOp && !RB_FULL(pOpQ)) { + STP_PSM_DBG_FUNC("opid = %d\n", pOp->op.opId); + RB_PUT(pOpQ, pOp); + } else { + STP_PSM_ERR_FUNC("clear up active queue fail, freeQ full\n"); + } + } + osal_unlock_unsleepable_lock(&(stp_psm->wq_spinlock)); + /* <5>We issue wakeup request into op queue. and wait for active. */ + do { + ret = _stp_psm_notify_wmt_wakeup_wq(stp_psm); + + if (ret == STP_PSM_OPERATION_SUCCESS) { + ret = _stp_psm_do_wait(stp_psm, ACT); + + /* STP_PSM_INFO_FUNC("<< wait ret = %d, num of activeQ = %d\n", + * ret, RB_COUNT(&stp_psm->rActiveOpQ)); + */ + if (ret == STP_PSM_OPERATION_SUCCESS) + break; + } else + STP_PSM_ERR_FUNC("_stp_psm_notify_wmt_wakeup_wq fail!!\n"); + + /* STP_PSM_INFO_FUNC("retry = %d\n", retry); */ + retry--; + + if (retry == 0) + break; + } while (1); + + if (retry == 0) + return STP_PSM_OPERATION_FAIL; + else + return STP_PSM_OPERATION_SUCCESS; +} + +static inline INT32 _stp_psm_disable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = STP_PSM_OPERATION_FAIL; + + STP_PSM_DBG_FUNC("PSM Disable start\n\r"); + + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + ret = _stp_psm_do_wakeup(stp_psm); + if (ret == STP_PSM_OPERATION_SUCCESS) + STP_PSM_DBG_FUNC("PSM Disable Success\n"); + else + STP_PSM_ERR_FUNC("***PSM Disable Fail***\n"); + + return ret; +} + +static inline INT32 _stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) +{ + INT32 ret = STP_PSM_OPERATION_FAIL; + + STP_PSM_LOUD_FUNC("PSM Enable start\n\r"); + + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + + ret = _stp_psm_do_wakeup(stp_psm); + if (ret == STP_PSM_OPERATION_SUCCESS) { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm->idle_time_to_sleep = idle_time_to_sleep; + + if (osal_wake_lock_count(&stp_psm->wake_lock) == 0) { + STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)\n", osal_wake_lock_count(&stp_psm->wake_lock)); + osal_wake_lock(&stp_psm->wake_lock); + STP_PSM_DBG_FUNC("psm_en+wake_lock(%d)#\n", osal_wake_lock_count(&stp_psm->wake_lock)); + } + + _stp_psm_start_monitor(stp_psm); + + STP_PSM_DBG_FUNC("PSM Enable succeed\n\r"); + } else + STP_PSM_ERR_FUNC("***PSM Enable Fail***\n"); + + return ret; +} + +INT32 _stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) +{ + return osal_lock_sleepable_lock(&stp_psm->stp_psm_lock); +} + +INT32 _stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) +{ + osal_unlock_sleepable_lock(&stp_psm->stp_psm_lock); + return 0; +} + +MTK_WCN_BOOL _stp_psm_is_quick_ps_support(VOID) +{ + if (stp_psm->is_wmt_quick_ps_support) + return (*(stp_psm->is_wmt_quick_ps_support)) (); + + STP_PSM_DBG_FUNC("stp_psm->is_wmt_quick_ps_support is NULL, return false\n\r"); + return MTK_WCN_BOOL_FALSE; +} + +MTK_WCN_BOOL stp_psm_is_quick_ps_support(VOID) +{ + return _stp_psm_is_quick_ps_support(); +} + +#if PSM_USE_COUNT_PACKAGE +int stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, int dir) +{ + + /* easy the variable maintain beween stp tx, rx thread. */ + /* so we create variable for tx, rx respectively. */ + + static int tx_cnt; + static int rx_cnt; + static int is_tx_first = 1; + static int is_rx_first = 1; + static unsigned long tx_end_time; + static unsigned long rx_end_time; + + /* */ + /* BT A2DP TX CNT = 220, RX CNT = 843 */ + /* BT FTP Transferring TX CNT = 574, RX CNT = 2233 (1228~1588) */ + /* BT FTP Receiving TX CNT = 204, RX CNT = 3301 (2072~2515) */ + /* BT OPP Tx TX_CNT= 330, RX CNT = 1300~1800 */ + /* BT OPP Rx TX_CNT= (109~157), RX CNT = 1681~2436 */ + if (dir == 0) { /* tx */ + + tx_cnt++; + + if (((long)jiffies - (long)tx_end_time >= 0) || (is_tx_first)) { + tx_end_time = jiffies + (3 * HZ); + STP_PSM_INFO_FUNC("tx cnt = %d in the previous 3 sec\n", tx_cnt); + /* if(tx_cnt > 400)//for high traffic , not to do sleep. */ + if (tx_cnt > 300) { + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm_start_monitor(stp_psm); + } else { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + tx_cnt = 0; + if (is_tx_first) + is_tx_first = 0; + } + } else { + rx_cnt++; + + if (((long)jiffies - (long)rx_end_time >= 0) || (is_rx_first)) { + rx_end_time = jiffies + (3 * HZ); + STP_PSM_INFO_FUNC("rx cnt = %d in the previous 3 sec\n", rx_cnt); + + /* if(rx_cnt > 2000)//for high traffic , not to do sleep. */ + if (rx_cnt > 1200) { /* for high traffic , not to do sleep. */ + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + stp_psm_start_monitor(stp_psm); + } else { + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_RX_HIGH_DENSITY, &stp_psm->flag); + _stp_psm_dbg_dmp_in(g_stp_psm_dbg, stp_psm->flag.data, __LINE__); + } + rx_cnt = 0; + if (is_rx_first) + is_rx_first = 0; + } + } + + return 0; +} + +#else +static struct timeval tv_now, tv_end; +static INT32 sample_start; +static INT32 tx_sum_len; +static INT32 rx_sum_len; + +INT32 stp_psm_disable_by_tx_rx_density(MTKSTP_PSM_T *stp_psm, INT32 dir, INT32 length) +{ + if (sample_start) { + if (dir) + rx_sum_len += length; + else + tx_sum_len += length; + + do_gettimeofday(&tv_now); + /* STP_PSM_INFO_FUNC("tv_now:%d.%d tv_end:%d.%d\n", + * tv_now.tv_sec,tv_now.tv_usec,tv_end.tv_sec,tv_end.tv_usec); + */ + if (((tv_now.tv_sec == tv_end.tv_sec) && (tv_now.tv_usec > tv_end.tv_usec)) || + (tv_now.tv_sec > tv_end.tv_sec)) { + STP_PSM_INFO_FUNC("STP speed rx:%d tx:%d\n", rx_sum_len, tx_sum_len); + if ((rx_sum_len + tx_sum_len) > RTX_SPEED_THRESHOLD) { + /* STP_PSM_INFO_FUNC("High speed,Disable monitor\n"); */ + osal_set_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP_1000; + stp_psm_start_monitor(stp_psm); + } else { + /* STP_PSM_INFO_FUNC("Low speed,Enable monitor\n"); */ + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; + osal_clear_bit(STP_PSM_WMT_EVENT_DISABLE_MONITOR_TX_HIGH_DENSITY, &stp_psm->flag); + } + sample_start = 0; + rx_sum_len = 0; + tx_sum_len = 0; + } + } else { + sample_start = 1; + do_gettimeofday(&tv_now); + tv_end = tv_now; + tv_end.tv_sec += SAMPLE_DURATION; + } + + return 0; +} +#endif + +/*external function for WMT module to do sleep/wakeup*/ +INT32 stp_psm_set_state(MTKSTP_PSM_T *stp_psm, MTKSTP_PSM_STATE_T state) +{ + return _stp_psm_set_state(stp_psm, state); +} + +INT32 stp_psm_thread_lock_aquire(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_aquire(stp_psm); +} + +INT32 stp_psm_thread_lock_release(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_thread_lock_release(stp_psm); +} + +INT32 stp_psm_do_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_do_wakeup(stp_psm); +} + +INT32 stp_psm_notify_stp(MTKSTP_PSM_T *stp_psm, const MTKSTP_PSM_ACTION_T action) +{ + + return _stp_psm_notify_stp(stp_psm, action); +} + +INT32 stp_psm_notify_wmt_wakeup(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_notify_wmt_wakeup_wq(stp_psm); +} + +int stp_psm_notify_wmt_sleep(MTKSTP_PSM_T *stp_psm) +{ + + return _stp_psm_notify_wmt_sleep_wq(stp_psm); +} + +INT32 stp_psm_start_monitor(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_start_monitor(stp_psm); +} + +INT32 stp_psm_is_to_block_traffic(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_is_to_block_traffic(stp_psm); +} + +INT32 stp_psm_is_disable(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_is_disable(stp_psm); +} + +INT32 stp_psm_has_pending_data(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_has_pending_data(stp_psm); +} + +INT32 stp_psm_release_data(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_release_data(stp_psm); +} + +INT32 stp_psm_hold_data(MTKSTP_PSM_T *stp_psm, const UINT8 *buffer, const UINT32 len, const UINT8 type) +{ + return _stp_psm_hold_data(stp_psm, buffer, len, type); +} + +INT32 stp_psm_disable(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_disable(stp_psm); +} + +INT32 stp_psm_enable(MTKSTP_PSM_T *stp_psm, INT32 idle_time_to_sleep) +{ + return _stp_psm_enable(stp_psm, idle_time_to_sleep); +} + +INT32 stp_psm_reset(MTKSTP_PSM_T *stp_psm) +{ + stp_psm_set_sleep_enable(stp_psm); + + return _stp_psm_reset(stp_psm); +} + +INT32 stp_psm_sleep_for_thermal(MTKSTP_PSM_T *stp_psm) +{ + return _stp_psm_notify_wmt_sleep_wq(stp_psm); +} + +INT32 stp_psm_set_sleep_enable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + stp_psm->sleep_en = 1; + STP_PSM_DBG_FUNC("\n"); + ret = 0; + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + +INT32 stp_psm_set_sleep_disable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + stp_psm->sleep_en = 0; + STP_PSM_DBG_FUNC("\n"); + ret = 0; + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + +/* stp_psm_check_sleep_enable - to check if sleep cmd is enabled or not + * @ stp_psm - pointer of psm + * + * return 1 if sleep is enabled; else return 0 if disabled; else error code + */ +INT32 stp_psm_check_sleep_enable(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = 0; + + if (stp_psm) { + ret = stp_psm->sleep_en; + STP_PSM_DBG_FUNC("%s\n", ret ? "enabled" : "disabled"); + } else { + STP_PSM_INFO_FUNC("Null pointer\n"); + ret = -1; + } + + return ret; +} + +static INT32 _stp_psm_dbg_dmp_in(STP_PSM_RECORD_T *stp_psm_dbg, UINT32 flag, UINT32 line_num) +{ + INT32 index = 0; + struct timeval now; + + if (stp_psm_dbg) { + osal_lock_unsleepable_lock(&stp_psm_dbg->lock); + do_gettimeofday(&now); + index = stp_psm_dbg->in - 1; + index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; + STP_PSM_DBG_FUNC("index(%d)\n", index); + stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag = stp_psm_dbg->queue[index].cur_flag; + stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag = flag; + stp_psm_dbg->queue[stp_psm_dbg->in].line_num = line_num; + stp_psm_dbg->queue[stp_psm_dbg->in].package_no = g_record_num++; + stp_psm_dbg->queue[stp_psm_dbg->in].sec = now.tv_sec; + stp_psm_dbg->queue[stp_psm_dbg->in].usec = now.tv_usec; + stp_psm_dbg->size++; + STP_PSM_DBG_FUNC("pre_Flag = %d, cur_flag = %d\n", stp_psm_dbg->queue[stp_psm_dbg->in].prev_flag, + stp_psm_dbg->queue[stp_psm_dbg->in].cur_flag); + stp_psm_dbg->size = (stp_psm_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : stp_psm_dbg->size; + stp_psm_dbg->in = (stp_psm_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (stp_psm_dbg->in + 1); + STP_PSM_DBG_FUNC("record size = %d, in = %d num = %d\n", stp_psm_dbg->size, stp_psm_dbg->in, line_num); + + osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); + } + return 0; +} + +static INT32 _stp_psm_dbg_out_printk(STP_PSM_RECORD_T *stp_psm_dbg) +{ + + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + + if (!stp_psm_dbg) { + STP_PSM_ERR_FUNC("NULL g_stp_psm_dbg reference\n"); + return -1; + } + osal_lock_unsleepable_lock(&stp_psm_dbg->lock); + + inIndex = stp_psm_dbg->in; + dumpSize = stp_psm_dbg->size; + if (STP_PSM_DBG_SIZE == dumpSize) + outIndex = inIndex; + else + outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; + + STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while (dumpSize > 0) { + + pr_debug("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d)\n", + stp_psm_dbg->queue[outIndex].sec, + stp_psm_dbg->queue[outIndex].usec, + stp_psm_dbg->queue[outIndex].package_no, + stp_psm_dbg->queue[outIndex].prev_flag, + stp_psm_dbg->queue[outIndex].cur_flag, stp_psm_dbg->queue[outIndex].line_num); + + outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); + dumpSize--; + + } + + osal_unlock_unsleepable_lock(&stp_psm_dbg->lock); + + return 0; +} + +static INT32 _stp_psm_opid_dbg_dmp_in(P_STP_PSM_OPID_RECORD p_opid_dbg, UINT32 opid, UINT32 line_num) +{ + INT32 index = 0; + struct timeval now; + + if (p_opid_dbg) { + osal_lock_unsleepable_lock(&p_opid_dbg->lock); + do_gettimeofday(&now); + index = p_opid_dbg->in - 1; + index = (index + STP_PSM_DBG_SIZE) % STP_PSM_DBG_SIZE; + STP_PSM_DBG_FUNC("index(%d)\n", index); + p_opid_dbg->queue[p_opid_dbg->in].prev_flag = p_opid_dbg->queue[index].cur_flag; + p_opid_dbg->queue[p_opid_dbg->in].cur_flag = opid; + p_opid_dbg->queue[p_opid_dbg->in].line_num = line_num; + p_opid_dbg->queue[p_opid_dbg->in].package_no = g_opid_record_num++; + p_opid_dbg->queue[p_opid_dbg->in].sec = now.tv_sec; + p_opid_dbg->queue[p_opid_dbg->in].usec = now.tv_usec; + p_opid_dbg->queue[p_opid_dbg->in].pid = current->pid; + p_opid_dbg->size++; + STP_PSM_DBG_FUNC("pre_opid = %d, cur_opid = %d\n", p_opid_dbg->queue[p_opid_dbg->in].prev_flag, + p_opid_dbg->queue[p_opid_dbg->in].cur_flag); + p_opid_dbg->size = (p_opid_dbg->size > STP_PSM_DBG_SIZE) ? STP_PSM_DBG_SIZE : p_opid_dbg->size; + p_opid_dbg->in = (p_opid_dbg->in >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (p_opid_dbg->in + 1); + STP_PSM_DBG_FUNC("opid record size = %d, in = %d num = %d\n", p_opid_dbg->size, p_opid_dbg->in, + line_num); + + osal_unlock_unsleepable_lock(&p_opid_dbg->lock); + } + return 0; + +} + +static INT32 _stp_psm_opid_dbg_out_printk(P_STP_PSM_OPID_RECORD p_opid_dbg) +{ + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + + if (!p_opid_dbg) { + STP_PSM_ERR_FUNC("NULL p_opid_dbg reference\n"); + return -1; + } + osal_lock_unsleepable_lock(&p_opid_dbg->lock); + + inIndex = p_opid_dbg->in; + dumpSize = p_opid_dbg->size; + if (STP_PSM_DBG_SIZE == dumpSize) + outIndex = inIndex; + else + outIndex = ((inIndex + STP_PSM_DBG_SIZE) - dumpSize) % STP_PSM_DBG_SIZE; + + STP_PSM_INFO_FUNC("loged record size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while (dumpSize > 0) { + + pr_debug("STP-PSM:%d.%ds, n(%d)pre_flag(%d)cur_flag(%d)line_no(%d) pid(%d)\n", + p_opid_dbg->queue[outIndex].sec, + p_opid_dbg->queue[outIndex].usec, + p_opid_dbg->queue[outIndex].package_no, + p_opid_dbg->queue[outIndex].prev_flag, + p_opid_dbg->queue[outIndex].cur_flag, + p_opid_dbg->queue[outIndex].line_num, p_opid_dbg->queue[outIndex].pid); + + outIndex = (outIndex >= (STP_PSM_DBG_SIZE - 1)) ? (0) : (outIndex + 1); + dumpSize--; + + } + + osal_unlock_unsleepable_lock(&p_opid_dbg->lock); + + return 0; + +} + +MTKSTP_PSM_T *stp_psm_init(void) +{ + INT32 err = 0; + INT32 i = 0; + INT32 ret = -1; + + STP_PSM_INFO_FUNC("psm init\n"); + + stp_psm->work_state = ACT; + stp_psm->wmt_notify = wmt_lib_ps_stp_cb; + stp_psm->is_wmt_quick_ps_support = wmt_lib_is_quick_ps_support; + stp_psm->idle_time_to_sleep = STP_PSM_IDLE_TIME_SLEEP; + stp_psm->flag.data = 0; + stp_psm->stp_tx_cb = NULL; + stp_psm_set_sleep_enable(stp_psm); + + ret = osal_fifo_init(&stp_psm->hold_fifo, NULL, STP_PSM_FIFO_SIZE); + if (ret < 0) { + STP_PSM_ERR_FUNC("FIFO INIT FAILS\n"); + goto ERR_EXIT4; + } + + osal_fifo_reset(&stp_psm->hold_fifo); + osal_sleepable_lock_init(&stp_psm->hold_fifo_spinlock_global); + osal_unsleepable_lock_init(&stp_psm->wq_spinlock); + osal_sleepable_lock_init(&stp_psm->stp_psm_lock); + +/* osal_unsleepable_lock_init(&stp_psm->flagSpinlock); */ + + osal_memcpy(stp_psm->wake_lock.name, "MT662x", 6); + osal_wake_lock_init(&stp_psm->wake_lock); + + osal_event_init(&stp_psm->STPd_event); + RB_INIT(&stp_psm->rFreeOpQ, STP_OP_BUF_SIZE); + RB_INIT(&stp_psm->rActiveOpQ, STP_OP_BUF_SIZE); + /* Put all to free Q */ + for (i = 0; i < STP_OP_BUF_SIZE; i++) { + osal_signal_init(&(stp_psm->arQue[i].signal)); + _stp_psm_put_op(stp_psm, &stp_psm->rFreeOpQ, &(stp_psm->arQue[i])); + } + /* stp_psm->current_active_op = NULL; */ + stp_psm->last_active_opId = STP_OPID_PSM_INALID; + /*Generate BTM thread, to servie STP-CORE and WMT-CORE for sleeping, waking up and host awake */ + stp_psm->PSMd.pThreadData = (VOID *) stp_psm; + stp_psm->PSMd.pThreadFunc = (VOID *) _stp_psm_proc; + osal_memcpy(stp_psm->PSMd.threadName, PSM_THREAD_NAME, osal_strlen(PSM_THREAD_NAME)); + + ret = osal_thread_create(&stp_psm->PSMd); + if (ret < 0) { + STP_PSM_ERR_FUNC("osal_thread_create fail...\n"); + goto ERR_EXIT5; + } + /* init_waitqueue_head(&stp_psm->wait_wmt_q); */ + stp_psm->wait_wmt_q.timeoutValue = STP_PSM_WAIT_EVENT_TIMEOUT; + osal_event_init(&stp_psm->wait_wmt_q); + + err = _stp_psm_init_monitor(stp_psm); + if (err) { + STP_PSM_ERR_FUNC("__stp_psm_init ERROR\n"); + goto ERR_EXIT6; + } + /* Start STPd thread */ + ret = osal_thread_run(&stp_psm->PSMd); + if (ret < 0) { + STP_PSM_ERR_FUNC("osal_thread_run FAILS\n"); + goto ERR_EXIT6; + } + /* psm disable in default */ + _stp_psm_disable(stp_psm); + + g_stp_psm_dbg = (STP_PSM_RECORD_T *) osal_malloc(osal_sizeof(STP_PSM_RECORD_T)); + if (!g_stp_psm_dbg) { + STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n"); + return NULL; + } + osal_memset(g_stp_psm_dbg, 0, osal_sizeof(STP_PSM_RECORD_T)); + osal_unsleepable_lock_init(&g_stp_psm_dbg->lock); + + g_stp_psm_opid_dbg = (STP_PSM_OPID_RECORD *) osal_malloc(osal_sizeof(STP_PSM_OPID_RECORD)); + if (!g_stp_psm_opid_dbg) { + STP_PSM_ERR_FUNC("stp psm dbg allocate memory fail!\n"); + return NULL; + } + osal_memset(g_stp_psm_opid_dbg, 0, osal_sizeof(STP_PSM_OPID_RECORD)); + osal_unsleepable_lock_init(&g_stp_psm_opid_dbg->lock); + + return stp_psm; + +ERR_EXIT6: + + ret = osal_thread_destroy(&stp_psm->PSMd); + if (ret < 0) { + STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); + goto ERR_EXIT5; + } +ERR_EXIT5: + osal_fifo_deinit(&stp_psm->hold_fifo); +ERR_EXIT4: + + return NULL; +} + +INT32 stp_psm_deinit(MTKSTP_PSM_T *stp_psm) +{ + INT32 ret = -1; + + STP_PSM_INFO_FUNC("psm deinit\n"); + + if (g_stp_psm_dbg) { + osal_unsleepable_lock_deinit(&g_stp_psm_dbg->lock); + osal_free(g_stp_psm_dbg); + g_stp_psm_dbg = NULL; + } + + if (!stp_psm) + return STP_PSM_OPERATION_FAIL; + + ret = osal_thread_destroy(&stp_psm->PSMd); + if (ret < 0) + STP_PSM_ERR_FUNC("osal_thread_destroy FAILS\n"); + + ret = _stp_psm_deinit_monitor(stp_psm); + if (ret < 0) + STP_PSM_ERR_FUNC("_stp_psm_deinit_monitor ERROR\n"); + + osal_wake_lock_deinit(&stp_psm->wake_lock); + osal_fifo_deinit(&stp_psm->hold_fifo); + osal_sleepable_lock_deinit(&stp_psm->hold_fifo_spinlock_global); + osal_unsleepable_lock_deinit(&stp_psm->wq_spinlock); + osal_sleepable_lock_deinit(&stp_psm->stp_psm_lock); +/* osal_unsleepable_lock_deinit(&stp_psm->flagSpinlock); */ + + return STP_PSM_OPERATION_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c new file mode 100644 index 0000000000000..a3c24ca144411 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/stp_core.c @@ -0,0 +1,3358 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "osal_typedef.h" +#include "stp_core.h" +#include "psm_core.h" +#include "btm_core.h" +#include "stp_dbg.h" +#include "stp_btif.h" + +#define PFX "[STP] " +#define STP_LOG_DBG 4 +#define STP_LOG_PKHEAD 3 +#define STP_LOG_INFO 2 +#define STP_LOG_WARN 1 +#define STP_LOG_ERR 0 + +#define STP_DEL_SIZE 2 /* STP delimiter length */ + +UINT32 gStpDbgLvl = STP_LOG_INFO; +unsigned int g_coredump_mode = 0; +#define REMOVE_USELESS_LOG 1 + +#define STP_POLL_CPUPCR_NUM 16 +#define STP_POLL_CPUPCR_DELAY 10 +#define STP_RETRY_OPTIMIZE 0 + +/* global variables */ +static const UINT8 stp_delimiter[STP_DEL_SIZE] = { 0x55, 0x55 }; + +static INT32 fgEnableNak; /* 0=enable NAK; 1=disable NAK */ +static INT32 fgEnableDelimiter; /* 0=disable Delimiter; 1=enable Delimiter */ +#if STP_RETRY_OPTIMIZE +static UINT32 g_retry_times; +#endif +/* common interface */ +static IF_TX sys_if_tx; +/* event/signal */ +static EVENT_SET sys_event_set; +static EVENT_TX_RESUME sys_event_tx_resume; +static FUNCTION_STATUS sys_check_function_status; +/* kernel lib */ +/* int g_block_tx = 0; */ +static mtkstp_context_struct stp_core_ctx = { 0 }; + +#define STP_PSM_CORE(x) ((x).psm) +#define STP_SET_PSM_CORE(x, v) ((x).psm = (v)) + +#define STP_BTM_CORE(x) ((x).btm) +#define STP_SET_BTM_CORE(x, v) ((x).btm = (v)) + +#define STP_IS_ENABLE(x) ((x).f_enable != 0) +#define STP_NOT_ENABLE(x) ((x).f_enable == 0) +#define STP_SET_ENABLE(x, v) ((x).f_enable = (v)) + +#define STP_IS_READY(x) ((x).f_ready != 0) +#define STP_NOT_READY(x) ((x).f_ready == 0) +#define STP_SET_READY(x, v) ((x).f_ready = (v)) + +#define STP_PENDING_TYPE(x) ((x).f_pending_type) +#define STP_SET_PENDING_TYPE(x, v) ((x).f_pending_type = (v)) + +#define STP_BLUE_ANGEL (0) +#define STP_BLUE_Z (1) +#define STP_BT_STK(x) ((x).f_bluez) +#define STP_BT_STK_IS_BLUEZ(x) ((x).f_bluez == (STP_BLUE_Z)) +#define STP_SET_BT_STK(x, v) ((x).f_bluez = (v)) + +#define STP_IS_ENABLE_DBG(x) ((x).f_dbg_en != 0) +#define STP_NOT_ENABLE_DBG(x) ((x).f_dbg_en == 0) +#define STP_SET_ENABLE_DBG(x, v) ((x).f_dbg_en = (v)) + +#define STP_IS_ENABLE_RST(x) ((x).f_autorst_en != 0) +#define STP_NOT_ENABLE_RST(x) ((x).f_autorst_en == 0) +#define STP_SET_ENABLE_RST(x, v) ((x).f_autorst_en = (v)) + +#define STP_SUPPORT_PROTOCOL(x) ((x).f_mode) +#define STP_SET_SUPPORT_PROTOCOL(x, v) ((x).f_mode = (v)) + +#define STP_FW_COREDUMP_FLAG(x) ((x).f_coredump) +#define STP_SET_FW_COREDUMP_FLAG(x, v) ((x).f_coredump = (v)) +#define STP_ENABLE_FW_COREDUMP(x, v) ((x).en_coredump = (v)) +#define STP_ENABLE_FW_COREDUMP_FLAG(x) ((x).en_coredump) + +#define STP_WMT_LAST_CLOSE(x) ((x).f_wmt_last_close) +#define STP_SET_WMT_LAST_CLOSE(x, v) ((x).f_wmt_last_close = (v)) + +#define STP_EVT_ERR_ASSERT(x) ((x).f_evt_err_assert) +#define STP_SET_EVT_ERR_ASSERT(x, v) ((x).f_evt_err_assert = (v)) + +/*[PatchNeed]Need to calculate the timeout value*/ +static UINT32 mtkstp_tx_timeout = MTKSTP_TX_TIMEOUT; +static mtkstp_parser_state prev_state = -1; + +#define CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +#ifdef CONFIG_DEBUG_STP_TRAFFIC_SUPPORT +static MTKSTP_DBG_T *g_mtkstp_dbg; +#endif +static VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len); +static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc); +static VOID stp_update_tx_queue(UINT32 txseq); +static VOID stp_rest_ctx_state(VOID); +static VOID stp_change_rx_state(mtkstp_parser_state next); +static void stp_tx_timeout_handler(/*unsigned long data*/ struct timer_list *t); +static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len); +static VOID stp_dump_tx_queue(UINT32 txseq); +static INT32 stp_is_apply_powersaving(VOID); +/*static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type);*/ +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length); +static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length); +static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type); +static VOID stp_send_tx_queue(UINT32 txseq); +static VOID stp_send_ack(UINT8 txAck, UINT8 nak); +static INT32 stp_process_rxack(VOID); +static VOID stp_process_packet(VOID); + +/*private functions*/ + +static INT32 stp_ctx_lock_init(mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_unsleepable_lock_init(&((pctx)->stp_mutex)); +#else + osal_sleepable_lock_init(&((pctx)->stp_mutex)); + return 0; +#endif +} + +static INT32 stp_ctx_lock_deinit(mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_unsleepable_lock_deinit(&((pctx)->stp_mutex)); +#else + return osal_sleepable_lock_deinit(&((pctx)->stp_mutex)); +#endif +} + +static INT32 stp_ctx_lock(mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_lock_unsleepable_lock(&((pctx)->stp_mutex)); +#else + return osal_lock_sleepable_lock(&((pctx)->stp_mutex)); +#endif +} + +static INT32 stp_ctx_unlock(mtkstp_context_struct *pctx) +{ +#if CFG_STP_CORE_CTX_SPIN_LOCK + return osal_unlock_unsleepable_lock(&((pctx)->stp_mutex)); +#else + return osal_unlock_sleepable_lock(&((pctx)->stp_mutex)); +#endif +} + +MTK_WCN_BOOL mtk_wcn_stp_dbg_level(UINT32 dbglevel) +{ + if (dbglevel <= 4) { + gStpDbgLvl = dbglevel; + STP_INFO_FUNC("gStpDbgLvl = %d\n", gStpDbgLvl); + return MTK_WCN_BOOL_TRUE; + } + STP_INFO_FUNC("invalid stp debug level. gStpDbgLvl = %d\n", gStpDbgLvl); + + return MTK_WCN_BOOL_FALSE; +} + +#if !(REMOVE_USELESS_LOG) +static UINT8 *stp_type_to_dbg_string(UINT32 type) +{ + UINT8 *type_name = NULL; + + if (type == BT_TASK_INDX) + type_name = "< BT>"; + else if (type == GPS_TASK_INDX) + type_name = ""; + else if (type == WMT_TASK_INDX) + type_name = ""; + else if (type == FM_TASK_INDX) + type_name = "< FM>"; + else if (type == ANT_TASK_INDX) + type_name = ""; + + return type_name; +} +#endif +#if 0 +/***************************************************************************** +* FUNCTION +* crc16 +* DESCRIPTION +* Compute the CRC-16 for the data buffer +* PARAMETERS +* crc [IN] previous CRC value +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* the updated CRC value +*****************************************************************************/ +static UINT16 crc16(const UINT8 *buffer, const UINT32 length) +{ + UINT32 crc, i; + + /* FIXME: Add STP checksum feature */ + crc = 0; + for (i = 0; i < length; i++, buffer++) + crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; + + return crc; +} + +#endif + +VOID stp_dbg_pkt_log(INT32 type, INT32 txAck, INT32 seq, INT32 crc, INT32 dir, const UINT8 *pBuf, INT32 len) +{ + +#ifndef CONFIG_LOG_STP_INTERNAL + return; +#endif + + if (STP_IS_ENABLE_DBG(stp_core_ctx)) { + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_PKT, type, /* type */ + txAck, /* ack */ + seq, /* seq */ + crc, /* crc */ + dir, /* dir */ + len, /* len */ + pBuf); /* body */ + } else { + STP_DBG_FUNC("stp_dbg not enabled"); + } +} + +/***************************************************************************** +* FUNCTION +* stp_check_crc +* DESCRIPTION +* check the check sum of packet payload +* PARAMETERS +* pdata [IN] the data want to check +* length [IN] the length of pdata +* crc [IN] the crc of pdata +* RETURNS +* KAL_TRUE crc is ok +* KAL_FALSE crc is wrong +*****************************************************************************/ +static MTK_WCN_BOOL stp_check_crc(UINT8 *buffer, UINT32 length, UINT16 crc) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + UINT16 checksum; + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + + /* FIXME: Add STP feature: check or skip crc */ + + checksum = osal_crc16(buffer, length); + if (checksum == crc) + return MTK_WCN_BOOL_TRUE; + + STP_ERR_FUNC("CRC fail, length = %d, rx = %x, calc = %x \r\n", length, crc, checksum); + return MTK_WCN_BOOL_FALSE; + +} + +/***************************************************************************** +* FUNCTION +* stp_update_tx_queue +* DESCRIPTION +* update packet's ACK field +* PARAMETERS +* txseq [IN] index of the tx packet which we want to update +* RETURNS +* void +*****************************************************************************/ +static void stp_update_tx_queue(UINT32 txseq) +{ + INT32 tx_read, i; + UINT8 checksum = 0; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + stp_core_ctx.tx_buf[tx_read] &= 0xf8; + stp_core_ctx.tx_buf[tx_read] |= stp_core_ctx.sequence.txack; + + for (i = 0; i < 3; i++) { + checksum += stp_core_ctx.tx_buf[tx_read]; + tx_read++; + if (tx_read >= MTKSTP_BUFFER_SIZE) + tx_read -= MTKSTP_BUFFER_SIZE; + + } + + stp_core_ctx.tx_buf[tx_read] = checksum; + +} + +/***************************************************************************** +* FUNCTION +* stp_rest_ctx_state +* DESCRIPTION +* Reset stp context state variables only. Mutex and timer resources are not touched. +* +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_rest_ctx_state(VOID) +{ + INT32 i; + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + stp_core_ctx.rx_counter = 0; + + /*reset rx buffer pointer */ + for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) { + stp_core_ctx.ring[i].read_p = 0; + stp_core_ctx.ring[i].write_p = 0; + } + + /*reset tx buffer pointer */ + stp_core_ctx.tx_write = 0; + stp_core_ctx.tx_read = 0; + + /*reset STP protocol context */ + stp_core_ctx.parser.state = MTKSTP_SYNC; + stp_core_ctx.sequence.txseq = 0; + stp_core_ctx.sequence.txack = 7; + stp_core_ctx.sequence.rxack = 7; + stp_core_ctx.sequence.winspace = MTKSTP_WINSIZE; + stp_core_ctx.sequence.expected_rxseq = 0; + stp_core_ctx.sequence.retry_times = 0; + stp_core_ctx.inband_rst_set = 0; + + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); +} + +/***************************************************************************** +* FUNCTION +* stp_change_rx_state +* DESCRIPTION +* change the rx fsm of STP to "next" +* PARAMETERS +* next [IN] the next state of rx fsm +* RETURNS +* void +*****************************************************************************/ +static VOID stp_change_rx_state(mtkstp_parser_state next) +{ + prev_state = stp_core_ctx.parser.state; + stp_core_ctx.parser.state = next; + +} + +/* static void stp_tx_timeout_handler(void){ */ +static void stp_tx_timeout_handler(/*unsigned long data*/struct timer_list *t) +{ + STP_WARN_FUNC("call retry btm retry wq ...\n"); + /*shorten the softirq lattency */ + stp_btm_notify_stp_retry_wq(STP_BTM_CORE(stp_core_ctx)); + STP_WARN_FUNC("call retry btm retry wq ...#\n"); +} + +VOID stp_do_tx_timeout(VOID) +{ + UINT32 seq; + UINT32 ret; + INT32 iRet; + ENUM_STP_FW_ISSUE_TYPE issue_type; + UINT8 resync[4]; + + STP_WARN_FUNC("==============================================================================\n"); + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + +#if STP_RETRY_OPTIMIZE + if ((g_retry_times != 0) && (stp_core_ctx.sequence.retry_times == 0)) { + STP_INFO_FUNC("STP TX timeout has been recoveryed by resend,record_retry_time(%d)\n", g_retry_times); + g_retry_times = 0; + stp_ctx_unlock(&stp_core_ctx); + return; + } +#endif + if (stp_core_ctx.sequence.retry_times > (MTKSTP_RETRY_LIMIT)) { + STP_INFO_FUNC("STP retry times(%d) have reached retry limit,stop it\n", + stp_core_ctx.sequence.retry_times); + stp_ctx_unlock(&stp_core_ctx); + return; + } +#if STP_RETRY_OPTIMIZE + else + STP_DBG_FUNC("current TX timeout package has not received ACK yet,retry_times(%d)\n", + g_retry_times); +#endif + /*polling cpupcr when no ack occurs at first retry */ + stp_notify_btm_poll_cpupcr(STP_BTM_CORE(stp_core_ctx), STP_POLL_CPUPCR_NUM, STP_POLL_CPUPCR_DELAY); + + seq = stp_core_ctx.sequence.rxack; + INDEX_INC(seq); + + if (seq != stp_core_ctx.sequence.txseq) { + osal_memset(&resync[0], 127, 4); + (*sys_if_tx) (&resync[0], 4, &ret); + if (ret != 4) { + STP_ERR_FUNC("mtkstp_tx_timeout_handler: send resync fail\n"); + osal_assert(0); + } + + do { + STP_WARN_FUNC("[stp.ctx]*rxack (=last rx ack) = %d\n\r", stp_core_ctx.sequence.rxack); + STP_WARN_FUNC("[stp.ctx]txack (=last rx seq)= %d\n\r", stp_core_ctx.sequence.txack); + STP_WARN_FUNC("[stp.ctx]*txseq (=next tx seq)= %d\n\r", stp_core_ctx.sequence.txseq); + STP_WARN_FUNC("Resend STP packet from %d -> %d\n\r", seq, + (stp_core_ctx.sequence.txseq <= 0) ? (7) : (stp_core_ctx.sequence.txseq - 1)); + stp_dump_tx_queue(seq); + + stp_send_tx_queue(seq); + INDEX_INC(seq); + } while (seq != stp_core_ctx.sequence.txseq); + + } + + osal_timer_stop(&stp_core_ctx.tx_timer); + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + + if (stp_core_ctx.sequence.winspace == MTKSTP_WINSIZE) { + osal_timer_stop(&stp_core_ctx.tx_timer); + STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); + } else { + stp_core_ctx.sequence.retry_times++; + STP_ERR_FUNC("mtkstp_tx_timeout_handler, retry = %d\n", stp_core_ctx.sequence.retry_times); +#if STP_RETRY_OPTIMIZE + g_retry_times = stp_core_ctx.sequence.retry_times; +#endif + /*If retry too much, try to recover STP by return back to initializatin state */ + /*And not to retry again */ + if (stp_core_ctx.sequence.retry_times > MTKSTP_RETRY_LIMIT) { +#if STP_RETRY_OPTIMIZE + g_retry_times = 0; +#endif + osal_timer_stop(&stp_core_ctx.tx_timer); + stp_ctx_unlock(&stp_core_ctx); + + STP_ERR_FUNC("mtkstp_tx_timeout_handler: wmt_stop_timer\n"); + + STP_ERR_FUNC("TX retry limit = %d\n", MTKSTP_RETRY_LIMIT); + osal_assert(0); + mtk_wcn_stp_dbg_dump_package(); + + /*Whole Chip Reset Procedure Invoke */ + /*if(STP_NOT_ENABLE_DBG(stp_core_ctx)) */ + + if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); + stp_dbg_set_host_assert_info(4, 36, 1); + STP_INFO_FUNC("**STP NoAck trigger firmware assert**\n"); + iRet = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); + + if (iRet) { + STP_ERR_FUNC("host tigger fw assert fail(%d), do noack handle flow\n", iRet); + mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); + issue_type = STP_FW_NOACK_ISSUE; + iRet = stp_dbg_set_fw_info("STP NoAck", osal_strlen("STP NoAck"), issue_type); + + osal_dbg_assert_aee("[SOC_CONNSYS]NoAck", + "**[WCN_ISSUE_INFO]STP Tx Timeout**\n F/W has NO any RESPONSE. Please check F/W status first\n"); + if (STP_IS_ENABLE_RST(stp_core_ctx)) { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } else { + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + } else { + STP_INFO_FUNC("do trigger assert & chip reset in wmt\n"); + } + return; + } + } + + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + STP_WARN_FUNC("==============================================================================#\n"); +} + +static VOID stp_dump_data(const UINT8 *buf, const UINT8 *title, const UINT32 len) +{ + osal_buffer_dump(buf, title, len, 32); +} + +/***************************************************************************** + * FUNCTION + * stp_tx_timeout_handler + * DESCRIPTION + * tx timeout handler, send resync & retransmitt + * PARAMETERS + * void + * RETURNS + * void + *****************************************************************************/ +static VOID stp_dump_tx_queue(UINT32 txseq) +{ + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + STP_ERR_FUNC("tx_seq=%d ..", txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) { + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q", (tx_length >= 8) ? (8) : (tx_length)); + } else { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + stp_dump_data(&stp_core_ctx.tx_buf[tx_read], "tx_q_0", (last_len >= 8) ? (8) : (last_len)); + stp_dump_data(&stp_core_ctx.tx_buf[0], "tx_q_0", + ((tx_length - last_len) ? (8) : (tx_length - last_len))); + } +} + +/***************************************************************************** +* FUNCTION +* stp_is_apply_powersaving +* DESCRIPTION +* Check if STP support power saving mode. +* PARAMETERS +* +* RETURNS +* True: support power saving False: not support power saving +*****************************************************************************/ +static INT32 stp_is_apply_powersaving(VOID) +{ + + if (STP_IS_READY(stp_core_ctx) && !stp_psm_is_disable(STP_PSM_CORE(stp_core_ctx))) { + /* osal_dbg_print("apply power saving\n"); */ + return MTK_WCN_BOOL_TRUE; + } + if (mtk_wcn_stp_is_sdio_mode()) + return MTK_WCN_BOOL_FALSE; + + STP_DBG_FUNC("not apply power saving\n"); + return MTK_WCN_BOOL_FALSE; +} +#if 0 +/***************************************************************************** +* FUNCTION +* stp_is_privileges_cmd +* DESCRIPTION +* Check if the data is privilege command +* PARAMETERS +* +* RETURNS +* True/False +*****************************************************************************/ +static INT32 stp_is_privileges_cmd(const UINT8 *buffer, const UINT32 length, const UINT8 type) +{ + typedef struct privileges_cmd { + UINT32 length; + UINT8 type; + UINT8 buf[7]; /* MAX length of target command is only 5 currently */ + } p_cmd_t; + + p_cmd_t p_cmd_table[] = { + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x01} }, /* sleep command */ + {0x05, WMT_TASK_INDX, {0x01, 0x03, 0x01, 0x00, 0x02} }, /* host_awake command */ + }; + + UINT32 i; + UINT32 size = sizeof(p_cmd_table) / sizeof(p_cmd_table[0]); + + for (i = 0; i < size; i++) { + if (type != p_cmd_table[i].type) + continue; + + if (length != p_cmd_table[i].length) + continue; + + if (osal_memcmp(p_cmd_table[i].buf, buffer, length)) + continue; + + /* matched entry is found */ + STP_DBG_FUNC("It's p_cmd_t\n"); + return MTK_WCN_BOOL_TRUE; + } + + return MTK_WCN_BOOL_FALSE; +} +#endif +/***************************************************************************** +* FUNCTION +* tx_queue_room_available +* DESCRIPTION +* check room if available, +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +static MTK_WCN_BOOL stp_is_tx_res_available(UINT32 length) +{ + UINT32 roomLeft; + + /* + Get available space of TX Queue + */ + if (stp_core_ctx.tx_read <= stp_core_ctx.tx_write) + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write + stp_core_ctx.tx_read - 1; + else + roomLeft = stp_core_ctx.tx_read - stp_core_ctx.tx_write - 1; + + if (roomLeft < length) { + STP_ERR_FUNC("%s: tx queue room shortage\n", __func__); + return MTK_WCN_BOOL_FALSE; + } else + return MTK_WCN_BOOL_TRUE; +} + +/***************************************************************************** +* FUNCTION +* stp_add_to_tx_queue +* DESCRIPTION +* put data to tx queue +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +static VOID stp_add_to_tx_queue(const UINT8 *buffer, UINT32 length) +{ + UINT32 last_len; + + /* Get available space of TX Queue */ + if (length + stp_core_ctx.tx_write < MTKSTP_BUFFER_SIZE) { + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, length); + stp_core_ctx.tx_write += length; + } else { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.tx_write; + osal_memcpy(stp_core_ctx.tx_buf + stp_core_ctx.tx_write, buffer, last_len); + osal_memcpy(stp_core_ctx.tx_buf, buffer + last_len, length - last_len); + + stp_core_ctx.tx_write = length - last_len; + } + +} + +/***************************************************************************** +* FUNCTION +* stp_add_to_rx_queue +* DESCRIPTION +* put data to corresponding task's rx queue and notify corresponding task +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] corresponding task index +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 stp_add_to_rx_queue(UINT8 *buffer, UINT32 length, UINT8 type) +{ + UINT32 roomLeft, last_len; + + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if (stp_core_ctx.ring[type].read_p <= stp_core_ctx.ring[type].write_p) + roomLeft = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p + stp_core_ctx.ring[type].read_p - 1; + else + roomLeft = stp_core_ctx.ring[type].read_p - stp_core_ctx.ring[type].write_p - 1; + + if (roomLeft < length) { + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + STP_ERR_FUNC("Queue is full !!!, type = %d\n", type); + osal_assert(0); + return -1; + } + + if (length + stp_core_ctx.ring[type].write_p < MTKSTP_BUFFER_SIZE) { + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, length); + stp_core_ctx.ring[type].write_p += length; + } else { + last_len = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].write_p; + osal_memcpy(stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].write_p, buffer, last_len); + osal_memcpy(stp_core_ctx.ring[type].buffer, buffer + last_len, length - last_len); + stp_core_ctx.ring[type].write_p = length - last_len; + } + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* stp_send_tx_queue +* DESCRIPTION +* send data in tx buffer to common interface +* PARAMETERS +* txseq [IN] sequence number of outgoing packet in tx buffer +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_tx_queue(UINT32 txseq) +{ + UINT32 ret; + INT32 tx_read, tx_length, last_len; + + tx_read = stp_core_ctx.tx_start_addr[txseq]; + tx_length = stp_core_ctx.tx_length[txseq]; + + stp_update_tx_queue(txseq); + + if (tx_read + tx_length < MTKSTP_BUFFER_SIZE) { + + (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], tx_length, &ret); + + if (ret != tx_length) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length, ret); + osal_assert(0); + } + } else { + last_len = MTKSTP_BUFFER_SIZE - tx_read; + (*sys_if_tx) (&stp_core_ctx.tx_buf[tx_read], last_len, &ret); + + if (ret != last_len) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", last_len, ret); + osal_assert(0); + } + + (*sys_if_tx) (&stp_core_ctx.tx_buf[0], tx_length - last_len, &ret); + + if (ret != tx_length - last_len) { + STP_ERR_FUNC("stp_send_tx_queue, %d/%d\n", tx_length - last_len, ret); + osal_assert(0); + } + } + +} + +/***************************************************************************** +* FUNCTION +* stp_send_ack +* DESCRIPTION +* send ack packet to the peer +* PARAMETERS +* txAck [IN] Ack number +* nak [IN] 0 = ack; !0 = NAK +* RETURNS +* void +*****************************************************************************/ +static VOID stp_send_ack(UINT8 txAck, UINT8 nak) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE]; + UINT32 ret; + INT32 iStatus; + + mtkstp_header[0] = 0x80 + (0 << 3) + txAck; /* stp_core_ctx.sequence.txack; */ + + if (fgEnableNak == 0) + mtkstp_header[1] = 0x00; /* disable NAK */ + else + mtkstp_header[1] = ((nak == 0) ? 0x00 : 0x80); + + mtkstp_header[2] = 0; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + + stp_dbg_pkt_log(STP_TASK_INDX, txAck, 0, 0, PKT_DIR_TX, NULL, 0); + + if (fgEnableDelimiter == 1) { + iStatus = (*sys_if_tx) ((PUINT8) &stp_delimiter[0], STP_DEL_SIZE, &ret); + STP_DUMP_PACKET_HEAD((PUINT8) &stp_delimiter[0], "tx del", STP_DEL_SIZE); + if (ret != STP_DEL_SIZE) { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", STP_DEL_SIZE, ret, iStatus); + osal_assert(0); + } + } + + iStatus = (*sys_if_tx) (&mtkstp_header[0], MTKSTP_HEADER_SIZE, &ret); + + if (ret != MTKSTP_HEADER_SIZE) { + STP_ERR_FUNC("stp_send_ack, %d/%d status %d\n", MTKSTP_HEADER_SIZE, ret, iStatus); + osal_assert(0); + } + +} + +INT32 stp_send_data_no_ps(UINT8 *buffer, UINT32 length, UINT8 type) +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + UINT8 *p_tx_buf = NULL; + UINT16 crc; + INT32 ret = 0; + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + + /*Only WMT can set raw data */ + if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) { + /* no op */ + /* NULL; */ + } else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) { + /* ret = mtk_wcn_stp_send_data_raw(buffer, length, type); */ + /* NULL; */ + } + /* STP over SDIO */ + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { + osal_printtimeofday("[ STP][SDIO][ B][W]"); + + mtkstp_header[0] = 0x80; + mtkstp_header[1] = (type << 4) + (((length) >> 8) & 0x0f); + mtkstp_header[2] = (length) & 0xff; + mtkstp_header[3] = 0x00; + + p_tx_buf = &stp_core_ctx.tx_buf[0]; + osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); + p_tx_buf += MTKSTP_HEADER_SIZE; + + osal_memcpy(p_tx_buf, buffer, length); + p_tx_buf += length; + + temp[0] = 0x00; + temp[1] = 0x00; + osal_memcpy(p_tx_buf, temp, 2); + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, 0, PKT_DIR_TX, buffer, length); + (*sys_if_tx) (&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE + length + 2), &ret); + if ((MTKSTP_HEADER_SIZE + length + 2) != ret) { + STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); + osal_assert(0); + ret = 0; + } else { + ret = (INT32) length; + } + + osal_printtimeofday("[ STP][SDIO][ E][W]"); + } + /* STP over BTIF OR UART */ + else if ((mtk_wcn_stp_is_btif_fullset_mode()) && STP_IS_ENABLE(stp_core_ctx)) { + + if ((stp_core_ctx.sequence.winspace > 0) && + (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) { + mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; + mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); + mtkstp_header[2] = length & 0xff; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + + stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; + + if (fgEnableDelimiter == 1) { + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; + stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); + } + + stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); + + /*Make Payload */ + stp_add_to_tx_queue(buffer, length); + + /*Make CRC */ + crc = osal_crc16(buffer, length); + temp[0] = crc & 0xff; + temp[1] = (crc & 0xff00) >> 8; + stp_add_to_tx_queue(temp, 2); + + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, crc, PKT_DIR_TX, buffer, length); + + /*Kick to UART */ + stp_send_tx_queue(stp_core_ctx.sequence.txseq); + INDEX_INC(stp_core_ctx.sequence.txseq); + stp_core_ctx.sequence.winspace--; + + /*Setup the Retry Timer */ + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + else + STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); + + ret = (INT32) length; + } else { + /* No winspace to send. Let caller retry */ + STP_ERR_FUNC("%s: There is no winspace/txqueue to send !!!\n", __func__); + ret = 0; + } + } + + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + + return ret; +} + +/***************************************************************************** +* FUNCTION +* stp_process_rxack +* DESCRIPTION +* process ack packet +* PARAMETERS +* void +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +static INT32 stp_process_rxack(VOID) +{ + INT32 j, k; + UINT8 rxack; + INT32 fgResult = (-1); + + if (stp_core_ctx.sequence.rxack != stp_core_ctx.parser.ack) { + j = k = 0; + rxack = stp_core_ctx.sequence.rxack; + INDEX_INC(rxack); + while (rxack != stp_core_ctx.sequence.txseq) { + j++; + if (rxack == stp_core_ctx.parser.ack) { + k = 1; + break; + } + INDEX_INC(rxack); + } + if (k == 1) { + stp_core_ctx.sequence.rxack = stp_core_ctx.parser.ack; + stp_core_ctx.tx_read = stp_core_ctx.tx_start_addr[rxack] + stp_core_ctx.tx_length[rxack]; + if (stp_core_ctx.tx_read >= MTKSTP_BUFFER_SIZE) + stp_core_ctx.tx_read -= MTKSTP_BUFFER_SIZE; + + stp_core_ctx.sequence.winspace += j; + stp_core_ctx.sequence.retry_times = 0; + + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + + fgResult = 0; + } + } + + return fgResult; +} + +/***************************************************************************** +* FUNCTION +* stp_process_packet +* DESCRIPTION +* process STP packet +* PARAMETERS +* void +* RETURNS +* void +*****************************************************************************/ +static VOID stp_process_packet(VOID) +{ + INT32 fgTriggerResume = (-1); + UINT8 txAck = 0; + static INT32 fgRxOk; + MTK_WCN_BOOL b; + MTK_WCN_BOOL is_function_active = 0; + static INT32 stp_process_packet_fail_count; + INT32 iRet = -1; + + stp_dbg_pkt_log(stp_core_ctx.parser.type, + stp_core_ctx.parser.ack, + stp_core_ctx.parser.seq, + stp_core_ctx.parser.crc, PKT_DIR_RX, stp_core_ctx.rx_buf, stp_core_ctx.parser.length); + /*Optimization */ + /*If bluez, direct send packet to hci_core not through RX buffer! */ + if ((stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) && + (stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) { + /*Indicate packet to hci_stp */ + STP_DBG_FUNC("Send Packet to BT_SUBFUCTION, len = %d\n", stp_core_ctx.rx_counter); + + b = mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if (b) + STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + /*Process rx ack */ + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + txAck = stp_core_ctx.sequence.txack; + + /*Send ack back */ + stp_send_ack(txAck, 0); + + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + fgRxOk = 0; + } + /* sequence matches expected, enqueue packet */ + else if (stp_core_ctx.sequence.expected_rxseq == stp_core_ctx.parser.seq) { + is_function_active = + ((*sys_check_function_status) (stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) == + STATUS_FUNCTION_ACTIVE); + /*If type is valid and function works, then try to enqueue */ + if ((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) && (is_function_active == MTK_WCN_BOOL_TRUE)) { + if (stp_core_ctx.parser.type == BT_TASK_INDX) { + static const UINT8 rst_buf[7] = { 0x04, 0x0e, 0x04, 0x01, 0x3, 0xc, 0x00 }; + + if (!osal_strncmp(stp_core_ctx.rx_buf, rst_buf, 7)) + osal_printtimeofday("############ BT Rest end <--"); + } + + stp_ctx_lock(&stp_core_ctx); + + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + + /*Send tx ack */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); +#if CFG_WMT_LTE_COEX_HANDLING + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && + (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { + fgRxOk = + stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, COEX_TASK_INDX); + } else { + fgRxOk = + stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + } +#else + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && + (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { + STP_WARN_FUNC("BT/WIFI & LTE coex in non-LTE projects,drop it...\n"); + } else { + fgRxOk = + stp_add_to_rx_queue(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + } +#endif + } else { + if (is_function_active == MTK_WCN_BOOL_FALSE) { + STP_ERR_FUNC("function type = %d is inactive, so no en-queue to rx\n", + stp_core_ctx.parser.type); + fgRxOk = 0; /*drop packet */ + } else { + STP_ERR_FUNC("mtkstp_process_packet: type = %x, the type is invalid\n", + stp_core_ctx.parser.type); + fgRxOk = 0; /*drop packet */ + } + stp_ctx_lock(&stp_core_ctx); + + fgTriggerResume = stp_process_rxack(); + stp_core_ctx.sequence.txack = stp_core_ctx.parser.seq; + INDEX_INC(stp_core_ctx.sequence.expected_rxseq); + + /*Send tx ack */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 0); + + stp_ctx_unlock(&stp_core_ctx); + } + + /* enqueue successfully */ + if (fgRxOk == 0) { + stp_process_packet_fail_count = 0; + /*notify corresponding subfunction of incoming data */ +#if CFG_WMT_LTE_COEX_HANDLING + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && + (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { +#if 1 + STP_DBG_FUNC + ("WMT/LTE package:[0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x][0x%2x]\n", + stp_core_ctx.rx_buf[0], stp_core_ctx.rx_buf[1], stp_core_ctx.rx_buf[2], + stp_core_ctx.rx_buf[3], stp_core_ctx.rx_buf[4], stp_core_ctx.rx_buf[5], + stp_core_ctx.rx_buf[6], stp_core_ctx.rx_buf[7]); +#endif + stp_notify_btm_handle_wmt_lte_coex(STP_BTM_CORE(stp_core_ctx)); + } else { + (*sys_event_set) (stp_core_ctx.parser.type); + } +#else + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) && + (stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG)) { + STP_WARN_FUNC("omit BT/WIFI & LTE coex msg handling in non-LTE projects\n"); + } else { + (*sys_event_set) (stp_core_ctx.parser.type); + } +#endif + } else { + stp_process_packet_fail_count++; + /*Queue is full */ + if (stp_core_ctx.parser.type == GPS_TASK_INDX) { + /*Clear Rx Queue if GPS */ + mtk_wcn_stp_flush_rx_queue(GPS_TASK_INDX); + } else { + /*notify corresponding subfunction of incoming data */ + (*sys_event_set) (stp_core_ctx.parser.type); + } + /*enqueue fail, don't send ack and wait for peer retry */ + STP_ERR_FUNC("Enqueue to Rx queue fail, maybe function %d queue is full\n", + stp_core_ctx.parser.type); + } + } + /*sequence not match && previous packet enqueue successfully, send the previous ACK */ + else if (fgRxOk == 0) { + STP_ERR_FUNC("mtkstp_process_packet: expected_rxseq = %d, parser.seq = %d\n", + stp_core_ctx.sequence.expected_rxseq, stp_core_ctx.parser.seq); + stp_process_packet_fail_count++; + + stp_ctx_lock(&stp_core_ctx); + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + txAck = stp_core_ctx.sequence.txack; + stp_send_ack(txAck, 1); + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + STP_ERR_FUNC + ("sequence not match && previous packet enqueue successfully, send the previous ACK (ack no =%d)\n", + txAck); + } + /*sequence not match && previous packet enqueue failed, do nothing, make the other side timeout */ + else { + stp_process_packet_fail_count++; + STP_ERR_FUNC + ("sequence not match && previous packet enqueue failed, do nothing, make the other side timeout\n"); + } + + if (fgTriggerResume == 0) { + /*[PatchNeed]Just Notificaiton, not blocking call */ + /* notify adaptation layer for possible tx resume mechanism */ + (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); + } + + if (stp_process_packet_fail_count > MTKSTP_RETRY_LIMIT) { + stp_process_packet_fail_count = 0; + STP_ERR_FUNC("The process packet fail count > 10 lastly\n\r, whole chip reset\n\r"); + mtk_wcn_stp_dbg_dump_package(); + /*Whole Chip Reset Procedure Invoke */ + /*if(STP_NOT_ENABLE_DBG(stp_core_ctx)) */ + if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); + stp_dbg_set_host_assert_info(4, 37, 1); + STP_INFO_FUNC("**Ack Miss trigger firmware assert**\n"); + iRet = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); + if (iRet) { + mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); + /* (*sys_dbg_assert_aee)("[MT662x]Ack Miss", "**STP Ack Miss**\n Ack Miss.\n"); */ + osal_dbg_assert_aee("[SOC_CONSYS]Ack Miss", + "**[WCN_ISSUE_INFO]STP Ack Miss**\n Ack Miss.\n"); + + if (STP_IS_ENABLE_RST(stp_core_ctx)) { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } else { + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + } + } + } + +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_init +* DESCRIPTION +* init STP kernel +* PARAMETERS +* cb_func [IN] function pointers of system APIs +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +INT32 mtk_wcn_stp_init(const mtkstp_callback * const cb_func) +{ + INT32 ret = 0; + INT32 i = 0; + + /* Function pointer to point to the currently used transmission interface + */ + sys_if_tx = cb_func->cb_if_tx; + + /* Used to inform the function driver has received the corresponding type of information */ + sys_event_set = cb_func->cb_event_set; + + /* Used to inform the function driver can continue to send information and + STP has resources to deal with + */ + sys_event_tx_resume = cb_func->cb_event_tx_resume; + + /* STP driver determines whether the function is enable. If not enable and + STP has received the kind of information, and STP have the right to put it away. + */ + sys_check_function_status = cb_func->cb_check_funciton_status; + + /* osal_unsleepable_lock_init(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock_init(&stp_core_ctx); + /* Setup timer to be used to check if f/w receive the data in the specific time + interval after being sent + */ + for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) + osal_unsleepable_lock_init(&stp_core_ctx.ring[i].mtx); + + stp_core_ctx.tx_timer.timeoutHandler = stp_tx_timeout_handler; + stp_core_ctx.tx_timer.timeroutHandlerData = 0; + osal_timer_create(&stp_core_ctx.tx_timer); + + STP_SET_BT_STK(stp_core_ctx, 0); + STP_SET_ENABLE(stp_core_ctx, 0); + STP_SET_ENABLE_DBG(stp_core_ctx, 0); + STP_SET_ENABLE_RST(stp_core_ctx, 0); + STP_SET_PENDING_TYPE(stp_core_ctx, 0); + STP_SET_READY(stp_core_ctx, 0); + STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, 0); + STP_SET_PSM_CORE(stp_core_ctx, stp_psm_init()); + STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, 0); + STP_ENABLE_FW_COREDUMP(stp_core_ctx, 0); + STP_SET_WMT_LAST_CLOSE(stp_core_ctx, 0); + STP_SET_EVT_ERR_ASSERT(stp_core_ctx, 0); + + if (!STP_PSM_CORE(stp_core_ctx)) { + ret = (-3); + goto ERROR; + } + + STP_SET_BTM_CORE(stp_core_ctx, stp_btm_init()); + if (!STP_BTM_CORE(stp_core_ctx)) { + STP_ERR_FUNC("STP_BTM_CORE(stp_core_ctx) initialization fail!\n"); + ret = (-3); + goto ERROR; + } + + if (STP_BTM_CORE(stp_core_ctx) != NULL) + g_mtkstp_dbg = stp_dbg_init(STP_BTM_CORE(stp_core_ctx)); + else + g_mtkstp_dbg = stp_dbg_init(NULL); + + if (!g_mtkstp_dbg) { + STP_ERR_FUNC("g_mtkstp_dbg initialization fail!\n"); + ret = (-3); + goto ERROR; + } + STP_SET_ENABLE_RST(stp_core_ctx, 1); +#ifdef CONFIG_LOG_STP_INTERNAL + mtk_wcn_stp_dbg_enable(); +#else + mtk_wcn_stp_dbg_enable(); +#endif + goto RETURN; + +ERROR: + stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); + +RETURN: + return ret; + +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_deinit +* DESCRIPTION +* deinit STP kernel +* PARAMETERS +* void +* RETURNS +* INT32 0 = success, others = failure +*****************************************************************************/ +INT32 mtk_wcn_stp_deinit(void) +{ + UINT32 i = 0; + + sys_if_tx = NULL; + sys_event_set = NULL; + sys_event_tx_resume = NULL; + sys_check_function_status = NULL; + + stp_dbg_deinit(g_mtkstp_dbg); + stp_btm_deinit(STP_BTM_CORE(stp_core_ctx)); + stp_psm_deinit(STP_PSM_CORE(stp_core_ctx)); + + for (i = 0; i < MTKSTP_MAX_TASK_NUM; i++) + osal_unsleepable_lock_deinit(&stp_core_ctx.ring[i].mtx); + + stp_ctx_lock_deinit(&stp_core_ctx); + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_btm_get_dmp +* DESCRIPTION +* get stp dump related information +* PARAMETERS +* buffer: dump placement, len: dump size +* RETURNS +* 0: Success Negative Value: Fail +*****************************************************************************/ + +int mtk_wcn_stp_btm_get_dmp(char *buf, int *len) +{ + return stp_dbg_dmp_out(g_mtkstp_dbg, buf, len); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_notify_stp +* DESCRIPTION +* WMT notification to STP that power saving job is done or not +* PARAMETERS +* +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +int mtk_wcn_stp_psm_notify_stp(const MTKSTP_PSM_ACTION_T action) +{ + return stp_psm_notify_stp(STP_PSM_CORE(stp_core_ctx), action); +} + +int mtk_wcn_stp_set_psm_state(MTKSTP_PSM_STATE_T state) +{ + return stp_psm_set_state(STP_PSM_CORE(stp_core_ctx), state); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_enable +* DESCRIPTION +* enable STP sleep/wakeup support +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +INT32 mtk_wcn_stp_psm_enable(INT32 idle_time_to_sleep) +{ +#if 0 + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) { + if (mtk_wcn_stp_is_ready()) + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + } else if (mtk_wcn_stp_is_sdio_mode()) { + stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + STP_DBG_FUNC("PSM is not support under SDIO mode\n"); + return 0; + } + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + +#else + if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { + return stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + } else if (mtk_wcn_stp_is_sdio_mode()) { + stp_psm_enable(STP_PSM_CORE(stp_core_ctx), idle_time_to_sleep); + STP_DBG_FUNC("PSM is not support under SDIO mode\n"); + return 0; + } + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; +#endif +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_psm_disable +* DESCRIPTION +* disable STP sleep/wakeup support +* PARAMETERS +* void +* RETURNS +* 0: Sccuess Negative value: Fail +*****************************************************************************/ +extern INT32 mtk_wcn_stp_psm_disable(VOID) +{ +#if 0 + if (MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) { + if (mtk_wcn_stp_is_ready()) + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + } + if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } else if (mtk_wcn_stp_is_sdio_mode()) { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + return 0; + } + STP_WARN_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return -1; + +#else + if (mtk_wcn_stp_is_ready() && mtk_wcn_stp_is_btif_fullset_mode()) { + return stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } else if (mtk_wcn_stp_is_sdio_mode()) { + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + return 0; + } + STP_DBG_FUNC("STP Not Ready, Dont do Sleep/Wakeup\n"); + return 0; + +#endif +} + +extern INT32 mtk_wcn_stp_psm_reset(VOID) +{ + return stp_psm_reset(STP_PSM_CORE(stp_core_ctx)); +} + +extern INT32 mtk_wcn_stp_dbg_disable(VOID) +{ + if (STP_IS_ENABLE_DBG(stp_core_ctx)) { + STP_DBG_FUNC("STP dbg mode is turned off\n"); + STP_SET_ENABLE_DBG(stp_core_ctx, 0); + stp_dbg_disable(g_mtkstp_dbg); + } else { + STP_WARN_FUNC("STP dbg mode has been turned off\n"); + } + + return 0; +} + +extern INT32 mtk_wcn_stp_dbg_enable(VOID) +{ + if (STP_NOT_ENABLE_DBG(stp_core_ctx)) { + STP_DBG_FUNC("STP dbg mode is turned on\n"); + STP_SET_ENABLE_DBG(stp_core_ctx, 1); + stp_dbg_enable(g_mtkstp_dbg); + } else { + STP_WARN_FUNC("STP dbg mode has been turned on\n"); + } + + return 0; +} + +INT32 mtk_wcn_stp_dbg_log_ctrl(UINT32 on) +{ + stp_dbg_log_ctrl(on); + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_ctrl(UINT32 on) +{ + STP_ENABLE_FW_COREDUMP(stp_core_ctx, on); + STP_INFO_FUNC("coredump function mode: %d.\n", on); + g_coredump_mode = on; + return 0; +} + +INT32 mtk_wcn_stp_coredump_flag_get(VOID) +{ + return STP_ENABLE_FW_COREDUMP_FLAG(stp_core_ctx); +} + +static INT32 stp_parser_data_in_mand_mode(UINT32 length, UINT8 *p_data) +{ + UINT8 padding_len = 0; + INT32 remain_length; /* GeorgeKuo: sync from MAUI, change to unsigned */ + MTK_WCN_BOOL is_function_active = 0; + INT32 i = length; + + while (i > 0) { + switch (stp_core_ctx.parser.state) { + case MTKSTP_SYNC: /* b'10 */ + /* if (((*p_data & 0x80) == 0x80) && ((*p_data & 0x40) == 0x00)) */ + /* if(*p_data == 0x80) */ + if ((*p_data & 0x80) == 0x80) { + /* STP_DBG_FUNC("[STP] STP Packet Start =========>\n"); */ + if (*p_data != 0x80) + STP_WARN_FUNC("SDIO not 0x80!!(0x%x)\n", *p_data); + + if (i >= 4) { +#if !(REMOVE_USELESS_LOG) + /*print header, when get the full STP header */ + UINT32 type = (*(p_data + 1) & 0x70) >> 4; + UINT8 *type_name = ""; + + type_name = stp_type_to_dbg_string(type); + STP_DBG_FUNC( + "STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", + *p_data, *(p_data + 1), *(p_data + 2), *(p_data + 3), + type_name, ((*(p_data + 1) & 0x0f) << 8) + *(p_data + 2), + (*p_data & 0x38) >> 3, *p_data & 0x07); +#endif + } else { + STP_WARN_FUNC("STP Rx: discard due to i < 4 (%d)\n", i); + } + + /* STP_DBG_FUNC("[STP] sync->nak\n"); */ + stp_change_rx_state(MTKSTP_NAK); + stp_core_ctx.rx_counter++; + } else { + STP_WARN_FUNC("sync to sync!!(0x%x)\n", *p_data); + stp_change_rx_state(MTKSTP_SYNC); + } + break; + + case MTKSTP_NAK: + /* STP_DBG_FUNC("[STP] nak->length\n"); */ + stp_change_rx_state(MTKSTP_LENGTH); + stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; + if (stp_core_ctx.parser.type <= MTKSTP_MAX_TASK_NUM) { + stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; + stp_core_ctx.rx_counter++; + } else { + STP_WARN_FUNC("nak to sync\n"); + stp_change_rx_state(MTKSTP_SYNC); + } + break; + + case MTKSTP_LENGTH: + /* STP_DBG_FUNC("[STP] length -> checksum\n"); */ + stp_change_rx_state(MTKSTP_CHECKSUM); + stp_core_ctx.parser.length += *p_data; + + /*Valid length checking */ + if (stp_core_ctx.parser.length < 2000) { + stp_core_ctx.rx_counter++; + } else { + STP_WARN_FUNC("The length of STP packet is not valid !!! length = %d\n", + stp_core_ctx.parser.length); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + /* return -1; */ + } + + break; + + case MTKSTP_CHECKSUM: + + if ((stp_core_ctx.parser.type == STP_TASK_INDX) || + (stp_core_ctx.parser.type == INFO_TASK_INDX)) { + stp_change_rx_state(MTKSTP_FW_MSG); + stp_core_ctx.rx_counter = 0; + i -= 1; + if (i != 0) + p_data += 1; + + continue; + } + + if (stp_core_ctx.parser.length == 0) { + STP_WARN_FUNC("checksum to sync\n"); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + } else { + /* STP_DBG_FUNC("[STP] checksum->data\n"); */ + stp_change_rx_state(MTKSTP_DATA); + stp_core_ctx.rx_counter = 0; + } + break; + + case MTKSTP_DATA: + + /* block copy instead of byte copy */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", + stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) { + /*boundary checking */ + if (stp_core_ctx.rx_counter + remain_length >= MTKSTP_BUFFER_SIZE) { + STP_ERR_FUNC("Abnormal!! Memory operation over boundary!!\n"); + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + return -1; + } + + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, + remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_core_ctx.parser.state = MTKSTP_CRC1; + continue; + + } else { /* only copy by data length */ + + /*fixed klocwork insight issue */ + /*boundary checking */ + if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { + STP_ERR_FUNC("Abnormal!! Memory operation over boundary 2!!\n"); + stp_core_ctx.rx_counter = 0; + return -1; + } + + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; /* all remain buffer are data */ + i = 0; + p_data += i; + continue; + } + break; + + case MTKSTP_CRC1: + stp_change_rx_state(MTKSTP_CRC2); + break; + + case MTKSTP_CRC2: +#if 1 + if (stp_core_ctx.parser.type == WMT_TASK_INDX) { + stp_core_ctx.parser.wmtsubtype = stp_core_ctx.rx_buf[1]; + STP_DBG_FUNC("wmt sub type (0x%x)\n", stp_core_ctx.parser.wmtsubtype); + } +#endif + /*SDIO mode do it. */ + if (mtk_wcn_stp_is_sdio_mode()) { + /*STP packet 4-bytes alignment */ + /*Discard padding bytes , otherwise make parser state machine disorder */ + if (i <= 4) { + /*STP_DBG_FUNC("STP last block padding %d bytes\n", i-1); */ + p_data += (i - 1); + i -= (i - 1); + } else { + padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03)) & 0x03; + p_data += padding_len; + i -= padding_len; + /*STP_DBG_FUNC("STP Agg padding %d bytes\n", padding_len); */ + } + } + stp_dbg_pkt_log(stp_core_ctx.parser.type, + 0, 0, 0, PKT_DIR_RX, stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if ((stp_core_ctx.parser.type == BT_TASK_INDX) && STP_BT_STK_IS_BLUEZ(stp_core_ctx)) { + int b; + + /*Indicate packet to hci_stp */ + if (gStpDbgLvl >= STP_LOG_DBG) { + stp_dump_data(stp_core_ctx.rx_buf, "indicate_to_bt_core", + stp_core_ctx.rx_counter); + } + + b = mtk_wcn_sys_if_rx(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); + if (b) + STP_ERR_FUNC("mtk_wcn_sys_if_rx is NULL\n"); + + } else { + + is_function_active = ( + (*sys_check_function_status)(stp_core_ctx.parser.type, OP_FUNCTION_ACTIVE) + == STATUS_FUNCTION_ACTIVE); + + /*check type and function if active? */ + if ((stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) + && (is_function_active == MTK_WCN_BOOL_TRUE)) { +#if CFG_WMT_LTE_COEX_HANDLING + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) + && stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG) { + STP_INFO_FUNC("wmt/lte coex package!\n"); + stp_add_to_rx_queue(stp_core_ctx.rx_buf, + stp_core_ctx.rx_counter, COEX_TASK_INDX); + stp_notify_btm_handle_wmt_lte_coex(STP_BTM_CORE(stp_core_ctx)); + } else { + stp_add_to_rx_queue(stp_core_ctx.rx_buf, + stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + + /*notify corresponding subfunction of incoming data */ + (*sys_event_set) (stp_core_ctx.parser.type); + } +#else + if ((stp_core_ctx.parser.type == WMT_TASK_INDX) + && stp_core_ctx.parser.wmtsubtype == WMT_LTE_COEX_FLAG) { + STP_WARN_FUNC + ("omit BT/WIFI & LTE coex msg handling in non-LTE projects\n"); + } else { + stp_add_to_rx_queue(stp_core_ctx.rx_buf, + stp_core_ctx.rx_counter, + stp_core_ctx.parser.type); + + /*notify corresponding subfunction of incoming data */ + (*sys_event_set) (stp_core_ctx.parser.type); + } +#endif + } else { + if (is_function_active == MTK_WCN_BOOL_FALSE) { + STP_ERR_FUNC + ("function type = %d is inactive, so no en-queue to rx\n", + stp_core_ctx.parser.type); + } else { + STP_ERR_FUNC + ("mtkstp_process_packet: type = %x, the type is invalid\n", + stp_core_ctx.parser.type); + } + } + } + + /* STP_DBG_FUNC("[STP] crc2->sync\n"); */ + /* STP_DBG_FUNC("[STP] STP Packet End <=========\n"); */ + stp_core_ctx.rx_counter = 0; + stp_change_rx_state(MTKSTP_SYNC); + + break; + + case MTKSTP_FW_MSG: + + /*f/w assert and exception information */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", + stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + } + + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + + if (i >= remain_length) { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, + remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; + /*Trace32 Dump */ + if (stp_core_ctx.parser.type == STP_TASK_INDX) { + /* g_block_tx = 1; */ + mtk_wcn_stp_coredump_start_ctrl(1); + pr_debug("[len=%d][type=%d]\n%s\n", stp_core_ctx.rx_counter, + stp_core_ctx.parser.type, stp_core_ctx.rx_buf); + /*use paged dump or full dump */ + stp_btm_notify_wmt_dmp_wq(stp_core_ctx.btm); +#if 0 + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_DMP /*STP_DBG_FW_ASSERT */ , 5, + 0, 0, 0, 0, + (stp_core_ctx.rx_counter + 1), stp_core_ctx.rx_buf); +#endif + } + + /*discard CRC */ + /* we will discard antoher CRC on the outer switch procedure. */ + if (i >= 1) { + STP_INFO_FUNC("crc discard.. i = %d\n", i); + i -= 1; + if (i > 0) + p_data += 1; + + } + + /*STP packet 4-bytes alignment */ + /*Discard padding bytes , otherwise make parser state machine disorder */ + if (i <= 4) { + STP_INFO_FUNC + ("\n[STP]FW_EVENT========= block padding %d bytes =========\n", + i - 1); + p_data += (i - 1); + i -= (i - 1); + } else { + padding_len = (0x04 - ((stp_core_ctx.parser.length + 6) & 0x03)) & 0x03; + p_data += padding_len; + i -= padding_len; + STP_INFO_FUNC + ("\n[STP]FW_EVENT========= STP Agg padding %d bytes =========\n", + padding_len); + } + stp_change_rx_state(MTKSTP_SYNC); + + } else { /* only copy by data length */ + + STP_ERR_FUNC("raw data doesn't contain full stp packet!!\n"); + } + break; + default: + break; + } + p_data++; + i--; + } + + return 0; +} + +static INT32 stp_parser_data_in_full_mode(UINT32 length, UINT8 *p_data) +{ + INT32 remain_length; /* GeorgeKuo: sync from MAUI, change to unsigned */ + INT32 i = length; + + while (i > 0) { + switch (stp_core_ctx.parser.state) { + + case MTKSTP_RESYNC1: /* RESYNC must be 4 _continuous_ 0x7f */ + if (*p_data == 0x7f) + stp_change_rx_state(MTKSTP_RESYNC2); + else + stp_change_rx_state(MTKSTP_RESYNC1); + break; + case MTKSTP_RESYNC2: + if (*p_data == 0x7f) + stp_change_rx_state(MTKSTP_RESYNC3); + else + stp_change_rx_state(MTKSTP_RESYNC1); + break; + case MTKSTP_RESYNC3: + if (*p_data == 0x7f) + stp_change_rx_state(MTKSTP_RESYNC4); + else + stp_change_rx_state(MTKSTP_RESYNC1); + break; + case MTKSTP_RESYNC4: + if (*p_data == 0x7f) + stp_change_rx_state(MTKSTP_SYNC); + else + stp_change_rx_state(MTKSTP_RESYNC1); + break; + case MTKSTP_SYNC: /* b'10 */ + STP_DUMP_PACKET_HEAD(p_data, "rx (uart):", length > 4 ? 4 : length); + if (((*p_data & 0x80) == 0x80) && ((*p_data & 0x40) == 0x00)) { + stp_change_rx_state(MTKSTP_NAK); + stp_core_ctx.parser.seq = (*p_data & 0x38) >> 3; + stp_core_ctx.parser.ack = *p_data & 0x07; + stp_core_ctx.rx_buf[0] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + /* stp_core_ctx.rx_counter++; */ + + if (i >= 4 && gStpDbgLvl >= STP_LOG_DBG) { + /*print header, when get the full STP header */ +#if !(REMOVE_USELESS_LOG) + int type = (*(p_data + 1) & 0x70) >> 4; + char *type_name = ""; + + type_name = stp_type_to_dbg_string(type); + + STP_DBG_FUNC + ("STP Rx Header: [%02x %02x %02x %02x] type=%s, len=%d, seq=%d, ack=%d\n", + *p_data, *(p_data + 1), *(p_data + 2), *(p_data + 3), type_name, + ((*(p_data + 1) & 0x0f) << 8) + *(p_data + 2), + (*p_data & 0x38) >> 3, *p_data & 0x07); +#endif + } else { + STP_DBG_FUNC("STP Rx: discard due to i < 4\n"); + } + } else if ((*p_data == 0x7f) && (prev_state == MTKSTP_RESYNC4)) { + /* if this 0x7f is continuous to resync pattern */ + /* skip this continuous 0x7f, remain current & prev state */ + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: continuous resync pattern, buff = %x\n", *p_data); + } else if (*p_data == 0x7f) { /* a start of 0x7f, maybe this is resync pattern */ + stp_change_rx_state(MTKSTP_RESYNC2); + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: go to MTKSTP_RESYNC2, buff = %x\n", *p_data); + } else if (*p_data == 0x55) { /* STP delimiter */ + /* do nothing for delimiter */ + } else { /* unexpected, go to resync1 */ + osal_assert(0); + STP_ERR_FUNC("MTKSTP_SYNC: unexpected data, buff = %x\n", *p_data); + } + break; + + case MTKSTP_NAK: + /* (*sys_dbg_print)("MTKSTP_NAK : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ + if (fgEnableNak == 0) + stp_core_ctx.parser.nak = 0; /* disable NAK */ + else + stp_core_ctx.parser.nak = (*p_data & 0x80) >> 7; + + stp_core_ctx.parser.type = (*p_data & 0x70) >> 4; + stp_core_ctx.parser.length = (*p_data & 0x0f) << 8; + stp_core_ctx.rx_buf[1] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + /*stp_core_ctx.rx_counter++; */ + if (stp_core_ctx.parser.nak) + STP_ERR_FUNC("MTKSTP_NAK TRUE: mtk_wcn_stp_parser_data, buff = %x\n", *p_data); + + if (stp_core_ctx.parser.type < MTKSTP_MAX_TASK_NUM) + stp_change_rx_state(MTKSTP_LENGTH); + else + stp_change_rx_state(MTKSTP_SYNC); + break; + + case MTKSTP_LENGTH: + /* (*sys_dbg_print)("MTKSTP_LENGTH : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ + stp_change_rx_state(MTKSTP_CHECKSUM); + stp_core_ctx.parser.length += *p_data; + + /*Valid length checking */ + if (stp_core_ctx.parser.length > 2048) { + STP_ERR_FUNC("The length of STP packet is not valid !!! length = %d\n", + stp_core_ctx.parser.length); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + STP_TRACE_FUNC("--\n"); + return -1; + } + + stp_core_ctx.rx_buf[2] = *p_data; + /* Geoge FIXME: WHY comment the following line? */ + /*stp_core_ctx.rx_counter++; */ + break; + + case MTKSTP_CHECKSUM: + /* (*sys_dbg_print)("MTKSTP_CHECKSUM : mtk_wcn_stp_parser_data, buff = %x", *p_data); */ + if ((stp_core_ctx.parser.type == STP_TASK_INDX) || + (stp_core_ctx.parser.type == INFO_TASK_INDX)) { + stp_change_rx_state(MTKSTP_FW_MSG); + stp_core_ctx.rx_counter = 0; + i -= 1; + if (i != 0) + p_data += 1; + + continue; + } + + if (((stp_core_ctx.rx_buf[0] + + stp_core_ctx.rx_buf[1] + stp_core_ctx.rx_buf[2]) & 0xff) == *p_data) { + /* header only packet */ + if (stp_core_ctx.parser.length == 0) { + INT32 fgTriggerResume = (-1); + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + if (stp_core_ctx.inband_rst_set == 0) { + stp_dbg_pkt_log(STP_TASK_INDX, + stp_core_ctx.parser.ack, + stp_core_ctx.parser.seq, + 5, /* STP type id */ + PKT_DIR_RX, + NULL, + 0); + fgTriggerResume = stp_process_rxack(); + } else { + STP_WARN_FUNC + ("Now it's inband reset process and drop ACK packet.\n"); + } + + if (fgTriggerResume == 0) { + /* notify adaptation layer for + * possible tx resume mechanism + */ + (*sys_event_tx_resume) (stp_core_ctx.sequence.winspace); + } + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.rx_counter = 0; + } else { + stp_change_rx_state(MTKSTP_DATA); + stp_core_ctx.rx_counter = 0; + } + } else { + STP_ERR_FUNC("The checksum of header is error !!! %02x %02x %02x %02x\n", + stp_core_ctx.rx_buf[0], stp_core_ctx.rx_buf[1], + stp_core_ctx.rx_buf[2], *p_data); + /* George FIXME: error handling mechanism shall be refined */ + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + + /* since checksum error is usually related to interface + * buffer overflow, so we just let timeout mechanism to + * handle such error. + */ + STP_TRACE_FUNC("--\n"); + /* return and purge COMM port */ + return -1; + /*stp_send_ack(1); NAK mechanism is removed */ + } + break; + + case MTKSTP_DATA: +#if 0 + if (stp_core_ctx.rx_counter < stp_core_ctx.parser.length) { + stp_core_ctx.rx_buf[stp_core_ctx.rx_counter] = *p_data; + stp_core_ctx.rx_counter++; + } + if (stp_core_ctx.rx_counter == stp_core_ctx.parser.length) + stp_change_rx_state(MTKSTP_CRC1); +#else + /* block copy instead of byte copy */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", + stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, + remain_length); + + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_core_ctx.parser.state = MTKSTP_CRC1; + continue; + } else { /* only copy by data length */ + + /*fixed klocwork insight issue */ + if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { + STP_ERR_FUNC + ("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + STP_TRACE_FUNC("--\n"); + return -1; + } + + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; /* all remain buffer are data */ + i = 0; + p_data += i; + continue; + } +#endif + break; + + case MTKSTP_CRC1: + stp_change_rx_state(MTKSTP_CRC2); + stp_core_ctx.parser.crc = *p_data; + break; + case MTKSTP_CRC2: + stp_change_rx_state(MTKSTP_SYNC); + stp_core_ctx.parser.crc += (*p_data) << 8; +#if 1 + if (stp_core_ctx.parser.type == WMT_TASK_INDX) { + stp_core_ctx.parser.wmtsubtype = stp_core_ctx.rx_buf[1]; + STP_DBG_FUNC("wmt sub type is (0x%x)\n", stp_core_ctx.parser.wmtsubtype); + } +#endif + if (stp_check_crc(stp_core_ctx.rx_buf, stp_core_ctx.rx_counter, stp_core_ctx.parser.crc) + == MTK_WCN_BOOL_TRUE) { + if (stp_core_ctx.inband_rst_set == 0) + stp_process_packet(); + else + STP_WARN_FUNC("Now it's inband reset process and drop packet.\n"); + } else { + STP_ERR_FUNC("The CRC of packet is error !!!\n"); + /* George FIXME: error handling mechanism shall be refined */ + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + + /* since checksum error is usually related to interface + * buffer overflow, so we just let timeout mechanism to + * handle such error. + */ + STP_TRACE_FUNC("--\n"); + /* return and purge COMM port */ + return -1; + /*stp_send_ack(1); NAK mechanism is removed */ + } + break; + + case MTKSTP_FW_MSG: +#if CFG_WMT_DUMP_INT_STATUS + if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) + wmt_plat_BGF_irq_dump_status(); +#endif + if (STP_IS_READY(stp_core_ctx)) + mtk_wcn_stp_dbg_dump_package(); + + STP_SET_READY(stp_core_ctx, 0); + /*stp inband reset */ + if (stp_core_ctx.parser.type == STP_TASK_INDX && + stp_core_ctx.parser.seq == 0 && + stp_core_ctx.parser.ack == 0 && + stp_core_ctx.parser.length == 0 && stp_core_ctx.inband_rst_set == 1) { + STP_INFO_FUNC("Inband reset event get! Resync STP with firmware!\n\r"); + stp_rest_ctx_state(); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.inband_rst_set = 0; + /* STP_INFO_FUNC("Restart STP Timer\n\r"); */ + /* (*sys_timer_start)(stp_core_ctx.tx_timer, + * mtkstp_tx_timeout, + * (MTK_WCN_TIMER_CB)stp_tx_timeout_handler, + * NULL); + */ + STP_TRACE_FUNC("--\n"); + return 0; + } + + /*f/w assert and exception information */ + if (stp_core_ctx.parser.length < stp_core_ctx.rx_counter) { + STP_ERR_FUNC("Abnormal length in STP_DATA phase 0x%x, 0x%x\n", + stp_core_ctx.parser.length, stp_core_ctx.rx_counter); + osal_assert(0); + } + + remain_length = stp_core_ctx.parser.length - stp_core_ctx.rx_counter; + if (i >= remain_length) { + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, + remain_length); + i -= remain_length; + p_data += remain_length; + stp_core_ctx.rx_counter = stp_core_ctx.parser.length; + stp_change_rx_state(MTKSTP_SYNC); + *(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter) = '\0'; + /* STP_ERR_FUNC("%s [%d]\n", stp_core_ctx.rx_buf, stp_core_ctx.rx_counter); */ +#if 0 + if ((stp_core_ctx.rx_counter == 1) && (stp_core_ctx.rx_buf[0] == 0xFF)) { + /* For MT6620, enable/disable coredump function is controlled by + * firmware for the moment, we need to set coredump enable flag + * to be 1 after see firmware send a pariticallar character(0xff) + * before any coredump packet is sent + */ + mtk_wcn_stp_coredump_flag_ctrl(1); + } +#endif + /*Trace32 Dump */ + if (STP_IS_ENABLE_DBG(stp_core_ctx) && + (stp_core_ctx.parser.type == STP_TASK_INDX)) { + if (0 != stp_core_ctx.rx_counter) { + STP_SET_READY(stp_core_ctx, 0); + mtk_wcn_stp_ctx_save(); + STP_INFO_FUNC("++ start to read paged dump and paged trace ++\n"); + stp_btm_notify_wmt_dmp_wq(stp_core_ctx.btm); + stp_btm_notify_wmt_trace_wq(stp_core_ctx.btm); + STP_INFO_FUNC("++ start to read paged dump and paged trace --\n"); + + } + STP_INFO_FUNC("[len=%d][type=%d]\n%s\n", stp_core_ctx.rx_counter, + stp_core_ctx.parser.type, stp_core_ctx.rx_buf); + } + + /*Runtime FW Log */ + else if (STP_IS_ENABLE_DBG(stp_core_ctx) + && (stp_core_ctx.parser.type == INFO_TASK_INDX)) { + stp_dbg_log_pkt(g_mtkstp_dbg, STP_DBG_FW_LOG, STP_TASK_INDX, 5, 0, 0, 0, + (stp_core_ctx.rx_counter + 1), stp_core_ctx.rx_buf); + mtk_wcn_stp_dbg_dump_package(); + } + /*Normal mode: whole chip reset */ + else { + /*Aee Kernel Warning Message Shown First */ + /* (*sys_dbg_assert_aee)("[MT662x]f/w Assert", stp_core_ctx.rx_buf); */ + mtk_wcn_stp_coredump_start_ctrl(0); + mtk_wcn_stp_dbg_dump_package(); + + osal_dbg_assert_aee(stp_core_ctx.rx_buf, stp_core_ctx.rx_buf); + /*Whole Chip Reset Procedure Invoke */ + if (STP_IS_ENABLE_RST(stp_core_ctx)) { + STP_SET_READY(stp_core_ctx, 0); + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + } else { + STP_INFO_FUNC + ("No to launch whole chip reset! for debugging purpose\n"); + } + } + /*discard CRC */ + if (i >= 2) { + STP_DBG_FUNC("crc discard.. i = %d\n", i); + i -= 2; + if (i > 0) + p_data += 2; + } + continue; + } else { /* only copy by data length */ + + /*fixed klocwork insight issue */ + if (i + stp_core_ctx.rx_counter >= MTKSTP_BUFFER_SIZE) { + STP_ERR_FUNC + ("Fail to handle Packet, maybe it doesn't follow STP protocol.\n"); + stp_change_rx_state(MTKSTP_RESYNC1); + stp_core_ctx.rx_counter = 0; + return -1; + } + osal_memcpy(stp_core_ctx.rx_buf + stp_core_ctx.rx_counter, p_data, i); + stp_core_ctx.rx_counter += i; /* all remain buffer are data */ + i = 0; + p_data += i; + continue; + } + + break; + default: + break; + } + p_data++; + i--; + } + + return 0; +} +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* int 0 = success; -1 = crc/checksum error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +int _mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length) +#else +int mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length) +#endif +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + INT32 i; + UINT8 *p_data; + INT32 ret = 0; +#ifdef DEBUG_DUMP_PACKET_HEAD + static UINT32 counter; + + STP_TRACE_FUNC("++, rx (cnt=%d,len=%d)\n", ++counter, length); +#endif + +#if 0 +#ifdef CONFIG_POWER_SAVING_SUPPORT + if (stp_is_apply_powersaving()) { + /* If now chip is awake, to restart monitor! */ + if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { + STP_DBG_FUNC("To restart moinotr when rx\n\r"); + stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); + } + } +#endif +#endif + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + /* George FIXME: WHY or HOW can we reduct the locked region? */ + /*flags = (*sys_mutex_lock)(stp_core_ctx.stp_mutex); */ + i = length; + p_data = (UINT8 *) buffer; + +/* stp_dump_data(buffer, "rx queue", length); */ + + /*STP is not enabled and only WMT can use Raw data path */ + if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == STP_PENDING_TYPE(stp_core_ctx)) { + /* route to task who send command */ + stp_add_to_rx_queue(buffer, length, STP_PENDING_TYPE(stp_core_ctx)); + + /* mike: notify corresponding subfunction of incoming data */ + (*sys_event_set) (STP_PENDING_TYPE(stp_core_ctx)); + } + /* STP over SDIO */ + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { +#if !(REMOVE_USELESS_LOG) + if (gStpDbgLvl >= STP_LOG_DBG) + stp_dump_data(buffer, "sdio parser_in", length); +#endif + /* STP_DBG_FUNC("sdio stp parser data length = %d\n", length); */ + ret = stp_parser_data_in_mand_mode(i, p_data); + } + /* STP over UART */ + else if (mtk_wcn_stp_is_btif_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) + ret = stp_parser_data_in_full_mode(i, p_data); + + /* George FIXME: WHY or HOW can we reduct the locked region? */ + /*(*sys_mutex_unlock)(stp_core_ctx.stp_mutex, flags); */ + STP_TRACE_FUNC("--\n"); + return ret; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_parser_data); +#endif + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_enable +* DESCRIPTION +* enable/disable STP +* PARAMETERS +* value [IN] 0=disable, others=enable +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_enable(INT32 value) +{ + STP_DBG_FUNC("%s: set the current enable = (%d)\n", __func__, value); + + stp_rest_ctx_state(); + STP_SET_ENABLE(stp_core_ctx, value); + if (!value) { + mtk_wcn_stp_psm_reset(); + } else { +/* g_block_tx = 0; */ + mtk_wcn_stp_coredump_start_ctrl(0); + } + return 0; +} + +INT32 mtk_wcn_stp_dbg_dump_package(VOID) +{ + if (STP_NOT_ENABLE(stp_core_ctx)) { + STP_INFO_FUNC("STP dbg mode is off\n"); + + } else { + STP_INFO_FUNC("STP dbg mode is on\n"); + /* if (0 == g_block_tx) */ + if (0 == mtk_wcn_stp_coredump_start_get()) { + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_LOG); + mtk_wcn_consys_stp_btif_logger_ctrl(BTIF_DUMP_BTIF_REG); + stp_dbg_dmp_printk(g_mtkstp_dbg); + } else { + STP_INFO_FUNC("assert start flag is set, disable packet dump function\n"); + } + } + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_ready +* DESCRIPTION +* ready/un-ready STP +* PARAMETERS +* value [IN] 0=un-ready, others=ready +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_ready(INT32 value) +{ + STP_DBG_FUNC("set ready (%d)\n", value); + + STP_SET_READY(stp_core_ctx, value); + /*if whole chip reset, reset the debuggine mode */ +#ifndef CONFIG_LOG_STP_INTERNAL + /* mtk_wcn_stp_dbg_disable(); */ +#endif + + if (stp_is_apply_powersaving()) { + STP_INFO_FUNC("Restart the stp-psm monitor !!\n"); + stp_psm_disable(STP_PSM_CORE(stp_core_ctx)); + } + + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_ctrl +* DESCRIPTION +* set f/w assert flag in STP context +* PARAMETERS +* value [IN] 0=assert end, others=assert begins +* RETURNS +* INT32 0=success, others=error +*****************************************************************************/ +INT32 mtk_wcn_stp_coredump_start_ctrl(UINT32 value) +{ + STP_DBG_FUNC("set f/w assert (%d)\n", value); + + STP_SET_FW_COREDUMP_FLAG(stp_core_ctx, value); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_coredump_start_get +* DESCRIPTION +* get f/w assert flag in STP context +* PARAMETERS +* VOID +* RETURNS +* INT32 0= f/w assert flag is not set, others=f/w assert flag is set +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_coredump_start_get(VOID) +#else +INT32 mtk_wcn_stp_coredump_start_get(VOID) +#endif +{ + return STP_FW_COREDUMP_FLAG(stp_core_ctx); +} + +/* mtk_wcn_stp_set_wmt_last_close -- set the state of link(UART or SDIO) + * @ value - 1, link already be closed; 0, link is open + * + * Return 0 if success; else error code + */ +INT32 mtk_wcn_stp_set_wmt_last_close(UINT32 value) +{ + STP_INFO_FUNC("set wmt_last_close flag (%d)\n", value); + + STP_SET_WMT_LAST_CLOSE(stp_core_ctx, value); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 > 0: length transmitted; = 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#else +INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#endif +{ + UINT8 mtkstp_header[MTKSTP_HEADER_SIZE], temp[2]; + UINT8 *p_tx_buf = NULL; + UINT16 crc; + INT32 ret = 0; + MTK_WCN_BOOL is_quick_enable = MTK_WCN_BOOL_TRUE; + + /* osal_buffer_dump(buffer,"tx", length, 32); */ + + if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { + STP_ERR_FUNC("WMT lats close,should not have tx request!\n"); + return length; + } + /* if(g_block_tx) */ + if (0 != mtk_wcn_stp_coredump_start_get()) { + STP_ERR_FUNC("STP fw coredump start flag set...\n"); + return length; + } +#ifdef CONFIG_POWER_SAVING_SUPPORT + is_quick_enable = stp_psm_is_quick_ps_support(); + STP_DBG_FUNC("is quick sleep enable:%s\n", is_quick_enable ? "yes" : "no"); + if (MTK_WCN_BOOL_TRUE == is_quick_enable) { + if (type != WMT_TASK_INDX) { +#if PSM_USE_COUNT_PACKAGE + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0); +#else + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 0, length); +#endif + } + /* if(stp_is_apply_powersaving()) */ + { + if (type == WMT_TASK_INDX) + goto DONT_MONITOR; + /*-----------------------------STP_PSM_Lock----------------------------------------*/ + ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); + if (ret) { + STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { + if (stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))) { + STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); + stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); + } + } else { + ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); + stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + return ret; + } + } + } else { + /* if(stp_is_apply_powersaving()) */ + { + if (type == WMT_TASK_INDX) + goto DONT_MONITOR; + /* If now chip is awake, to restart monitor! */ + /* STP_INFO_FUNC("check if block traffic !!\n"); */ + /*-----------------------------STP_PSM_Lock----------------------------------------*/ + ret = stp_psm_thread_lock_aquire(STP_PSM_CORE(stp_core_ctx)); + if (ret) { + STP_ERR_FUNC("--->lock psm_thread_lock failed ret=%d\n", ret); + return ret; + } + + if (!stp_psm_is_to_block_traffic(STP_PSM_CORE(stp_core_ctx))) { + /* STP_INFO_FUNC("not to block !!\n"); */ + if (stp_psm_has_pending_data(STP_PSM_CORE(stp_core_ctx))) { + STP_WARN_FUNC("***** Release psm hold data before send normal data *****\n"); + stp_psm_release_data(STP_PSM_CORE(stp_core_ctx)); + } + stp_psm_start_monitor(STP_PSM_CORE(stp_core_ctx)); + } else { + /* STP_INFO_FUNC("to block !!\n"); */ + + /* STP_INFO_FUNC("*****hold data in psm queue data length = %d\n", + * length); + */ + /* stp_dump_data(buffer, "Hold in psm queue", length); */ + /* hold datas */ + ret = stp_psm_hold_data(STP_PSM_CORE(stp_core_ctx), buffer, length, type); + /* wmt notification */ + STP_INFO_FUNC("#####Type = %d, to inform WMT to wakeup chip, ret = %d:0x%2x,0x%2x\n", + type, ret, *buffer, *(buffer + 1)); + stp_psm_notify_wmt_wakeup(STP_PSM_CORE(stp_core_ctx)); + /* STP_INFO_FUNC("*********Type = %d, to inform WMT to wakeup chip>end\n", type); */ + /*-----------------------------STP_PSM_UnLock----------------------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + return ret; + } + } + } +DONT_MONITOR: +#endif + if (type == BT_TASK_INDX) { + static const UINT8 rst_buf[4] = { 0x01, 0x03, 0x0c, 0x00 }; + + if (!osal_strncmp(buffer, rst_buf, 4)) + osal_printtimeofday("############ BT Rest start -->"); + } + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + /*Only WMT can set raw data */ + if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX != type) { + /* no-op */ + /* NULL; */ + } else if (STP_NOT_ENABLE(stp_core_ctx) && WMT_TASK_INDX == type) { + /* ret = mtk_wcn_stp_send_data_raw(buffer, length, type); */ + /* NULL; */ + } + /* STP over SDIO */ + else if ((mtk_wcn_stp_is_sdio_mode() || mtk_wcn_stp_is_btif_mand_mode()) && STP_IS_ENABLE(stp_core_ctx)) { + + /* osal_printtimeofday("[ STP][SDIO][ B][W]"); */ + + mtkstp_header[0] = 0x80; + mtkstp_header[1] = (type << 4) + (((length) >> 8) & 0x0f); + mtkstp_header[2] = (length) & 0xff; + mtkstp_header[3] = 0x00; + + /* HEADER */ + p_tx_buf = &stp_core_ctx.tx_buf[0]; + osal_memcpy(p_tx_buf, mtkstp_header, MTKSTP_HEADER_SIZE); + p_tx_buf += MTKSTP_HEADER_SIZE; + + /* PAYLOAD */ + osal_memcpy(p_tx_buf, buffer, length); + p_tx_buf += length; + + /* CRC */ + temp[0] = 0x00; + temp[1] = 0x00; + osal_memcpy(p_tx_buf, temp, 2); + stp_dbg_pkt_log(type, 0, 0, 0, PKT_DIR_TX, buffer, length); + (*sys_if_tx) (&stp_core_ctx.tx_buf[0], (MTKSTP_HEADER_SIZE + length + 2), &ret); + + if ((MTKSTP_HEADER_SIZE + length + 2) != ret) { + STP_ERR_FUNC("stp send tx packet: %d, maybe stp_if_tx == NULL\n", ret); + osal_assert(0); + ret = 0; + } else { + ret = (INT32) length; + } + + /* osal_printtimeofday("[ STP][SDIO][ E][W]"); */ + } + /* STP over UART */ + else if (mtk_wcn_stp_is_btif_fullset_mode() && STP_IS_ENABLE(stp_core_ctx)) { + + /* osal_printtimeofday("[ STP][UART][ B][W]"); */ + /* STP_INFO_FUNC("Write byte %d\n", length); */ + + if ((stp_core_ctx.sequence.winspace > 0) && + (stp_core_ctx.inband_rst_set == 0) && + (stp_is_tx_res_available(MTKSTP_HEADER_SIZE + length + MTKSTP_CRC_SIZE))) { + /*Make Header */ + /* (*sys_dbg_print)("mtk_wcn_stp_send_data 1, txseq = %d, winspace = %d", + * stp_core_ctx.sequence.txseq, stp_core_ctx.sequence.winspace); + */ + mtkstp_header[0] = 0x80 + (stp_core_ctx.sequence.txseq << 3) + stp_core_ctx.sequence.txack; + mtkstp_header[1] = (type << 4) + ((length & 0xf00) >> 8); + mtkstp_header[2] = length & 0xff; + mtkstp_header[3] = (mtkstp_header[0] + mtkstp_header[1] + mtkstp_header[2]) & 0xff; + stp_core_ctx.tx_start_addr[stp_core_ctx.sequence.txseq] = stp_core_ctx.tx_write; + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] = MTKSTP_HEADER_SIZE + length + 2; + if (fgEnableDelimiter == 1) { + stp_core_ctx.tx_length[stp_core_ctx.sequence.txseq] += STP_DEL_SIZE; + stp_add_to_tx_queue(&stp_delimiter[0], STP_DEL_SIZE); + } + stp_add_to_tx_queue(mtkstp_header, MTKSTP_HEADER_SIZE); + + /*Make Payload */ + stp_add_to_tx_queue(buffer, length); + + /*Make CRC */ + crc = osal_crc16(buffer, length); + temp[0] = crc & 0xff; + temp[1] = (crc & 0xff00) >> 8; + stp_add_to_tx_queue(temp, 2); + stp_dbg_pkt_log(type, + stp_core_ctx.sequence.txack, + stp_core_ctx.sequence.txseq, crc, PKT_DIR_TX, buffer, length); + + /*Kick to UART */ + stp_send_tx_queue(stp_core_ctx.sequence.txseq); + + INDEX_INC(stp_core_ctx.sequence.txseq); + stp_core_ctx.sequence.winspace--; + + /*Setup the Retry Timer */ + osal_timer_stop(&stp_core_ctx.tx_timer); + if (stp_core_ctx.sequence.winspace != MTKSTP_WINSIZE) + osal_timer_start(&stp_core_ctx.tx_timer, mtkstp_tx_timeout); + else + STP_ERR_FUNC("mtk_wcn_stp_send_data: wmt_stop_timer\n"); + + ret = (INT32) length; + } else { + /* + No winspace to send. Let caller retry + */ + if (stp_core_ctx.inband_rst_set == 1) + STP_WARN_FUNC("Now it's inband reset process and drop sent packet.\n"); + else + STP_ERR_FUNC("There is no winspace/txqueue to send !!!\n"); + + ret = 0; + } + + /* osal_printtimeofday("[ STP][UART][ E][W]"); */ + } + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + +#ifdef CONFIG_POWER_SAVING_SUPPORT + + if (MTK_WCN_BOOL_TRUE == is_quick_enable) { + if (type != WMT_TASK_INDX) { + stp_psm_notify_wmt_sleep(STP_PSM_CORE(stp_core_ctx)); + /*-----------------------STP_PSM_UnLock-------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + } + } else { + /* if(stp_is_apply_powersaving()) */ + /* { */ + if (type != WMT_TASK_INDX) { + + /*--------------------STP_PSM_UnLock--------------------------*/ + stp_psm_thread_lock_release(STP_PSM_CORE(stp_core_ctx)); + } + /* } */ + } +#endif + + return ret; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_send_data); +#endif +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data_raw +* DESCRIPTION +* send raw data to common interface, bypass STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#else +INT32 mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type) +#endif +{ + UINT32 written = 0; + INT32 ret = 0; + + if (0 != STP_WMT_LAST_CLOSE(stp_core_ctx)) { + STP_ERR_FUNC("WMT lats close,should not have tx request!"); + return length; + } + + STP_DBG_FUNC("mtk_wcn_stp_send_data_raw, type = %d, data = %x %x %x %x %x %x ", type, buffer[0], buffer[1], + buffer[2], buffer[3], buffer[4], buffer[5]); + STP_SET_PENDING_TYPE(stp_core_ctx, type); /* remember tx type, forward following rx to this type */ + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + stp_dbg_pkt_log(type, 0, 0, 0, PKT_DIR_TX, buffer, 1); + (*sys_if_tx) (&buffer[0], length, &written); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + + if (written == 0) + stp_dump_data(&buffer[0], "tx raw failed:", length); + + if (written == length) + ret = (INT32) written; + else + ret = (-1); + + return ret; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_send_data_raw); +#endif +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type) +#else +INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type) +#endif +{ + /* GeorgeKuo modify: reduce "if" branch */ + UINT16 copyLen = 0; + UINT16 tailLen = 0; + + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + while (stp_core_ctx.ring[type].read_p != stp_core_ctx.ring[type].write_p) { + /* GeorgeKuo modify: reduce if branch */ + if (stp_core_ctx.ring[type].write_p > stp_core_ctx.ring[type].read_p) { + copyLen = stp_core_ctx.ring[type].write_p - stp_core_ctx.ring[type].read_p; + if (copyLen > length) + copyLen = length; + + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + } else { + tailLen = MTKSTP_BUFFER_SIZE - stp_core_ctx.ring[type].read_p; + if (tailLen > length) { /* exclude equal case to skip wrap check */ + copyLen = length; + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, + copyLen); + stp_core_ctx.ring[type].read_p += copyLen; + } else { + /* part 1: copy tailLen */ + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + stp_core_ctx.ring[type].read_p, + tailLen); + + buffer += tailLen; /* update buffer offset */ + + /* part 2: check if head length is enough */ + copyLen = length - tailLen; + copyLen = + (stp_core_ctx.ring[type].write_p < + copyLen) ? stp_core_ctx.ring[type].write_p : copyLen; + + if (copyLen) + osal_memcpy(buffer, stp_core_ctx.ring[type].buffer + 0, copyLen); + + /* Update read_p final position */ + stp_core_ctx.ring[type].read_p = copyLen; + + /* update return length: head + tail */ + copyLen += tailLen; + } + } + break; + } + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if ((MTK_WCN_BOOL_TRUE == stp_psm_is_quick_ps_support()) && (type != WMT_TASK_INDX)) { +#if PSM_USE_COUNT_PACKAGE + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1); +#else + stp_psm_disable_by_tx_rx_density(STP_PSM_CORE(stp_core_ctx), 1, copyLen); +#endif + } + + return copyLen; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_receive_data); +#endif +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +#else +INT32 mtk_wcn_stp_is_rxqueue_empty(UINT8 type) +#endif +{ + INT32 ret; + + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + if (stp_core_ctx.ring[type].read_p == stp_core_ctx.ring[type].write_p) + ret = 1; /* queue is empty */ + else + ret = 0; /* queue is not empty */ + + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + + return ret; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_is_rxqueue_empty); +#endif +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_set_sdio_mode +* DESCRIPTION +* Set stp for SDIO mode +* PARAMETERS +* sdio_flag [IN] sdio mode flag (TRUE:SDIO mode, FALSE:UART mode) +* RETURNS +* void +*****************************************************************************/ + +void mtk_wcn_stp_set_mode(UINT32 mode) +{ + STP_SET_SUPPORT_PROTOCOL(stp_core_ctx, mode); + + STP_DBG_FUNC("STP_SUPPORT_PROTOCOL = %08x\n", STP_SUPPORT_PROTOCOL(stp_core_ctx)); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_fullset_mode +* DESCRIPTION +* Is stp use UART fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Fullset mode, FALSE:Not UART Fullset mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_fullset_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_FULL_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_uart_mand_mode +* DESCRIPTION +* Is stp use UART mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:Uart Mandatory mode, FALSE:Not UART Mandotary mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_uart_mand_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_UART_MAND_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_fullset_mode +* DESCRIPTION +* Is stp use BTIF fullset mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Fullset mode, FALSE:Not BTIF Fullset mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_btif_fullset_mode(void) +{ + + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_FULL_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_btif_mand_mode +* DESCRIPTION +* Is stp use BTIF mandatory mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:BTIF Mandatory mode, FALSE:Not BTIF Mandotary mode +*****************************************************************************/ + +MTK_WCN_BOOL mtk_wcn_stp_is_btif_mand_mode(void) +{ + + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_BTIF_MAND_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_sdio_mode +* DESCRIPTION +* Is stp use SDIO mode? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:SDIO mode, FALSE:UART mode +*****************************************************************************/ +MTK_WCN_BOOL mtk_wcn_stp_is_sdio_mode(void) +{ + /* + bit 0: uart fullset mode + bit 1: uart mandatory mode + bit 2: sdio mode + */ + if (STP_SUPPORT_PROTOCOL(stp_core_ctx) & MTKSTP_SDIO_MODE) + return MTK_WCN_BOOL_TRUE; + else + return MTK_WCN_BOOL_FALSE; +} + +/***************************************************************************** +* FUNCTION +* stp_send_inband_reset +* DESCRIPTION +* To sync to oringnal stp state with f/w stp +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +void mtk_wcn_stp_inband_reset(void) +{ + UINT8 inband_reset_packet[64]; + UINT32 txseq = 0; + UINT32 txack = 0; + UINT32 crc = 0; + UINT32 ret = 0; + UINT32 reset_payload_len = 0; + + /*512 bytes */ + UINT8 reset_payload[] = { + 0xc0, 0x01, 0xc0, 0xde, 0x3e, 0xd1, 0xa7, 0xef + }; + + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + + /*RESYNC*/ inband_reset_packet[0] = 0x7f; + inband_reset_packet[1] = 0x7f; + inband_reset_packet[2] = 0x7f; + inband_reset_packet[3] = 0x7f; + inband_reset_packet[4] = 0x7f; + inband_reset_packet[5] = 0x7f; + inband_reset_packet[6] = 0x7f; + inband_reset_packet[7] = 0x7f; + + /*header */ + reset_payload_len = sizeof(reset_payload) / sizeof(reset_payload[0]); + inband_reset_packet[8] = 0x80 + (txseq << 3) + txack; + inband_reset_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); + inband_reset_packet[10] = reset_payload_len & 0xff; + inband_reset_packet[11] = (inband_reset_packet[8] + inband_reset_packet[9] + inband_reset_packet[10]) & 0xff; + + /*payload */ + osal_memcpy(&inband_reset_packet[12], reset_payload, reset_payload_len); + + /*crc */ + crc = osal_crc16(&reset_payload[0], reset_payload_len); + inband_reset_packet[12 + reset_payload_len] = crc & 0xff; + inband_reset_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; + + (*sys_if_tx) (&inband_reset_packet[0], 14 + reset_payload_len, &ret); + + if (ret != (14 + reset_payload_len)) + STP_ERR_FUNC("Inband sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, ret); + + stp_core_ctx.inband_rst_set = 1; + stp_ctx_unlock(&stp_core_ctx); + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ +} + +void mtk_wcn_stp_debug_ctrl(INT32 op, INT32 filter, INT32 filter_param) +{ + /*nothing at now*/ +} + +void mtk_wcn_stp_test_cmd(INT32 cmd_no) +{ + UINT8 test_packet[64]; + UINT32 txseq = 0; + UINT32 txack = 0; + UINT32 crc = 0; + UINT32 ret = 0; + UINT32 reset_payload_len = 0; + + UINT8 test_payload[] = { + 0xAA, 0xAA, 0xC0, 0xDE, 0x3E, 0xD1, 0xA7, 0xEF + }; +/* */ +/* select your test command by cmd_no */ +/* */ + if (cmd_no == 0) { + /* to test new command to chip */ + /* osal_lock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_lock(&stp_core_ctx); + + /*RESYNC*/ test_packet[0] = 0x7f; + test_packet[1] = 0x7f; + test_packet[2] = 0x7f; + test_packet[3] = 0x7f; + test_packet[4] = 0x7f; + test_packet[5] = 0x7f; + test_packet[6] = 0x7f; + test_packet[7] = 0x7f; + + /*header */ + reset_payload_len = sizeof(test_payload) / sizeof(test_payload[0]); + test_packet[8] = 0x80 + (txseq << 3) + txack; + test_packet[9] = (STP_TASK_INDX << 4) + ((reset_payload_len & 0xf00) >> 8); + test_packet[10] = reset_payload_len & 0xff; + test_packet[11] = (test_packet[8] + test_packet[9] + test_packet[10]) & 0xff; + + /*payload */ + osal_memcpy(&test_packet[12], test_payload, reset_payload_len); + + /*crc */ + crc = osal_crc16(&test_payload[0], reset_payload_len); + test_packet[12 + reset_payload_len] = crc & 0xff; + test_packet[12 + reset_payload_len + 1] = (crc & 0xff00) >> 8; + + (*sys_if_tx) (&test_packet[0], 14 + reset_payload_len, &ret); + if (ret != (14 + reset_payload_len)) { + STP_ERR_FUNC("stp test sending error, sending %d , but ret = %d\n", 10 + reset_payload_len, + ret); + } + /* osal_unlock_unsleepable_lock(&stp_core_ctx.stp_mutex); */ + stp_ctx_unlock(&stp_core_ctx); + } + +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush_context +* DESCRIPTION +* Flush STP Context +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +void mtk_wcn_stp_flush_context(void) +{ + stp_rest_ctx_state(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_flush_rx_queue +* DESCRIPTION +* Flush STP Rx Queue +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ + +void mtk_wcn_stp_flush_rx_queue(UINT32 type) +{ + osal_lock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); + if (type < MTKSTP_MAX_TASK_NUM) { + stp_core_ctx.ring[type].read_p = 0; + stp_core_ctx.ring[type].write_p = 0; + } + osal_unlock_unsleepable_lock(&stp_core_ctx.ring[type].mtx); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* STP is ready? +* PARAMETERS +* none. +* RETURNS +* none +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_stp_is_ready(void) +#else +MTK_WCN_BOOL mtk_wcn_stp_is_ready(void) +#endif +{ + return STP_IS_READY(stp_core_ctx); +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_is_ready); +#endif +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ +#if STP_EXP_HID_API_EXPORT +void _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) +#else +void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL bluez_flag) +#endif +{ + /* g_mtkstp_bluez_flag = bluez_flag; */ + STP_SET_BT_STK(stp_core_ctx, bluez_flag); +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_set_bluez); +#endif +/***************************************************************************** +* FUNCTION +* set stp debugging mdoe +* DESCRIPTION +* set stp debugging mdoe +* PARAMETERS +* dbg_mode: switch to dbg mode ? +* RETURNS +* void +*****************************************************************************/ +void mtk_wcn_stp_set_dbg_mode(MTK_WCN_BOOL dbg_mode) +{ + STP_SET_ENABLE_DBG(stp_core_ctx, dbg_mode); +} + +/***************************************************************************** +* FUNCTION +* set stp auto reset mdoe +* DESCRIPTION +* set stp auto reset mdoe +* PARAMETERS +* auto_rst: switch to auto reset mode ? +* RETURNS +* void +*****************************************************************************/ +void mtk_wcn_stp_set_auto_rst(MTK_WCN_BOOL auto_rst) +{ + STP_SET_ENABLE_RST(stp_core_ctx, auto_rst); +} + +INT32 mtk_wcn_stp_notify_sleep_for_thermal(void) +{ + return stp_psm_sleep_for_thermal(STP_PSM_CORE(stp_core_ctx)); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_open_btif +* DESCRIPTION +* init btif hw & sw by owner stp +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_open_btif(VOID) +{ + return mtk_wcn_consys_stp_btif_open(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_open_close +* DESCRIPTION +* close btif hw & sw by owner stp +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_close_btif(VOID) +{ + return mtk_wcn_consys_stp_btif_close(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_rx_cb_register +* DESCRIPTION +* register stp rx cb to btif +* PARAMETERS +* MTK_WCN_BTIF_RX_CB stp rx handle function +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_rxcb_register(MTK_WCN_BTIF_RX_CB rx_cb) +{ + return mtk_wcn_consys_stp_btif_rx_cb_register(rx_cb); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_tx +* DESCRIPTION +* send stp package by btif +* PARAMETERS +* pBuf:package buffer pointer,len:package length +* written_len:package written length +* RETURNS +* INT32 package length-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_tx(UINT8 *pBuf, UINT32 len, UINT32 *written_len) +{ + INT32 iRet = -1; + + iRet = mtk_wcn_consys_stp_btif_tx(pBuf, len, written_len); + return iRet; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_wakeup_consys +* DESCRIPTION +* STP wakeup consys by btif +* PARAMETERS +* VOID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_wakeup_consys(VOID) +{ + /*log wakeup int for debug */ + stp_dbg_pkt_log(7, 0, 0, 0, PKT_DIR_TX, NULL, 0); + return mtk_wcn_consys_stp_btif_wakeup(); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_dpidle_ctrl +* DESCRIPTION +* decide AP enter or exit deep idle +* PARAMETERS +* en_flag:1,enter,0,exit +* RETURNS +* always 0 +*****************************************************************************/ +INT32 mtk_wcn_stp_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag) +{ + mtk_wcn_consys_stp_btif_dpidle_ctrl(en_flag); + + return 0; +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_lpbk_ctrl +* DESCRIPTION +* enable stp internal lpbk test or not +* PARAMETERS +* mode:1,enable,0,disabel +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode) +{ + return mtk_wcn_consys_stp_btif_lpbk_ctrl(mode); +} + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_logger_ctrl +* DESCRIPTION +* dump btif buffer or register status when No ACK or assert occurs +* PARAMETERS +* flag:see enum value in ENUM_BTIF_DBG_ID +* RETURNS +* INT32 0-success,other fail. +*****************************************************************************/ +INT32 mtk_wcn_stp_logger_ctrl(ENUM_BTIF_DBG_ID flag) +{ + return mtk_wcn_consys_stp_btif_logger_ctrl(flag); +} + +VOID mtk_wcn_stp_ctx_save(void) +{ + STP_INFO_FUNC("start ++\n"); + mtk_wcn_stp_coredump_start_ctrl(1); + stp_psm_set_sleep_disable(stp_core_ctx.psm); + STP_INFO_FUNC("exit --\n"); +} + +VOID mtk_wcn_stp_ctx_restore(void) +{ + STP_INFO_FUNC("start ++\n"); + stp_psm_set_sleep_enable(stp_core_ctx.psm); + stp_btm_reset_btm_wq(STP_BTM_CORE(stp_core_ctx)); + + if (STP_IS_ENABLE_RST(stp_core_ctx)) + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + else + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); +#if STP_RETRY_OPTIMIZE + g_retry_times = 0; +#endif + STP_INFO_FUNC("exit --\n"); +} + +INT32 mtk_wcn_stp_wmt_evt_err_trg_assert(void) +{ + INT32 ret = -1; + + if (mtk_wcn_stp_coredump_start_get() != 0) { + STP_INFO_FUNC("firmware assert has been triggered\n"); + return 0; + } + + ret = stp_notify_btm_do_fw_assert_via_emi(STP_BTM_CORE(stp_core_ctx)); + if (ret) { + STP_ERR_FUNC("evt err trigger assert fail,do chip reset to recovery\n"); + + mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); + if (STP_IS_ENABLE_RST(stp_core_ctx)) + stp_btm_notify_wmt_rst_wq(STP_BTM_CORE(stp_core_ctx)); + else + STP_INFO_FUNC("No to launch whole chip reset! for debugging purpose\n"); + } + + return ret; +} + +VOID mtk_wcn_stp_set_wmt_evt_err_trg_assert(UINT32 value) +{ + STP_INFO_FUNC("set evt err tigger assert flag to %d\n", value); + STP_SET_EVT_ERR_ASSERT(stp_core_ctx, value); +} + +UINT32 mtk_wcn_stp_get_wmt_evt_err_trg_assert(void) +{ + return STP_EVT_ERR_ASSERT(stp_core_ctx); +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c new file mode 100644 index 0000000000000..3009bd26df41a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_conf.c @@ -0,0 +1,529 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CONF]" + +#include "osal_typedef.h" +/* #include "osal.h" */ +#include "wmt_lib.h" +#include "wmt_dev.h" +#include "wmt_conf.h" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +struct parse_data { + PINT8 name; + INT32 (*parser)(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 value); + PINT8 (*writer)(P_DEV_WMT pWmtDev, const struct parse_data *data); + /*PINT8 param1, *param2, *param3; */ + /* TODO:[FixMe][George] CLARIFY WHAT SHOULD BE USED HERE!!! */ + PINT8 param1; + PINT8 param2; + PINT8 param3; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ +static INT32 wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos); + +static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data); + +static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 pVal); + +static INT32 wmt_conf_parse(P_DEV_WMT pWmtDev, const PINT8 pInBuf, UINT32 size); + +#define OFFSET(v) ((void *) &((P_DEV_WMT) 0)->v) + +#define CHAR(f) \ +{ \ + #f, \ + wmt_conf_parse_char, \ + wmt_conf_write_char, \ + OFFSET(rWmtGenConf.f), \ + NULL, \ + NULL \ +} +/* #define CHAR(f) _CHAR(f), NULL, NULL} */ + +#define SHORT(f) \ +{ \ + #f, \ + wmt_conf_parse_short, \ + wmt_conf_write_short, \ + OFFSET(rWmtGenConf.f), \ + NULL, \ + NULL \ +} +/* #define SHORT(f) _SHORT(f), NULL, NULL */ + +#define INT(f) \ +{ \ + #f, \ + wmt_conf_parse_int, \ + wmt_conf_write_int, \ + OFFSET(rWmtGenConf.f), \ + NULL, \ + NULL \ +} +/* #define INT(f) _INT(f), NULL, NULL */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static const struct parse_data wmtcfg_fields[] = { + CHAR(coex_wmt_ant_mode), + CHAR(coex_wmt_ext_component), + CHAR(coex_wmt_wifi_time_ctl), + CHAR(coex_wmt_ext_pta_dev_on), + CHAR(coex_wmt_filter_mode), + + CHAR(coex_bt_rssi_upper_limit), + CHAR(coex_bt_rssi_mid_limit), + CHAR(coex_bt_rssi_lower_limit), + CHAR(coex_bt_pwr_high), + CHAR(coex_bt_pwr_mid), + CHAR(coex_bt_pwr_low), + + CHAR(coex_wifi_rssi_upper_limit), + CHAR(coex_wifi_rssi_mid_limit), + CHAR(coex_wifi_rssi_lower_limit), + CHAR(coex_wifi_pwr_high), + CHAR(coex_wifi_pwr_mid), + CHAR(coex_wifi_pwr_low), + + CHAR(coex_ext_pta_hi_tx_tag), + CHAR(coex_ext_pta_hi_rx_tag), + CHAR(coex_ext_pta_lo_tx_tag), + CHAR(coex_ext_pta_lo_rx_tag), + SHORT(coex_ext_pta_sample_t1), + SHORT(coex_ext_pta_sample_t2), + CHAR(coex_ext_pta_wifi_bt_con_trx), + + INT(coex_misc_ext_pta_on), + INT(coex_misc_ext_feature_set), + + CHAR(wmt_gps_lna_pin), + CHAR(wmt_gps_lna_enable), + + CHAR(pwr_on_rtc_slot), + CHAR(pwr_on_ldo_slot), + CHAR(pwr_on_rst_slot), + CHAR(pwr_on_off_slot), + CHAR(pwr_on_on_slot), + CHAR(co_clock_flag), + + INT(sdio_driving_cfg), + +}; + +#define NUM_WMTCFG_FIELDS (osal_sizeof(wmtcfg_fields) / osal_sizeof(wmtcfg_fields[0])) + +static int wmt_conf_parse_char(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PINT8 dst; + long res; + int ret; + + dst = (PINT8) (((PUINT8) pWmtDev) + (long)data->param1); + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + ret = osal_strtol(pos + 2, 16, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + ret = osal_strtol(pos, 10, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + return 0; +} + +static PINT8 wmt_conf_write_char(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT8 src; + INT32 res; + PINT8 value; + + src = (PINT8) (((PUINT8) pWmtDev) + (long)data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static int wmt_conf_parse_short(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PUINT16 dst; + long res; + int ret; + + dst = (PINT16) (((PUINT8) pWmtDev) + (long)data->param1); + + /* WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); */ + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + ret = osal_strtol(pos + 2, 16, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + ret = osal_strtol(pos, 10, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PINT8 wmt_conf_write_short(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT16 src; + INT32 res; + PINT8 value; + + /* TODO: [FixMe][George] FIX COMPILE WARNING HERE! */ + src = (PINT16) (((PUINT8) pWmtDev) + (long)data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static int wmt_conf_parse_int(P_DEV_WMT pWmtDev, const struct parse_data *data, const PINT8 pos) +{ + PUINT32 dst; + long res; + int ret; + + dst = (PINT32) (((PUINT8) pWmtDev) + (long)data->param1); + + /* WMT_INFO_FUNC(">strlen(pos)=%d\n", strlen(pos)); */ + + if ((osal_strlen(pos) > 2) && ((*pos) == '0') && (*(pos + 1) == 'x')) { + ret = osal_strtol(pos + 2, 16, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=0x%x\n", data->name, *dst); + } else { + ret = osal_strtol(pos, 10, &res); + if (ret) + WMT_ERR_FUNC("fail(%d)\n", ret); + *dst = res; + WMT_DBG_FUNC("wmtcfg==> %s=%d\n", data->name, *dst); + } + + return 0; +} + +static PINT8 wmt_conf_write_int(P_DEV_WMT pWmtDev, const struct parse_data *data) +{ + PINT32 src; + INT32 res; + PINT8 value; + + src = (PUINT32) (((PUINT8) pWmtDev) + (long)data->param1); + + value = osal_malloc(20); + if (value == NULL) + return NULL; + res = osal_snprintf(value, 20, "0x%x", *src); + if (res < 0 || res >= 20) { + osal_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} + +static INT32 wmt_conf_parse_pair(P_DEV_WMT pWmtDev, const PINT8 pKey, const PINT8 pVal) +{ + int i = 0; + int ret = 0; + + /* WMT_INFO_FUNC( DBG_NAME "cfg(%s) val(%s)\n", pKey, pVal); */ + + for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { + const struct parse_data *field = &wmtcfg_fields[i]; + + if (osal_strcmp(pKey, field->name) != 0) + continue; + if (field->parser(pWmtDev, field, pVal)) { + WMT_ERR_FUNC("failed to parse %s '%s'.\n", pKey, pVal); + ret = -1; + } + break; + } + if (i == NUM_WMTCFG_FIELDS) { + WMT_ERR_FUNC("unknown field '%s'.\n", pKey); + ret = -1; + } + + return ret; +} + +static INT32 wmt_conf_parse(P_DEV_WMT pWmtDev, const PINT8 pInBuf, UINT32 size) +{ + PINT8 pch; + PINT8 pBuf; + PINT8 pLine; + PINT8 pKey; + PINT8 pVal; + PINT8 pPos; + INT32 ret = 0; + INT32 i = 0; + PINT8 pa = NULL; + + pBuf = osal_malloc(size); + if (!pBuf) + return -1; + + osal_memcpy(pBuf, pInBuf, size); + pBuf[size] = '\0'; + + pch = pBuf; + /* pch is to be updated by strsep(). Keep pBuf unchanged!! */ + +#if 0 + { + PINT8 buf_ptr = pBuf; + INT32 k = 0; + + WMT_INFO_FUNC("%s len=%d", "wmcfg.content:", size); + for (k = 0; k < size; k++) { + /* if(k%16 == 0) WMT_INFO_FUNC("\n"); */ + WMT_INFO_FUNC("%c", buf_ptr[k]); + } + WMT_INFO_FUNC("--end\n"); + } +#endif + + while ((pLine = osal_strsep(&pch, "\r\n")) != NULL) { + /* pch is updated to the end of pLine by strsep() and updated to '\0' */ + /*WMT_INFO_FUNC("strsep offset(%d), char(%d, '%c' )\n", pLine-pBuf, *pLine, *pLine); */ + /* parse each line */ + + /* WMT_INFO_FUNC("==> Line = (%s)\n", pLine); */ + + if (!*pLine) + continue; + + pVal = osal_strchr(pLine, '='); + if (!pVal) { + WMT_WARN_FUNC("mal-format cfg string(%s)\n", pLine); + continue; + } + + /* |<-pLine->|'='<-pVal->|'\n' ('\0')| */ + *pVal = '\0'; /* replace '=' with '\0' to get key */ + /* |<-pKey->|'\0'|<-pVal->|'\n' ('\0')| */ + pKey = pLine; + + if ((pVal - pBuf) < size) + pVal++; + + /*key handling */ + pPos = pKey; + /*skip space characeter */ + while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*key head */ + pKey = pPos; + while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') && ((*pPos) != '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*key tail */ + (*pPos) = '\0'; + + /*value handling */ + pPos = pVal; + /*skip space characeter */ + while (((*pPos) == ' ') || ((*pPos) == '\t') || ((*pPos) == '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*value head */ + pVal = pPos; + while (((*pPos) != ' ') && ((*pPos) != '\t') && ((*pPos) != '\0') && ((*pPos) != '\n')) { + if ((pPos - pBuf) >= size) + break; + pPos++; + } + /*value tail */ + (*pPos) = '\0'; + + /* WMT_DBG_FUNC("parse (key: #%s#, value: #%s#)\n", pKey, pVal); */ + ret = wmt_conf_parse_pair(pWmtDev, pKey, pVal); + WMT_DBG_FUNC("parse (%s, %s, %d)\n", pKey, pVal, ret); + if (ret) + WMT_WARN_FUNC("parse fail (%s, %s, %d)\n", pKey, pVal, ret); + } + + for (i = 0; i < NUM_WMTCFG_FIELDS; i++) { + const struct parse_data *field = &wmtcfg_fields[i]; + + pa = field->writer(pWmtDev, field); + if (pa) { + WMT_DBG_FUNC("#%d(%s)=>%s\n", i, field->name, pa); + osal_free(pa); + } else { + WMT_ERR_FUNC("failed to parse '%s'.\n", field->name); + } + } + osal_free(pBuf); + return 0; +} + +INT32 wmt_conf_set_cfg_file(const char *name) +{ + if (NULL == name) { + WMT_ERR_FUNC("name is NULL\n"); + return -1; + } + if (osal_strlen(name) >= osal_sizeof(gDevWmt.cWmtcfgName)) { + WMT_ERR_FUNC("name is too long, length=%d, expect to < %d\n", osal_strlen(name), + osal_sizeof(gDevWmt.cWmtcfgName)); + return -2; + } + osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); + osal_strcpy(&(gDevWmt.cWmtcfgName[0]), name); + WMT_ERR_FUNC("WMT config file is set to (%s)\n", &(gDevWmt.cWmtcfgName[0])); + + return 0; +} + +INT32 wmt_conf_read_file(VOID) +{ + INT32 ret = -1; + + osal_memset(&gDevWmt.rWmtGenConf, 0, osal_sizeof(gDevWmt.rWmtGenConf)); + osal_memset(&gDevWmt.pWmtCfg, 0, osal_sizeof(gDevWmt.pWmtCfg)); + +#if 1 + osal_memset(&gDevWmt.cWmtcfgName[0], 0, osal_sizeof(gDevWmt.cWmtcfgName)); + + osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT_PREFIX, osal_sizeof(CUST_CFG_WMT_PREFIX)); + osal_strncat(&(gDevWmt.cWmtcfgName[0]), CUST_CFG_WMT, osal_sizeof(CUST_CFG_WMT)); +#endif + + if (!osal_strlen(&(gDevWmt.cWmtcfgName[0]))) { + WMT_ERR_FUNC("empty Wmtcfg name\n"); + osal_assert(0); + return ret; + } + WMT_DBG_FUNC("WMT config file:%s\n", &(gDevWmt.cWmtcfgName[0])); + if (0 == wmt_dev_patch_get(&gDevWmt.cWmtcfgName[0], (osal_firmware **) &gDevWmt.pWmtCfg, 0)) { + /*get full name patch success */ + WMT_DBG_FUNC("get full file name(%s) buf(0x%p) size(%d)\n", + &gDevWmt.cWmtcfgName[0], gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size); + + if (0 == wmt_conf_parse(&gDevWmt, (const PINT8)gDevWmt.pWmtCfg->data, gDevWmt.pWmtCfg->size)) { + /*config file exists */ + gDevWmt.rWmtGenConf.cfgExist = 1; + + WMT_DBG_FUNC("&gDevWmt.rWmtGenConf=%p\n", &gDevWmt.rWmtGenConf); + ret = 0; + } else { + WMT_ERR_FUNC("wmt conf parsing fail\n"); + osal_assert(0); + ret = -1; + } + wmt_dev_patch_put((osal_firmware **) &gDevWmt.pWmtCfg); +/* + if (gDevWmt.pWmtCfg) + { + if (gDevWmt.pWmtCfg->data) + { + osal_free(gDevWmt.pWmtCfg->data); + } + osal_free(gDevWmt.pWmtCfg); + gDevWmt.pWmtCfg = 0; + } +*/ + return ret; + } + WMT_ERR_FUNC("read %s file fails\n", &(gDevWmt.cWmtcfgName[0])); + osal_assert(0); + + gDevWmt.rWmtGenConf.cfgExist = 0; + return ret; +} + +P_WMT_GEN_CONF wmt_conf_get_cfg(VOID) +{ + if (0 == gDevWmt.rWmtGenConf.cfgExist) + return NULL; + + return &gDevWmt.rWmtGenConf; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c new file mode 100644 index 0000000000000..cca6729d53a07 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_core.c @@ -0,0 +1,2521 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CORE]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_lib.h" +#include "wmt_core.h" +#include "wmt_ctrl.h" +#include "wmt_ic.h" +#include "wmt_conf.h" + +#include "wmt_func.h" +#include "stp_core.h" +#include "psm_core.h" + + +P_WMT_FUNC_OPS gpWmtFuncOps[4] = { +#if CFG_FUNC_BT_SUPPORT + [0] = &wmt_func_bt_ops, +#else + [0] = NULL, +#endif + +#if CFG_FUNC_FM_SUPPORT + [1] = &wmt_func_fm_ops, +#else + [1] = NULL, +#endif + +#if CFG_FUNC_GPS_SUPPORT + [2] = &wmt_func_gps_ops, +#else + [2] = NULL, +#endif + +#if CFG_FUNC_WIFI_SUPPORT + [3] = &wmt_func_wifi_ops, +#else + [3] = NULL, +#endif + +}; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* TODO:[FixMe][GeorgeKuo]: is it an MT6620 only or general general setting? +*move to wmt_ic_6620 temporarily. +*/ +/* BT Port 2 Feature. */ +/* #define CFG_WMT_BT_PORT2 (1) */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +static WMT_CTX gMtkWmtCtx; +static UINT8 gLpbkBuf[1024+5] = { 0 }; +#ifdef CONFIG_MTK_COMBO_ANT +static UINT8 gAntBuf[1024] = { 0 }; +#define CFG_CHECK_WMT_RESULT (1) +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp); +static INT32 opfunc_func_on(P_WMT_OP pWmtOp); +static INT32 opfunc_func_off(P_WMT_OP pWmtOp); +static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp); +static INT32 opfunc_exit(P_WMT_OP pWmtOp); +static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp); +static INT32 opfunc_dsns(P_WMT_OP pWmtOp); +static INT32 opfunc_lpbk(P_WMT_OP pWmtOp); +static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp); +static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp); +static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp); +static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_gpio_ctrl(P_WMT_OP pWmtOp); +static INT32 opfunc_pin_state(P_WMT_OP pWmtOp); +static INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp); +static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp); +static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp); +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp); +#endif +#ifdef CONFIG_MTK_COMBO_ANT +static INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp); +static INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp); +#endif +static VOID wmt_core_dump_func_state(PINT8 pSource); +static INT32 wmt_core_stp_init(VOID); +static INT32 wmt_core_stp_deinit(VOID); +static INT32 wmt_core_hw_check(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static const UINT8 WMT_SLEEP_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x01 }; +static const UINT8 WMT_SLEEP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; + +static const UINT8 WMT_HOST_AWAKE_CMD[] = { 0x01, 0x03, 0x01, 0x00, 0x02 }; +static const UINT8 WMT_HOST_AWAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; + +static const UINT8 WMT_WAKEUP_CMD[] = { 0xFF }; +static const UINT8 WMT_WAKEUP_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; + +static UINT8 WMT_THERM_CMD[] = { 0x01, 0x11, 0x01, 0x00, + 0x00 /*thermal sensor operation */ +}; +static UINT8 WMT_THERM_CTRL_EVT[] = { 0x02, 0x11, 0x01, 0x00, 0x00 }; +static UINT8 WMT_THERM_READ_EVT[] = { 0x02, 0x11, 0x02, 0x00, 0x00, 0x00 }; + +static UINT8 WMT_EFUSE_CMD[] = { 0x01, 0x0D, 0x08, 0x00, + 0x01, /*[4]operation, 0:init, 1:write 2:read */ + 0x01, /*[5]Number of register setting */ + 0xAA, 0xAA, /*[6-7]Address */ + 0xBB, 0xBB, 0xBB, 0xBB /*[8-11] Value */ +}; + +static UINT8 WMT_EFUSE_EVT[] = { 0x02, 0x0D, 0x08, 0x00, + 0xAA, /*[4]operation, 0:init, 1:write 2:read */ + 0xBB, /*[5]Number of register setting */ + 0xCC, 0xCC, /*[6-7]Address */ + 0xDD, 0xDD, 0xDD, 0xDD /*[8-11] Value */ +}; + +static UINT8 WMT_DSNS_CMD[] = { 0x01, 0x0E, 0x02, 0x00, 0x01, + 0x00 /*desnse type */ +}; +static UINT8 WMT_DSNS_EVT[] = { 0x02, 0x0E, 0x01, 0x00, 0x00 }; + +/* TODO:[NewFeature][GeorgeKuo] Update register group in ONE CMD/EVT */ +static UINT8 WMT_SET_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x00 /*op: w(1) & r(2) */ + , 0x01 /*type: reg */ + , 0x00 /*res */ + , 0x01 /*1 register */ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ + , 0xFF, 0xFF, 0xFF, 0xFF /*mask */ +}; + +static UINT8 WMT_SET_REG_WR_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 register */ + /* , 0x00, 0x00, 0x00, 0x00 */ /* addr */ + /* , 0x00, 0x00, 0x00, 0x00 */ /* value */ +}; + +static UINT8 WMT_SET_REG_RD_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 register */ + , 0x00, 0x00, 0x00, 0x00 /* addr */ + , 0x00, 0x00, 0x00, 0x00 /* value */ +}; + +#ifdef CONFIG_MTK_COMBO_ANT +static UINT8 WMT_ANT_RAM_STA_GET_CMD[] = { 0x01, 0x06, 0x02, 0x00, 0x05, 0x02 +}; + +static UINT8 WMT_ANT_RAM_STA_GET_EVT[] = { 0x02, 0x06, 0x03, 0x00 /*length */ + , 0x05, 0x02, 0x00 /*S: result */ +}; + +static UINT8 WMT_ANT_RAM_DWN_CMD[] = { 0x01, 0x15, 0x00, 0x00, 0x01 +}; + +static UINT8 WMT_ANT_RAM_DWN_EVT[] = { 0x02, 0x15, 0x01, 0x00 /*length */ + , 0x00 +}; +#endif + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ + +static const WMT_OPID_FUNC wmt_core_opfunc[] = { + [WMT_OPID_HIF_CONF] = opfunc_hif_conf, + [WMT_OPID_PWR_ON] = opfunc_pwr_on, + [WMT_OPID_PWR_OFF] = opfunc_pwr_off, + [WMT_OPID_FUNC_ON] = opfunc_func_on, + [WMT_OPID_FUNC_OFF] = opfunc_func_off, + [WMT_OPID_REG_RW] = opfunc_reg_rw, /* TODO:[ChangeFeature][George] is this OP obsoleted? */ + [WMT_OPID_EXIT] = opfunc_exit, + [WMT_OPID_PWR_SV] = opfunc_pwr_sv, + [WMT_OPID_DSNS] = opfunc_dsns, + [WMT_OPID_LPBK] = opfunc_lpbk, + [WMT_OPID_CMD_TEST] = opfunc_cmd_test, + [WMT_OPID_HW_RST] = opfunc_hw_rst, + [WMT_OPID_SW_RST] = opfunc_sw_rst, + [WMT_OPID_STP_RST] = opfunc_stp_rst, + [WMT_OPID_THERM_CTRL] = opfunc_therm_ctrl, + [WMT_OPID_EFUSE_RW] = opfunc_efuse_rw, + [WMT_OPID_GPIO_CTRL] = opfunc_gpio_ctrl, + [WMT_OPID_GPIO_STATE] = opfunc_pin_state, + [WMT_OPID_BGW_DS] = opfunc_bgw_ds, + [WMT_OPID_SET_MCU_CLK] = opfunc_set_mcu_clk, + [WMT_OPID_ADIE_LPBK_TEST] = opfunc_adie_lpbk_test, +#if CFG_WMT_LTE_COEX_HANDLING + [WMT_OPID_IDC_MSG_HANDLING] = opfunc_idc_msg_handling, +#endif +#ifdef CONFIG_MTK_COMBO_ANT + [WMT_OPID_ANT_RAM_DOWN] = opfunc_ant_ram_down, + [WMT_OPID_ANT_RAM_STA_GET] = opfunc_ant_ram_stat_get, +#endif +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_core_init(VOID) +{ + INT32 i = 0; + + osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); + /* gMtkWmtCtx.p_ops is cleared to NULL */ + + /* default FUNC_OFF state */ + for (i = 0; i < WMTDRV_TYPE_MAX; ++i) { + /* WinMo is default to DRV_STS_UNREG; */ + gMtkWmtCtx.eDrvStatus[i] = DRV_STS_POWER_OFF; + } + + return 0; +} + +INT32 wmt_core_deinit(VOID) +{ + /* return to init state */ + osal_memset(&gMtkWmtCtx, 0, osal_sizeof(gMtkWmtCtx)); + /* gMtkWmtCtx.p_ops is cleared to NULL */ + return 0; +} + +/* TODO: [ChangeFeature][George] Is wmt_ctrl a good interface? maybe not...... */ +/* parameters shall be copied in/from ctrl buffer, which is also a size-wasting buffer. */ +INT32 wmt_core_tx(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) +{ + INT32 iRet; +#if 0 /* Test using direct function call instead of wmt_ctrl() interface */ + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_TX; + ctrlData.au4CtrlData[0] = (UINT32) pData; + ctrlData.au4CtrlData[1] = size; + ctrlData.au4CtrlData[2] = (UINT32) writtenSize; + ctrlData.au4CtrlData[3] = bRawFlag; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_TX, iRet:%d\n", iRet); + /* (*sys_dbg_assert)(0, __FILE__, __LINE__); */ + osal_assert(0); + } +#endif + iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); + if (0 == *writtenSize) { + INT32 retry_times = 0; + INT32 max_retry_times = 3; + INT32 retry_delay_ms = 360; + + WMT_WARN_FUNC("WMT-CORE: wmt_ctrl_tx_ex failed and written ret:%d, maybe no winspace in STP layer\n", + *writtenSize); + while ((0 == *writtenSize) && (retry_times < max_retry_times)) { + WMT_ERR_FUNC("WMT-CORE: retrying, wait for %d ms\n", retry_delay_ms); + osal_sleep_ms(retry_delay_ms); + + iRet = wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); + retry_times++; + } + } + return iRet; +} + +INT32 wmt_core_rx(PUINT8 pBuf, UINT32 bufLen, UINT32 *readSize) +{ + INT32 iRet; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_RX; + ctrlData.au4CtrlData[0] = (SIZE_T) pBuf; + ctrlData.au4CtrlData[1] = bufLen; + ctrlData.au4CtrlData[2] = (SIZE_T) readSize; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX, iRet:%d\n", iRet); + mtk_wcn_stp_dbg_dump_package(); + osal_assert(0); + } + return iRet; +} + +INT32 wmt_core_rx_flush(UINT32 type) +{ + INT32 iRet; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_RX_FLUSH; + ctrlData.au4CtrlData[0] = (UINT32) type; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: WMT_CTRL_RX_FLUSH, iRet:%d\n", iRet); + osal_assert(0); + } + return iRet; +} + +INT32 wmt_core_func_ctrl_cmd(ENUM_WMTDRV_TYPE_T type, MTK_WCN_BOOL fgEn) +{ + INT32 iRet = 0; + UINT32 u4WmtCmdPduLen; + UINT32 u4WmtEventPduLen; + UINT32 u4ReadSize; + UINT32 u4WrittenSize; + WMT_PKT rWmtPktCmd; + WMT_PKT rWmtPktEvent; + MTK_WCN_BOOL fgFail; + + /* TODO:[ChangeFeature][George] remove WMT_PKT. replace it with hardcoded arrays. */ + /* Using this struct relies on compiler's implementation and pack() settings */ + osal_memset(&rWmtPktCmd, 0, osal_sizeof(rWmtPktCmd)); + osal_memset(&rWmtPktEvent, 0, osal_sizeof(rWmtPktEvent)); + + rWmtPktCmd.eType = (UINT8) PKT_TYPE_CMD; + rWmtPktCmd.eOpCode = (UINT8) OPCODE_FUNC_CTRL; + + /* Flag field: driver type */ + rWmtPktCmd.aucParam[0] = (UINT8) type; + /* Parameter field: ON/OFF */ + rWmtPktCmd.aucParam[1] = (fgEn == WMT_FUNC_CTRL_ON) ? 1 : 0; + rWmtPktCmd.u2SduLen = WMT_FLAG_LEN + WMT_FUNC_CTRL_PARAM_LEN; /* (2) */ + + /* WMT Header + WMT SDU */ + u4WmtCmdPduLen = WMT_HDR_LEN + rWmtPktCmd.u2SduLen; /* (6) */ + u4WmtEventPduLen = WMT_HDR_LEN + WMT_STS_LEN; /* (5) */ + + do { + fgFail = MTK_WCN_BOOL_TRUE; +/* iRet = (*kal_stp_tx)((PUINT8)&rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize); */ + iRet = wmt_core_tx((PUINT8) &rWmtPktCmd, u4WmtCmdPduLen, &u4WrittenSize, MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_tx failed\n"); + break; + } + + iRet = wmt_core_rx((PUINT8) &rWmtPktEvent, u4WmtEventPduLen, &u4ReadSize); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd kal_stp_rx failed\n"); + break; + } + + /* Error Checking */ + if (PKT_TYPE_EVENT != rWmtPktEvent.eType) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd PKT_TYPE_EVENT != rWmtPktEvent.eType %d\n", + rWmtPktEvent.eType); + break; + } + + if (rWmtPktCmd.eOpCode != rWmtPktEvent.eOpCode) { + WMT_ERR_FUNC + ("WMT-CORE: wmt_func_ctrl_cmd rWmtPktCmd.eOpCode(0x%x) != rWmtPktEvent.eType(0x%x)\n", + rWmtPktCmd.eOpCode, rWmtPktEvent.eOpCode); + break; + } + + if (u4WmtEventPduLen != (rWmtPktEvent.u2SduLen + WMT_HDR_LEN)) { + WMT_ERR_FUNC + ("WMT-CORE: wmt_func_ctrl_cmd u4WmtEventPduLen(0x%x) != rWmtPktEvent.u2SduLen(0x%x)+4\n", + u4WmtEventPduLen, rWmtPktEvent.u2SduLen); + break; + } + /* Status field of event check */ + if (0 != rWmtPktEvent.aucParam[0]) { + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd, 0 != status(%d)\n", rWmtPktEvent.aucParam[0]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + } while (0); + + if (MTK_WCN_BOOL_FALSE == fgFail) { + /* WMT_INFO_FUNC("WMT-CORE: wmt_func_ctrl_cmd OK!\n"); */ + return 0; + } + WMT_ERR_FUNC("WMT-CORE: wmt_func_ctrl_cmd 0x%x FAIL\n", rWmtPktCmd.aucParam[0]); + return -3; +} + +INT32 wmt_core_opid_handler(P_WMT_OP pWmtOp) +{ + UINT32 opId; + INT32 ret; + + opId = pWmtOp->opId; + + if (wmt_core_opfunc[opId]) { + ret = (*(wmt_core_opfunc[opId])) (pWmtOp); /*wmtCoreOpidHandlerPack[].opHandler */ + return ret; + } + WMT_ERR_FUNC("WMT-CORE: null handler (%d)\n", pWmtOp->opId); + return -2; + +} + +INT32 wmt_core_opid(P_WMT_OP pWmtOp) +{ + + /*sanity check */ + if (NULL == pWmtOp) { + WMT_ERR_FUNC("null pWmtOP\n"); + /*print some message with error info */ + return -1; + } + + if (WMT_OPID_MAX <= pWmtOp->opId) { + WMT_ERR_FUNC("WMT-CORE: invalid OPID(%d)\n", pWmtOp->opId); + return -2; + } + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + return wmt_core_opid_handler(pWmtOp); +} + +INT32 wmt_core_ctrl(ENUM_WMT_CTRL_T ctrId, unsigned long *pPa1, unsigned long *pPa2) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + SIZE_T val1 = (pPa1) ? *pPa1 : 0; + SIZE_T val2 = (pPa2) ? *pPa2 : 0; + + ctrlData.ctrlId = (SIZE_T) ctrId; + ctrlData.au4CtrlData[0] = val1; + ctrlData.au4CtrlData[1] = val2; + + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /* ERROR */ + WMT_ERR_FUNC("WMT-CORE: wmt_core_ctrl failed: id(%d), type(%d), value(%d) iRet:(%d)\n", ctrId, val1, + val2, iRet); + osal_assert(0); + } else { + if (pPa1) + *pPa1 = ctrlData.au4CtrlData[0]; + if (pPa2) + *pPa2 = ctrlData.au4CtrlData[1]; + } + return iRet; +} + +VOID wmt_core_dump_data(PUINT8 pData, PUINT8 pTitle, UINT32 len) +{ + PUINT8 ptr = pData; + INT32 k = 0; + + WMT_INFO_FUNC("%s len=%d\n", pTitle, len); + for (k = 0; k < len; k++) { + if (k % 16 == 0) + WMT_INFO_FUNC("\n"); + WMT_INFO_FUNC("0x%02x ", *ptr); + ptr++; + } + WMT_INFO_FUNC("--end\n"); +} + +/*! + * \brief An WMT-CORE function to support read, write, and read after write to + * an internal register. + * + * Detailed description. + * + * \param isWrite 1 for write, 0 for read + * \param offset of register to be written or read + * \param pVal a pointer to the 32-bit value to be writtern or read + * \param mask a 32-bit mask to be applied for the read or write operation + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval -2 tx cmd fail + * \retval -3 rx event fail + * \retval -4 read check error + */ +INT32 wmt_core_reg_rw_raw(UINT32 isWrite, UINT32 offset, PUINT32 pVal, UINT32 mask) +{ + INT32 iRet; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + WMT_SET_REG_CMD[4] = (isWrite) ? 0x1 : 0x2; /* w:1, r:2 */ + osal_memcpy(&WMT_SET_REG_CMD[8], &offset, 4); /* offset */ + osal_memcpy(&WMT_SET_REG_CMD[12], pVal, 4); /* [2] is var addr */ + osal_memcpy(&WMT_SET_REG_CMD[16], &mask, 4); /* mask */ + + /* send command */ + iRet = wmt_core_tx(WMT_SET_REG_CMD, sizeof(WMT_SET_REG_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if ((iRet) || (u4Res != sizeof(WMT_SET_REG_CMD))) { + WMT_ERR_FUNC("Tx REG_CMD fail!(%d) len (%d, %d)\n", iRet, u4Res, sizeof(WMT_SET_REG_CMD)); + return -2; + } + + /* receive event */ + evtLen = (isWrite) ? sizeof(WMT_SET_REG_WR_EVT) : sizeof(WMT_SET_REG_RD_EVT); + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if ((iRet) || (u4Res != evtLen)) { + WMT_ERR_FUNC("Rx REG_EVT fail!(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + return -3; + } + + if (!isWrite) { + UINT32 rxEvtAddr; + UINT32 txCmdAddr; + + osal_memcpy(&txCmdAddr, &WMT_SET_REG_CMD[8], 4); + osal_memcpy(&rxEvtAddr, &evtBuf[8], 4); + + /* check read result */ + if (txCmdAddr != rxEvtAddr) { + WMT_ERR_FUNC("Check read addr fail (0x%08x, 0x%08x)\n", rxEvtAddr, txCmdAddr); + return -4; + } + WMT_DBG_FUNC("Check read addr(0x%08x) ok\n", rxEvtAddr); + + osal_memcpy(pVal, &evtBuf[12], 4); + } + + /* no error here just return 0 */ + return 0; +} + +INT32 wmt_core_init_script(struct init_script *script, INT32 count) +{ + UINT8 evtBuf[256]; + UINT32 u4Res; + INT32 i = 0; + INT32 iRet; + + for (i = 0; i < count; i++) { + WMT_DBG_FUNC("WMT-CORE: init_script operation %s start\n", script[i].str); + /* CMD */ + /* iRet = (*kal_stp_tx)(script[i].cmd, script[i].cmdSz, &u4Res); */ + iRet = wmt_core_tx(script[i].cmd, script[i].cmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != script[i].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", script[i].str, iRet, u4Res, + script[i].cmdSz); + break; + } + /* EVENT BUF */ + osal_memset(evtBuf, 0, sizeof(evtBuf)); + iRet = wmt_core_rx(evtBuf, script[i].evtSz, &u4Res); + if (iRet || (u4Res != script[i].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", script[i].str, iRet, + u4Res, script[i].evtSz); + mtk_wcn_stp_dbg_dump_package(); + break; + } + /* RESULT */ + if (0x14 != evtBuf[1]) { /* workaround RF calibration data EVT,do not care this EVT */ + if (osal_memcmp(evtBuf, script[i].evt, script[i].evtSz) != 0) { + WMT_ERR_FUNC("WMT-CORE:compare %s result error\n", script[i].str); + WMT_ERR_FUNC + ("WMT-CORE:rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], script[i].evtSz, + script[i].evt[0], script[i].evt[1], script[i].evt[2], script[i].evt[3], + script[i].evt[4]); + mtk_wcn_stp_dbg_dump_package(); + break; + } + } + WMT_DBG_FUNC("init_script operation %s ok\n", script[i].str); + } + + return (i == count) ? 0 : -1; +} + +static INT32 wmt_core_stp_init(VOID) +{ + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT8 co_clock_type; + P_WMT_CTX pctx = &gMtkWmtCtx; + P_WMT_GEN_CONF pWmtGenConf = NULL; + + wmt_conf_read_file(); + pWmtGenConf = wmt_conf_get_cfg(); + if (!(pctx->wmtInfoBit & WMT_OP_HIF_BIT)) { + WMT_ERR_FUNC("WMT-CORE: no hif info!\n"); + osal_assert(0); + return -1; + } + /* 4 <1> open stp */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -2; + } + /* 4 <1.5> disable and un-ready stp */ + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_RDY; + ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + /* 4 <2> set mode and enable */ + if (WMT_HIF_BTIF == pctx->wmtHifConf.hifType) { + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + } + + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); + return -3; + } + /* TODO: [ChangeFeature][GeorgeKuo] can we apply raise UART baud rate firstly for ALL supported chips??? */ + + iRet = wmt_core_hw_check(); + if (iRet) { + WMT_ERR_FUNC("hw_check fail:%d\n", iRet); + return -4; + } + /* mtkWmtCtx.p_ic_ops is identified and checked ok */ + if ((NULL != pctx->p_ic_ops->co_clock_ctrl) && (pWmtGenConf != NULL)) { + co_clock_type = (pWmtGenConf->co_clock_flag & 0x0f); + (*(pctx->p_ic_ops->co_clock_ctrl)) (co_clock_type == 0 ? WMT_CO_CLOCK_DIS : WMT_CO_CLOCK_EN); + } else { + WMT_WARN_FUNC("pctx->p_ic_ops->co_clock_ctrl(0x%x), pWmtGenConf(0x%x)\n", pctx->p_ic_ops->co_clock_ctrl, + pWmtGenConf); + } + osal_assert(NULL != pctx->p_ic_ops->sw_init); + if (NULL != pctx->p_ic_ops->sw_init) { + iRet = (*(pctx->p_ic_ops->sw_init)) (&pctx->wmtHifConf); + } else { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); + return -5; + } + if (iRet) { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init fail:%d\n", iRet); + return -6; + } + /* 4 <10> set stp ready */ + ctrlPa1 = WMT_STP_CONF_RDY; + ctrlPa2 = 1; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + return iRet; +} + +static INT32 wmt_core_stp_deinit(VOID) +{ + INT32 iRet; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + WMT_DBG_FUNC(" start\n"); + + if (NULL == gMtkWmtCtx.p_ic_ops) { + WMT_WARN_FUNC("gMtkWmtCtx.p_ic_ops is NULL\n"); + goto deinit_ic_ops_done; + } + if (NULL != gMtkWmtCtx.p_ic_ops->sw_deinit) { + iRet = (*(gMtkWmtCtx.p_ic_ops->sw_deinit)) (&gMtkWmtCtx.wmtHifConf); + /* unbind WMT-IC */ + gMtkWmtCtx.p_ic_ops = NULL; + } else { + WMT_ERR_FUNC("gMtkWmtCtx.p_ic_ops->sw_init is NULL\n"); + } + +deinit_ic_ops_done: + + /* 4 <1> un-ready, disable, and close stp. */ + ctrlPa1 = WMT_STP_CONF_RDY; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + + if (iRet) + WMT_WARN_FUNC("end with fail:%d\n", iRet); + + return iRet; +} + +static VOID wmt_core_dump_func_state(PINT8 pSource) +{ + WMT_WARN_FUNC("[%s]status(b:%d f:%d g:%d w:%d lpbk:%d coredump:%d wmt:%d stp:%d)\n", + (pSource == NULL ? (PINT8) "CORE" : pSource), + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP], + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT], gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] + ); + return; + +} + +MTK_WCN_BOOL wmt_core_patch_check(UINT32 u4PatchVer, UINT32 u4HwVer) +{ + if (MAJORNUM(u4HwVer) != MAJORNUM(u4PatchVer)) { + /*major no. does not match */ + WMT_ERR_FUNC("WMT-CORE: chip version(0x%d) does not match patch version(0x%d)\n", u4HwVer, u4PatchVer); + return MTK_WCN_BOOL_FALSE; + } + return MTK_WCN_BOOL_TRUE; +} + +static INT32 wmt_core_hw_check(VOID) +{ + UINT32 chipid; + P_WMT_IC_OPS p_ops; + INT32 iret; + + /* 1. get chip id */ + chipid = 0; + WMT_LOUD_FUNC("before read hwcode (chip id)\n"); + iret = wmt_core_reg_rw_raw(0, GEN_HCR, &chipid, GEN_HCR_MASK); /* read 0x80000008 */ + if (iret) { + WMT_ERR_FUNC("get hwcode (chip id) fail (%d)\n", iret); + return -2; + } + WMT_DBG_FUNC("get hwcode (chip id) (0x%x)\n", chipid); + + /* TODO:[ChangeFeature][George]: use a better way to select a correct ops table based on chip id */ + switch (chipid) { +#if CFG_CORE_MT6620_SUPPORT + case 0x6620: + p_ops = &wmt_ic_ops_mt6620; + break; +#endif +#if CFG_CORE_MT6628_SUPPORT + case 0x6628: + p_ops = &wmt_ic_ops_mt6628; + break; +#endif +#if CFG_CORE_SOC_SUPPORT + case 0x6572: + case 0x6582: + case 0x6592: + case 0x8127: + case 0x6571: + case 0x6752: + case 0x0279: + case 0x0326: + case 0x0321: + case 0x0335: + case 0x0337: + case 0x8163: + case 0x6580: + p_ops = &wmt_ic_ops_soc; + break; +#endif + default: + p_ops = (P_WMT_IC_OPS) NULL; +#if CFG_CORE_SOC_SUPPORT + if (0x7f90 == chipid - 0x600) { + p_ops = &wmt_ic_ops_soc; + chipid -= 0xf6d; + } +#endif + break; + } + + if (NULL == p_ops) { + WMT_ERR_FUNC("unsupported chip id (hw_code): 0x%x\n", chipid); + return -3; + } else if (MTK_WCN_BOOL_FALSE == wmt_core_ic_ops_check(p_ops)) { + WMT_ERR_FUNC + ("chip id(0x%x) with null operation fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", + chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); + return -4; + } + WMT_DBG_FUNC("chip id(0x%x) fp: init(0x%p), deinit(0x%p), pin_ctrl(0x%p), ver_chk(0x%p)\n", + chipid, p_ops->sw_init, p_ops->sw_deinit, p_ops->ic_pin_ctrl, p_ops->ic_ver_check); + + wmt_ic_ops_soc.icId = chipid; + WMT_DBG_FUNC("wmt_ic_ops_soc.icId(0x%x)\n", wmt_ic_ops_soc.icId); + iret = p_ops->ic_ver_check(); + if (iret) { + WMT_ERR_FUNC("chip id(0x%x) ver_check error:%d\n", chipid, iret); + return -5; + } + + WMT_DBG_FUNC("chip id(0x%x) ver_check ok\n", chipid); + gMtkWmtCtx.p_ic_ops = p_ops; + return 0; +} + +static INT32 opfunc_hif_conf(P_WMT_OP pWmtOp) +{ + if (!(pWmtOp->u4InfoBit & WMT_OP_HIF_BIT)) { + WMT_ERR_FUNC("WMT-CORE: no HIF_BIT in WMT_OP!\n"); + return -1; + } + + if (gMtkWmtCtx.wmtInfoBit & WMT_OP_HIF_BIT) { + WMT_ERR_FUNC("WMT-CORE: WMT HIF already exist. overwrite! old (%d), new(%d))\n", + gMtkWmtCtx.wmtHifConf.hifType, pWmtOp->au4OpData[0]); + } else { + gMtkWmtCtx.wmtInfoBit |= WMT_OP_HIF_BIT; + WMT_ERR_FUNC("WMT-CORE: WMT HIF info added\n"); + } + + osal_memcpy(&gMtkWmtCtx.wmtHifConf, &pWmtOp->au4OpData[0], osal_sizeof(gMtkWmtCtx.wmtHifConf)); + return 0; + +} + +static INT32 opfunc_pwr_on(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + INT32 retry = WMT_PWRON_RTY_DFT; + + if (DRV_STS_POWER_OFF != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: already powered on, WMT DRV_STS_[0x%x]\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + /* TODO: [FixMe][GeorgeKuo]: clarify the following is reqiured or not! */ + if (pWmtOp->u4InfoBit & WMT_OP_HIF_BIT) + opfunc_hif_conf(pWmtOp); + +pwr_on_rty: + /* power on control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); + if (0 == retry--) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + return -1; + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + + /* init stp */ + iRet = wmt_core_stp_init(); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_core_stp_init fail (%d)\n", iRet); + osal_assert(0); + + /* deinit stp */ + iRet = wmt_core_stp_deinit(); + iRet = opfunc_pwr_off(pWmtOp); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: opfunc_pwr_off fail during pwr_on retry\n"); + + if (0 < retry--) { + WMT_INFO_FUNC("WMT-CORE: retry (%d)\n", retry); + goto pwr_on_rty; + } + iRet = -2; + return iRet; + } + + WMT_DBG_FUNC("WMT-CORE: WMT [FUNC_ON]\n"); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + + /* What to do when state is changed from POWER_OFF to POWER_ON? + * 1. STP driver does s/w reset + * 2. UART does 0xFF wake up + * 3. SDIO does re-init command(changed to trigger by host) + */ + return iRet; + +} + +static INT32 opfunc_pwr_off(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_WARN_FUNC("WMT-CORE: WMT already off, WMT DRV_STS_[0x%x]\n", + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]); + osal_assert(0); + return -1; + } + if (MTK_WCN_BOOL_FALSE == g_pwr_off_flag) { + WMT_WARN_FUNC("CONNSYS power off be disabled, maybe need trigger core dump!\n"); + osal_assert(0); + return -2; + } + + /* wmt and stp are initialized successfully */ + if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + iRet = wmt_core_stp_deinit(); + if (iRet) { + WMT_WARN_FUNC("wmt_core_stp_deinit fail (%d)\n", iRet); + /*should let run to power down chip */ + } + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + + /* power off control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_OFF, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_WARN_FUNC("HW_PWR_OFF fail (%d)\n", iRet); + WMT_WARN_FUNC("HW_PWR_OFF ok\n"); + + /*anyway, set to POWER_OFF state */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + return iRet; + +} + +static INT32 opfunc_func_on(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + INT32 iPwrOffRet = -1; + UINT32 drvType; + + drvType = pWmtOp->au4OpData[0]; + + /* Check abnormal type */ + if (WMTDRV_TYPE_COREDUMP < drvType) { + WMT_ERR_FUNC("abnormal Fun(%d)\n", drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if ((DRV_STS_POWER_OFF > gMtkWmtCtx.eDrvStatus[drvType]) + || (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType])) { + WMT_ERR_FUNC("func(%d) status[0x%x] abnormal\n", drvType, gMtkWmtCtx.eDrvStatus[drvType]); + osal_assert(0); + return -2; + } + + /* check if func already on */ + if (DRV_STS_FUNC_ON == gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_WARN_FUNC("func(%d) already on\n", drvType); + return 0; + } + /*enable power off flag, if flag=0, power off connsys will not be executed */ + mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); + /* check if chip power on is needed */ + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + iRet = opfunc_pwr_on(pWmtOp); + + if (iRet) { + WMT_ERR_FUNC("func(%d) pwr_on fail(%d)\n", drvType, iRet); + osal_assert(0); + + /* check all sub-func and do power off */ + return -3; + } + } + + if (WMTDRV_TYPE_WMT > drvType) { + if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_on) { + iRet = (*(gpWmtFuncOps[drvType]->func_on)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (0 != iRet) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + else + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + } else { + WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); + iRet = -5; + } + } else { + if (WMTDRV_TYPE_LPBK == drvType) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + else if (WMTDRV_TYPE_COREDUMP == drvType) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_FUNC_ON; + iRet = 0; + } + + if (iRet) { + WMT_ERR_FUNC("WMT-CORE:type(0x%x) function on failed, ret(%d)\n", drvType, iRet); + osal_assert(0); + /* FIX-ME:[Chaozhong Liang], Error handling? check subsystem state and do pwr off if necessary? */ + /* check all sub-func and do power off */ + if ((DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { + WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); + mtk_wcn_wmt_system_state_reset(); + + iPwrOffRet = opfunc_pwr_off(pWmtOp); + if (iPwrOffRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iPwrOffRet, + drvType); + osal_assert(0); + } + } + return iRet; + } + + wmt_core_dump_func_state("AF FUNC ON"); + + return 0; +} + +static INT32 opfunc_func_off(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 drvType; + + drvType = pWmtOp->au4OpData[0]; + /* Check abnormal type */ + if (WMTDRV_TYPE_COREDUMP < drvType) { + WMT_ERR_FUNC("WMT-CORE: abnormal Fun(%d) in wmt_func_off\n", drvType); + osal_assert(0); + return -1; + } + + /* Check abnormal state */ + if (DRV_STS_MAX <= gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_ERR_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] abnormal in wmt_func_off\n", + drvType, gMtkWmtCtx.eDrvStatus[drvType]); + osal_assert(0); + return -2; + } + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[drvType]) { + WMT_WARN_FUNC("WMT-CORE: Fun(%d) DRV_STS_[0x%x] already non-FUN_ON in wmt_func_off\n", + drvType, gMtkWmtCtx.eDrvStatus[drvType]); + /* needs to check 4 subsystem's state? */ + return 0; + } else if (WMTDRV_TYPE_WMT > drvType) { + if (NULL != gpWmtFuncOps[drvType] && NULL != gpWmtFuncOps[drvType]->func_off) { + iRet = (*(gpWmtFuncOps[drvType]->func_off)) (gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + } else { + WMT_WARN_FUNC("WMT-CORE: ops for type(%d) not found\n", drvType); + iRet = -3; + } + } else { + if (WMTDRV_TYPE_LPBK == drvType) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + else if (WMTDRV_TYPE_COREDUMP == drvType) + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + iRet = 0; + } + + /* shall we put device state to POWER_OFF state when fail? */ + gMtkWmtCtx.eDrvStatus[drvType] = DRV_STS_POWER_OFF; + + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: type(0x%x) function off failed, ret(%d)\n", drvType, iRet); + osal_assert(0); + /* no matter subsystem function control fail or not, + *chip should be powered off when no subsystem is active + */ + /* return iRet; */ + } + + /* check all sub-func and do power off */ + if ((DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK]) && + (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP])) { + WMT_INFO_FUNC("WMT-CORE:Fun(%d) [POWER_OFF] and power down chip\n", drvType); + + iRet = opfunc_pwr_off(pWmtOp); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt_pwr_off fail(%d) when turn off func(%d)\n", iRet, drvType); + osal_assert(0); + } + } + + wmt_core_dump_func_state("AF FUNC OFF"); + return iRet; +} + +/* TODO:[ChangeFeature][George] is this OP obsoleted? */ +static INT32 opfunc_reg_rw(P_WMT_OP pWmtOp) +{ + INT32 iret; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("reg_rw when WMT is powered off\n"); + return -1; + } + iret = wmt_core_reg_rw_raw(pWmtOp->au4OpData[0], + pWmtOp->au4OpData[1], (PUINT32) pWmtOp->au4OpData[2], pWmtOp->au4OpData[3]); + + return iret; +} + +static INT32 opfunc_exit(P_WMT_OP pWmtOp) +{ + /* TODO: [FixMe][George] is ok to leave this function empty??? */ + WMT_WARN_FUNC("EMPTY FUNCTION\n"); + return 0; +} + +static INT32 opfunc_pwr_sv(P_WMT_OP pWmtOp) +{ + INT32 ret = -1; + UINT32 u4_result = 0; + UINT32 evt_len; + UINT8 evt_buf[16] = { 0 }; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + + typedef INT32(*STP_PSM_CB) (INT32); + STP_PSM_CB psm_cb = NULL; + + if (SLEEP == pWmtOp->au4OpData[0]) { + WMT_DBG_FUNC("**** Send sleep command\n"); + /* mtk_wcn_stp_set_psm_state(ACT_INACT); */ + /* (*kal_stp_flush_rx)(WMT_TASK_INDX); */ + ret = wmt_core_tx((PUINT8) &WMT_SLEEP_CMD[0], sizeof(WMT_SLEEP_CMD), &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_SLEEP_CMD))) { + WMT_ERR_FUNC("wmt_core: SLEEP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, + sizeof(WMT_SLEEP_CMD)); + goto pwr_sv_done; + } + + evt_len = sizeof(WMT_SLEEP_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) { + unsigned long type = WMTDRV_TYPE_WMT; + unsigned long reason = 33; + unsigned long ctrlpa = 1; + + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: read SLEEP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); + if (!ret) { /* parser ok */ + reason = 38; /* host schedule issue reason code */ + WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); + } + wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_SLEEP_EVT, sizeof(WMT_SLEEP_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_SLEEP_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, + evt_buf[0], + evt_buf[1], + evt_buf[2], + evt_buf[3], + evt_buf[4], + evt_buf[5]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_SLEEP_EVT), + WMT_SLEEP_EVT[0], + WMT_SLEEP_EVT[1], + WMT_SLEEP_EVT[2], + WMT_SLEEP_EVT[3], + WMT_SLEEP_EVT[4], + WMT_SLEEP_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } else { + WMT_DBG_FUNC("Send sleep command OK!\n"); + } + } else if (pWmtOp->au4OpData[0] == WAKEUP) { + WMT_DBG_FUNC("wakeup connsys by btif"); + + ret = wmt_core_ctrl(WMT_CTRL_SOC_WAKEUP_CONSYS, &ctrlPa1, &ctrlPa2); + if (ret) { + WMT_ERR_FUNC("wmt-core:WAKEUP_CONSYS by BTIF fail(%d)", ret); + goto pwr_sv_done; + } +#if 0 + WMT_DBG_FUNC("**** Send wakeup command\n"); + ret = wmt_core_tx(WMT_WAKEUP_CMD, sizeof(WMT_WAKEUP_CMD), &u4_result, 1); + + if (ret || (u4_result != sizeof(WMT_WAKEUP_CMD))) { + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: WAKEUP_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, + sizeof(WMT_WAKEUP_CMD)); + goto pwr_sv_done; + } +#endif + evt_len = sizeof(WMT_WAKEUP_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) { + unsigned long type = WMTDRV_TYPE_WMT; + unsigned long reason = 34; + unsigned long ctrlpa = 2; + + WMT_ERR_FUNC("wmt_core: read WAKEUP_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); + if (!ret) { /* parser ok */ + reason = 39; /* host schedule issue reason code */ + WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); + } + wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_WAKEUP_EVT, sizeof(WMT_WAKEUP_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_WAKEUP_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, + evt_buf[0], + evt_buf[1], + evt_buf[2], + evt_buf[3], + evt_buf[4], + evt_buf[5]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_WAKEUP_EVT), + WMT_WAKEUP_EVT[0], + WMT_WAKEUP_EVT[1], + WMT_WAKEUP_EVT[2], + WMT_WAKEUP_EVT[3], + WMT_WAKEUP_EVT[4], + WMT_WAKEUP_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + goto pwr_sv_done; + } else { + WMT_DBG_FUNC("Send wakeup command OK!\n"); + } + } else if (pWmtOp->au4OpData[0] == HOST_AWAKE) { + + WMT_DBG_FUNC("**** Send host awake command\n"); + + psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; + /* (*kal_stp_flush_rx)(WMT_TASK_INDX); */ + ret = wmt_core_tx((PUINT8) WMT_HOST_AWAKE_CMD, sizeof(WMT_HOST_AWAKE_CMD), &u4_result, 0); + if (ret || (u4_result != sizeof(WMT_HOST_AWAKE_CMD))) { + WMT_ERR_FUNC("wmt_core: HOST_AWAKE_CMD ret(%d) cmd len err(%d, %d) ", ret, u4_result, + sizeof(WMT_HOST_AWAKE_CMD)); + goto pwr_sv_done; + } + + evt_len = sizeof(WMT_HOST_AWAKE_EVT); + ret = wmt_core_rx(evt_buf, evt_len, &u4_result); + if (ret || (u4_result != evt_len)) { + unsigned long type = WMTDRV_TYPE_WMT; + unsigned long reason = 35; + unsigned long ctrlpa = 3; + + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: read HOST_AWAKE_EVT fail(%d) len(%d, %d)", ret, u4_result, evt_len); + mtk_wcn_stp_dbg_dump_package(); + ret = wmt_core_ctrl(WMT_CTRL_EVT_PARSER, &ctrlpa, 0); + if (!ret) { /* parser ok */ + reason = 40; /* host schedule issue reason code */ + WMT_WARN_FUNC("This evt error may be caused by system schedule issue\n"); + } + wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &type, &reason); + goto pwr_sv_done; + } + + if (osal_memcmp(evt_buf, WMT_HOST_AWAKE_EVT, sizeof(WMT_HOST_AWAKE_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_HOST_AWAKE_EVT error\n"); + wmt_core_rx_flush(WMT_TASK_INDX); + WMT_ERR_FUNC("wmt_core: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + u4_result, + evt_buf[0], + evt_buf[1], + evt_buf[2], + evt_buf[3], + evt_buf[4], + evt_buf[5]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_HOST_AWAKE_EVT), + WMT_HOST_AWAKE_EVT[0], + WMT_HOST_AWAKE_EVT[1], + WMT_HOST_AWAKE_EVT[2], + WMT_HOST_AWAKE_EVT[3], + WMT_HOST_AWAKE_EVT[4], + WMT_HOST_AWAKE_EVT[5]); + mtk_wcn_stp_dbg_dump_package(); + /* goto pwr_sv_done; */ + } else { + WMT_DBG_FUNC("Send host awake command OK!\n"); + } + } +pwr_sv_done: + + if (pWmtOp->au4OpData[0] < STP_PSM_MAX_ACTION) { + psm_cb = (STP_PSM_CB) pWmtOp->au4OpData[1]; + WMT_DBG_FUNC("Do STP-CB! %d %p / %p\n", pWmtOp->au4OpData[0], (PVOID) pWmtOp->au4OpData[1], + (PVOID) psm_cb); + if (NULL != psm_cb) { + psm_cb(pWmtOp->au4OpData[0]); + } else { + WMT_ERR_FUNC("fatal error !!!, psm_cb = %p, god, someone must have corrupted our memory.\n", + psm_cb); + } + } + + return ret; +} + +static INT32 opfunc_dsns(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + WMT_DSNS_CMD[4] = (UINT8) pWmtOp->au4OpData[0]; + WMT_DSNS_CMD[5] = (UINT8) pWmtOp->au4OpData[1]; + + /* send command */ + /* iRet = (*kal_stp_tx)(WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res); */ + iRet = wmt_core_tx((PUINT8) WMT_DSNS_CMD, osal_sizeof(WMT_DSNS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_DSNS_CMD))) { + WMT_ERR_FUNC("WMT-CORE: DSNS_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, + osal_sizeof(WMT_DSNS_CMD)); + return iRet; + } + + evtLen = osal_sizeof(WMT_DSNS_EVT); + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) { + WMT_ERR_FUNC("WMT-CORE: read DSNS_EVT fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + mtk_wcn_stp_dbg_dump_package(); + return iRet; + } + + if (osal_memcmp(evtBuf, WMT_DSNS_EVT, osal_sizeof(WMT_DSNS_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_DSNS_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + osal_sizeof(WMT_DSNS_EVT), WMT_DSNS_EVT[0], WMT_DSNS_EVT[1], WMT_DSNS_EVT[2], + WMT_DSNS_EVT[3], WMT_DSNS_EVT[4]); + } else { + WMT_INFO_FUNC("Send WMT_DSNS_CMD command OK!\n"); + } + + return iRet; +} + +#if CFG_CORE_INTERNAL_TXRX +INT32 wmt_core_lpbk_do_stp_init(void) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_OPEN, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -1; + } + + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_MAND_MODE; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: stp_init <1><2> fail:%d\n", iRet); + return -2; + } +} + +INT32 wmt_core_lpbk_do_stp_deinit(void) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: wmt open stp\n"); + return -1; + } + + return 0; +} +#endif +static INT32 opfunc_lpbk(P_WMT_OP pWmtOp) +{ + + INT32 iRet; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT32 buf_length = 0; + UINT32 *pbuffer = NULL; + UINT16 len_in_cmd; + + /* UINT32 offset; */ + UINT8 WMT_TEST_LPBK_CMD[] = { 0x1, 0x2, 0x0, 0x0, 0x7 }; + UINT8 WMT_TEST_LPBK_EVT[] = { 0x2, 0x2, 0x0, 0x0, 0x0 }; + + /* UINT8 lpbk_buf[1024 + 5] = {0}; */ + MTK_WCN_BOOL fgFail; + + buf_length = pWmtOp->au4OpData[0]; /* packet length */ + pbuffer = (VOID *) pWmtOp->au4OpData[1]; /* packet buffer pointer */ + WMT_DBG_FUNC("WMT-CORE: -->wmt_do_lpbk\n"); + +#if 0 + osal_memcpy(&WMT_TEST_LPBK_EVT[0], &WMT_TEST_LPBK_CMD[0], osal_sizeof(WMT_TEST_LPBK_CMD)); +#endif +#if !CFG_CORE_INTERNAL_TXRX + /*check if WMTDRV_TYPE_LPBK function is already on */ + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] + || buf_length + osal_sizeof(WMT_TEST_LPBK_CMD) > osal_sizeof(gLpbkBuf)) { + WMT_ERR_FUNC("WMT-CORE: abnormal LPBK in wmt_do_lpbk\n"); + osal_assert(0); + return -2; + } +#endif + /*package loopback for STP */ + + /* init buffer */ + osal_memset(gLpbkBuf, 0, osal_sizeof(gLpbkBuf)); + + len_in_cmd = buf_length + 1; /* add flag field */ + + osal_memcpy(&WMT_TEST_LPBK_CMD[2], &len_in_cmd, 2); + osal_memcpy(&WMT_TEST_LPBK_EVT[2], &len_in_cmd, 2); + + /* wmt cmd */ + osal_memcpy(gLpbkBuf, WMT_TEST_LPBK_CMD, osal_sizeof(WMT_TEST_LPBK_CMD)); + osal_memcpy(gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), pbuffer, buf_length); + + do { + fgFail = MTK_WCN_BOOL_TRUE; + /*send packet through STP */ + + /* iRet = (*kal_stp_tx)( + *(PUINT8)gLpbkBuf, + *osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length, + *&u4WrittenSize); + */ + iRet = wmt_core_tx((PUINT8) gLpbkBuf, + (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length), + &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet) { + WMT_ERR_FUNC("opfunc_lpbk wmt_core_tx failed\n"); + break; + } + WMT_INFO_FUNC("opfunc_lpbk wmt_core_tx OK\n"); + + /*receive firmware response from STP */ + iRet = wmt_core_rx((PUINT8) gLpbkBuf, (osal_sizeof(WMT_TEST_LPBK_EVT) + buf_length), &u4ReadSize); + if (iRet) { + WMT_ERR_FUNC("opfunc_lpbk wmt_core_rx failed\n"); + break; + } + WMT_INFO_FUNC("opfunc_lpbk wmt_core_rx OK\n"); + /*check if loopback response ok or not */ + if (u4ReadSize != (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)) { + WMT_ERR_FUNC("lpbk event read size wrong(%d, %d)\n", u4ReadSize, + (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)); + break; + } + WMT_INFO_FUNC("lpbk event read size right(%d, %d)\n", u4ReadSize, + (osal_sizeof(WMT_TEST_LPBK_CMD) + buf_length)); + + if (osal_memcmp(WMT_TEST_LPBK_EVT, gLpbkBuf, osal_sizeof(WMT_TEST_LPBK_EVT))) { + WMT_ERR_FUNC("WMT-CORE WMT_TEST_LPBK_EVT error! read len %d [%02x,%02x,%02x,%02x,%02x]\n", + (INT32) u4ReadSize, gLpbkBuf[0], gLpbkBuf[1], gLpbkBuf[2], gLpbkBuf[3], gLpbkBuf[4] + ); + break; + } + pWmtOp->au4OpData[0] = u4ReadSize - osal_sizeof(WMT_TEST_LPBK_EVT); + osal_memcpy((VOID *) pWmtOp->au4OpData[1], gLpbkBuf + osal_sizeof(WMT_TEST_LPBK_CMD), buf_length); + fgFail = MTK_WCN_BOOL_FALSE; + } while (0); + /*return result */ + /* WMT_DBG_FUNC("WMT-CORE: <--wmt_do_lpbk, fgFail = %d\n", fgFail); */ + return fgFail; + +} + +static INT32 opfunc_cmd_test(P_WMT_OP pWmtOp) +{ + + INT32 iRet = 0; + UINT32 cmdNo = 0; + UINT32 cmdNoPa = 0; + + UINT8 tstCmd[64]; + UINT8 tstEvt[64]; + UINT8 tstEvtTmp[64]; + UINT32 u4Res; + SIZE_T tstCmdSz = 0; + SIZE_T tstEvtSz = 0; + + UINT8 *pRes = NULL; + UINT32 resBufRoom = 0; + /*test command list */ + /*1 */ + UINT8 WMT_ASSERT_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x08 }; + UINT8 WMT_ASSERT_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_NOACK_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0A }; + UINT8 WMT_NOACK_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_WARNRST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0B }; + UINT8 WMT_WARNRST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + UINT8 WMT_FWLOGTST_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x0C }; + UINT8 WMT_FWLOGTST_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + + UINT8 WMT_EXCEPTION_CMD[] = { 0x01, 0x02, 0x01, 0x00, 0x09 }; + UINT8 WMT_EXCEPTION_EVT[] = { 0x02, 0x02, 0x00, 0x00, 0x00 }; + /*2 */ + UINT8 WMT_COEXDBG_CMD[] = { 0x01, 0x10, 0x02, 0x00, + 0x08, + 0xAA /*Debugging Parameter */ + }; + UINT8 WMT_COEXDBG_1_EVT[] = { 0x02, 0x10, 0x05, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA /*event content */ + }; + UINT8 WMT_COEXDBG_2_EVT[] = { 0x02, 0x10, 0x07, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB /*event content */ + }; + UINT8 WMT_COEXDBG_3_EVT[] = { 0x02, 0x10, 0x0B, 0x00, + 0x00, + 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB /*event content */ + }; + /*test command list -end */ + + cmdNo = pWmtOp->au4OpData[0]; + + WMT_INFO_FUNC("Send Test command %d!\n", cmdNo); + if (cmdNo == 0) { + /*dead command */ + WMT_INFO_FUNC("Send Assert command !\n"); + tstCmdSz = osal_sizeof(WMT_ASSERT_CMD); + tstEvtSz = osal_sizeof(WMT_ASSERT_EVT); + osal_memcpy(tstCmd, WMT_ASSERT_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_ASSERT_EVT, tstEvtSz); + } else if (cmdNo == 1) { + /*dead command */ + WMT_INFO_FUNC("Send Exception command !\n"); + tstCmdSz = osal_sizeof(WMT_EXCEPTION_CMD); + tstEvtSz = osal_sizeof(WMT_EXCEPTION_EVT); + osal_memcpy(tstCmd, WMT_EXCEPTION_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_EXCEPTION_EVT, tstEvtSz); + } else if (cmdNo == 2) { + cmdNoPa = pWmtOp->au4OpData[1]; + pRes = (PUINT8) pWmtOp->au4OpData[2]; + resBufRoom = pWmtOp->au4OpData[3]; + if (cmdNoPa <= 0xf) { + WMT_INFO_FUNC("Send Coexistence Debug command [0x%x]!\n", cmdNoPa); + tstCmdSz = osal_sizeof(WMT_COEXDBG_CMD); + osal_memcpy(tstCmd, WMT_COEXDBG_CMD, tstCmdSz); + if (tstCmdSz > 5) + tstCmd[5] = cmdNoPa; + + /*setup the expected event length */ + if (cmdNoPa <= 0x4) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_1_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_1_EVT, tstEvtSz); + } else if (cmdNoPa == 0x5) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_2_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_2_EVT, tstEvtSz); + } else if (cmdNoPa >= 0x6 && cmdNoPa <= 0xf) { + tstEvtSz = osal_sizeof(WMT_COEXDBG_3_EVT); + osal_memcpy(tstEvt, WMT_COEXDBG_3_EVT, tstEvtSz); + } else { + + } + } else { + WMT_ERR_FUNC("cmdNoPa is wrong\n"); + return iRet; + } + } else if (cmdNo == 3) { + /*dead command */ + WMT_INFO_FUNC("Send No Ack command !\n"); + tstCmdSz = osal_sizeof(WMT_NOACK_CMD); + tstEvtSz = osal_sizeof(WMT_NOACK_EVT); + osal_memcpy(tstCmd, WMT_NOACK_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_NOACK_EVT, tstEvtSz); + } else if (cmdNo == 4) { + /*dead command */ + WMT_INFO_FUNC("Send Warm reset command !\n"); + tstCmdSz = osal_sizeof(WMT_WARNRST_CMD); + tstEvtSz = osal_sizeof(WMT_WARNRST_EVT); + osal_memcpy(tstCmd, WMT_WARNRST_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_WARNRST_EVT, tstEvtSz); + } else if (cmdNo == 5) { + /*dead command */ + WMT_INFO_FUNC("Send f/w log test command !\n"); + tstCmdSz = osal_sizeof(WMT_FWLOGTST_CMD); + tstEvtSz = osal_sizeof(WMT_FWLOGTST_EVT); + osal_memcpy(tstCmd, WMT_FWLOGTST_CMD, tstCmdSz); + osal_memcpy(tstEvt, WMT_FWLOGTST_EVT, tstEvtSz); + } + + else { + /*Placed youer test WMT command here, easiler to integrate and test with F/W side */ + } + + /* send command */ + /* iRet = (*kal_stp_tx)(tstCmd, tstCmdSz, &u4Res); */ + iRet = wmt_core_tx((PUINT8) tstCmd, tstCmdSz, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != tstCmdSz)) { + WMT_ERR_FUNC("WMT-CORE: wmt_cmd_test iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, tstCmdSz); + return -1; + } + + if ((cmdNo == 0) || (cmdNo == 1) || cmdNo == 3) { + WMT_INFO_FUNC("WMT-CORE: not to rx event for assert command\n"); + return 0; + } + + iRet = wmt_core_rx(tstEvtTmp, tstEvtSz, &u4Res); + + /*Event Post Handling */ + if (cmdNo == 2) { + WMT_INFO_FUNC("#=========================================================#\n"); + WMT_INFO_FUNC("coext debugging id = %d", cmdNoPa); + if (tstEvtSz > 5) { + wmt_core_dump_data(&tstEvtTmp[5], "coex debugging ", tstEvtSz - 5); + } else { + /* error log */ + WMT_ERR_FUNC("error coex debugging event\n"); + } + /*put response to buffer for shell to read */ + if (pRes != NULL && resBufRoom > 0) { + pWmtOp->au4OpData[3] = resBufRoom < tstEvtSz - 5 ? resBufRoom : tstEvtSz - 5; + osal_memcpy(pRes, &tstEvtTmp[5], pWmtOp->au4OpData[3]); + } else + pWmtOp->au4OpData[3] = 0; + WMT_INFO_FUNC("#=========================================================#\n"); + } + + return iRet; + +} + +static INT32 opfunc_hw_rst(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + wmt_core_dump_func_state("BE HW RST"); + /*-->Reset WMT data structure*/ + /* gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_FM] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_GPS] = DRV_STS_POWER_OFF; + /* gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; */ + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_LPBK] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_STP] = DRV_STS_POWER_OFF; + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = DRV_STS_POWER_OFF; + /*enable power off flag, if flag=0, power off connsys will not be executed */ + mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL_TRUE); + /* if wmt is poweroff, we need poweron chip first */ + /* Zhiguo : this action also needed in BTIF interface to avoid KE */ +#if 1 + if (DRV_STS_POWER_OFF == gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_WARN_FUNC("WMT-CORE: WMT is off, need re-poweron\n"); + /* power on control */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_PWR_ON, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: WMT_CTRL_HW_PWR_ON fail iRet(%d)\n", iRet); + return -1; + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + } +#endif + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] == DRV_STS_FUNC_ON) { + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: wmt_ctrl_soc_paldo_ctrl failed(%d)(%d)(%d)\n", iRet, ctrlPa1, ctrlPa2); + + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_BT] = DRV_STS_POWER_OFF; + } + + if (gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] == DRV_STS_FUNC_ON) { + + if (NULL != gpWmtFuncOps[WMTDRV_TYPE_WIFI] && NULL != gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off) { + iRet = gpWmtFuncOps[WMTDRV_TYPE_WIFI]->func_off(gMtkWmtCtx.p_ic_ops, wmt_conf_get_cfg()); + if (iRet) { + WMT_ERR_FUNC("WMT-CORE: turn off WIFI func fail (%d)\n", iRet); + + /* check all sub-func and do power off */ + } else { + WMT_INFO_FUNC("wmt core: turn off WIFI func ok!!\n"); + } + } + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WIFI] = DRV_STS_POWER_OFF; + } +#if 0 + /*<4>Power off Combo chip */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF fail (%d)", iRet); + WMT_INFO_FUNC("WMT-CORE: [HW RST] WMT_CTRL_POWER_OFF ok (%d)", iRet); +#endif + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_OFF; + + /*-->PesetCombo chip*/ + iRet = wmt_core_ctrl(WMT_CTRL_HW_RST, &ctrlPa1, &ctrlPa2); + if (iRet) + WMT_ERR_FUNC("WMT-CORE: -->[HW RST] fail iRet(%d)\n", iRet); + WMT_WARN_FUNC("WMT-CORE: -->[HW RST] ok\n"); + + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_POWER_ON; + + /* 4 close stp */ + ctrlPa1 = 0; + ctrlPa2 = 0; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CLOSE, &ctrlPa1, &ctrlPa2); + if (iRet) { + if (iRet == -2) { + WMT_INFO_FUNC("WMT-CORE:stp should have be closed\n"); + return 0; + } + WMT_ERR_FUNC("WMT-CORE: wmt close stp failed\n"); + return -1; + } + + wmt_core_dump_func_state("AF HW RST"); + return iRet; + +} + +static INT32 opfunc_sw_rst(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + + iRet = wmt_core_stp_init(); + if (!iRet) + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT] = DRV_STS_FUNC_ON; + return iRet; +} + +static INT32 opfunc_stp_rst(P_WMT_OP pWmtOp) +{ + + return 0; +} + +static INT32 opfunc_therm_ctrl(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + WMT_THERM_CMD[4] = pWmtOp->au4OpData[0]; /*CMD type, refer to ENUM_WMTTHERM_TYPE_T */ + + /* send command */ + /* iRet = (*kal_stp_tx)(WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res); */ + iRet = wmt_core_tx((PUINT8) WMT_THERM_CMD, osal_sizeof(WMT_THERM_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_THERM_CMD))) { + WMT_ERR_FUNC("WMT-CORE: THERM_CTRL_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, + osal_sizeof(WMT_THERM_CMD)); + return iRet; + } + + evtLen = 16; + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || ((u4Res != osal_sizeof(WMT_THERM_CTRL_EVT)) && (u4Res != osal_sizeof(WMT_THERM_READ_EVT)))) { + WMT_ERR_FUNC("WMT-CORE: read THERM_CTRL_EVT/THERM_READ_EVENT fail(%d) len(%d, %d)\n", iRet, u4Res, + evtLen); + mtk_wcn_stp_dbg_dump_package(); + return iRet; + } + if (u4Res == osal_sizeof(WMT_THERM_CTRL_EVT)) { + if (osal_memcmp(evtBuf, WMT_THERM_CTRL_EVT, osal_sizeof(WMT_THERM_CTRL_EVT)) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_CTRL_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], + osal_sizeof(WMT_THERM_CTRL_EVT), WMT_THERM_CTRL_EVT[0], WMT_THERM_CTRL_EVT[1], + WMT_THERM_CTRL_EVT[2], WMT_THERM_CTRL_EVT[3], WMT_THERM_CTRL_EVT[4]); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_FALSE; /*will return to function driver */ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_DBG_FUNC("Send WMT_THERM_CTRL_CMD command OK!\n"); + pWmtOp->au4OpData[1] = MTK_WCN_BOOL_TRUE; /*will return to function driver */ + } + } else { + /*no need to judge the real thermal value */ + if (osal_memcmp(evtBuf, WMT_THERM_READ_EVT, osal_sizeof(WMT_THERM_READ_EVT) - 1) != 0) { + WMT_ERR_FUNC("WMT-CORE: compare WMT_THERM_READ_EVT error\n"); + WMT_ERR_FUNC("WMT-CORE: rx(%d):[%02X,%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X]\n", + u4Res, evtBuf[0], evtBuf[1], evtBuf[2], evtBuf[3], evtBuf[4], evtBuf[5], + osal_sizeof(WMT_THERM_READ_EVT), WMT_THERM_READ_EVT[0], WMT_THERM_READ_EVT[1], + WMT_THERM_READ_EVT[2], WMT_THERM_READ_EVT[3]); + pWmtOp->au4OpData[1] = 0xFF; /*will return to function driver */ + mtk_wcn_stp_dbg_dump_package(); + } else { + WMT_DBG_FUNC("Send WMT_THERM_READ_CMD command OK!\n"); + pWmtOp->au4OpData[1] = evtBuf[5]; /*will return to function driver */ + } + } + + return iRet; + +} + +static INT32 opfunc_efuse_rw(P_WMT_OP pWmtOp) +{ + + INT32 iRet = -1; + UINT32 u4Res; + UINT32 evtLen; + UINT8 evtBuf[16] = { 0 }; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: wmt_efuse_rw fail: chip is powered off\n"); + return -1; + } + + WMT_EFUSE_CMD[4] = (pWmtOp->au4OpData[0]) ? 0x1 : 0x2; /* w:2, r:1 */ + osal_memcpy(&WMT_EFUSE_CMD[6], (PUINT8) &pWmtOp->au4OpData[1], 2); /* address */ + osal_memcpy(&WMT_EFUSE_CMD[8], (PUINT32) pWmtOp->au4OpData[2], 4); /* value */ + + wmt_core_dump_data(&WMT_EFUSE_CMD[0], "efuse_cmd", osal_sizeof(WMT_EFUSE_CMD)); + + /* send command */ + /* iRet = (*kal_stp_tx)(WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res); */ + iRet = wmt_core_tx((PUINT8) WMT_EFUSE_CMD, osal_sizeof(WMT_EFUSE_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(WMT_EFUSE_CMD))) { + WMT_ERR_FUNC("WMT-CORE: EFUSE_CMD iRet(%d) cmd len err(%d, %d)\n", iRet, u4Res, + osal_sizeof(WMT_EFUSE_CMD)); + return iRet; + } + + evtLen = (pWmtOp->au4OpData[0]) ? osal_sizeof(WMT_EFUSE_EVT) : osal_sizeof(WMT_EFUSE_EVT); + + iRet = wmt_core_rx(evtBuf, evtLen, &u4Res); + if (iRet || (u4Res != evtLen)) + WMT_ERR_FUNC("WMT-CORE: read REG_EVB fail(%d) len(%d, %d)\n", iRet, u4Res, evtLen); + wmt_core_dump_data(&evtBuf[0], "efuse_evt", osal_sizeof(evtBuf)); + + return iRet; + +} + +static INT32 opfunc_gpio_ctrl(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + WMT_IC_PIN_ID id; + WMT_IC_PIN_STATE stat; + UINT32 flag; + + if (DRV_STS_FUNC_ON != gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_WMT]) { + WMT_ERR_FUNC("WMT-CORE: wmt_gpio_ctrl fail: chip is powered off\n"); + return -1; + } + + if (!gMtkWmtCtx.p_ic_ops->ic_pin_ctrl) { + WMT_ERR_FUNC("WMT-CORE: error, gMtkWmtCtx.p_ic_ops->ic_pin_ctrl(NULL)\n"); + return -1; + } + + id = pWmtOp->au4OpData[0]; + stat = pWmtOp->au4OpData[1]; + flag = pWmtOp->au4OpData[2]; + + WMT_INFO_FUNC("ic pin id:%d, stat:%d, flag:0x%x\n", id, stat, flag); + + iRet = (*(gMtkWmtCtx.p_ic_ops->ic_pin_ctrl)) (id, stat, flag); + + return iRet; +} + +MTK_WCN_BOOL wmt_core_is_quick_ps_support(void) +{ + P_WMT_CTX pctx = &gMtkWmtCtx; + + if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_quick_sleep)) + return (*(pctx->p_ic_ops->is_quick_sleep)) (); + + return MTK_WCN_BOOL_FALSE; +} + +MTK_WCN_BOOL wmt_core_get_aee_dump_flag(void) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_WMT_CTX pctx = &gMtkWmtCtx; + + if ((NULL != pctx->p_ic_ops) && (NULL != pctx->p_ic_ops->is_aee_dump_support)) + bRet = (*(pctx->p_ic_ops->is_aee_dump_support)) (); + else + bRet = MTK_WCN_BOOL_FALSE; + + return bRet; +} + +INT32 opfunc_pin_state(P_WMT_OP pWmtOp) +{ + + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + UINT32 iRet = 0; + + iRet = wmt_core_ctrl(WMT_CTRL_HW_STATE_DUMP, &ctrlPa1, &ctrlPa2); + return iRet; +} + +static INT32 opfunc_bgw_ds(P_WMT_OP pWmtOp) +{ + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT32 buf_len = 0; + UINT8 *buffer = NULL; + UINT8 evt_buffer[8] = { 0 }; + MTK_WCN_BOOL fgFail; + + UINT8 WMT_BGW_DESENSE_CMD[] = { + 0x01, 0x0e, 0x0f, 0x00, + 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 + }; + UINT8 WMT_BGW_DESENSE_EVT[] = { 0x02, 0x0e, 0x01, 0x00, 0x00 }; + + buf_len = pWmtOp->au4OpData[0]; + buffer = (PUINT8) pWmtOp->au4OpData[1]; + + osal_memcpy(&WMT_BGW_DESENSE_CMD[5], buffer, buf_len); + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = + wmt_core_tx(&WMT_BGW_DESENSE_CMD[0], osal_sizeof(WMT_BGW_DESENSE_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_BGW_DESENSE_CMD))) { + WMT_ERR_FUNC("bgw desense tx CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_BGW_DESENSE_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_BGW_DESENSE_EVT))) { + WMT_ERR_FUNC("bgw desense rx EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + break; + } + + if (osal_memcmp(evt_buffer, WMT_BGW_DESENSE_EVT, osal_sizeof(WMT_BGW_DESENSE_EVT)) != 0) { + WMT_ERR_FUNC + ("bgw desense WMT_BGW_DESENSE_EVT compare fail:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3], evt_buffer[4]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + return fgFail; +} + +static INT32 opfunc_set_mcu_clk(P_WMT_OP pWmtOp) +{ + UINT32 kind = 0; + INT32 iRet = -1; + UINT32 u4WrittenSize = 0; + UINT32 u4ReadSize = 0; + UINT8 evt_buffer[12] = { 0 }; + MTK_WCN_BOOL fgFail; + PUINT8 set_mcu_clk_str[] = { + "Enable MCU PLL", + "SET MCU CLK to 26M", + "SET MCU CLK to 37M", + "SET MCU CLK to 64M", + "SET MCU CLK to 69M", + "SET MCU CLK to 104M", + "SET MCU CLK to 118.857M", + "SET MCU CLK to 138.67M", + "Disable MCU PLL" + }; + UINT8 WMT_SET_MCU_CLK_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff + }; + UINT8 WMT_SET_MCU_CLK_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + + UINT8 WMT_EN_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00 }; /* enable pll clk */ + UINT8 WMT_26_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x00, 0x4d, 0x84, 0x00 }; /* set 26M */ + UINT8 WMT_37_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1e, 0x4d, 0x84, 0x00 }; /* set 37.8M */ + UINT8 WMT_64_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1d, 0x4d, 0x84, 0x00 }; /* set 64M */ + UINT8 WMT_69_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x1c, 0x4d, 0x84, 0x00 }; /* set 69M */ + UINT8 WMT_104_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5b, 0x4d, 0x84, 0x00 }; /* set 104M */ + UINT8 WMT_108_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x5a, 0x4d, 0x84, 0x00 }; /* set 118.857M */ + UINT8 WMT_138_MCU_CLK_CMD[] = { 0x0c, 0x01, 0x00, 0x80, 0x59, 0x4d, 0x84, 0x00 }; /* set 138.67M */ + UINT8 WMT_DIS_MCU_CLK_CMD[] = { 0x34, 0x03, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00 }; /* disable pll clk */ + + kind = pWmtOp->au4OpData[0]; + WMT_INFO_FUNC("do %s\n", set_mcu_clk_str[kind]); + + switch (kind) { + case 0: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_EN_MCU_CLK_CMD[0], osal_sizeof(WMT_EN_MCU_CLK_CMD)); + break; + case 1: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_26_MCU_CLK_CMD[0], osal_sizeof(WMT_26_MCU_CLK_CMD)); + break; + case 2: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_37_MCU_CLK_CMD[0], osal_sizeof(WMT_37_MCU_CLK_CMD)); + break; + case 3: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_64_MCU_CLK_CMD[0], osal_sizeof(WMT_64_MCU_CLK_CMD)); + break; + case 4: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_69_MCU_CLK_CMD[0], osal_sizeof(WMT_69_MCU_CLK_CMD)); + break; + case 5: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_104_MCU_CLK_CMD[0], osal_sizeof(WMT_104_MCU_CLK_CMD)); + break; + case 6: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_108_MCU_CLK_CMD[0], osal_sizeof(WMT_108_MCU_CLK_CMD)); + break; + case 7: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_138_MCU_CLK_CMD[0], osal_sizeof(WMT_138_MCU_CLK_CMD)); + break; + case 8: + osal_memcpy(&WMT_SET_MCU_CLK_CMD[8], &WMT_DIS_MCU_CLK_CMD[0], osal_sizeof(WMT_DIS_MCU_CLK_CMD)); + break; + default: + WMT_ERR_FUNC("unknown kind\n"); + break; + } + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + iRet = + wmt_core_tx(&WMT_SET_MCU_CLK_CMD[0], osal_sizeof(WMT_SET_MCU_CLK_CMD), &u4WrittenSize, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4WrittenSize != osal_sizeof(WMT_SET_MCU_CLK_CMD))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_CMD fail(%d),size(%d)\n", iRet, u4WrittenSize); + break; + } + + iRet = wmt_core_rx(evt_buffer, osal_sizeof(WMT_SET_MCU_CLK_EVT), &u4ReadSize); + if (iRet || (u4ReadSize != osal_sizeof(WMT_SET_MCU_CLK_EVT))) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT fail(%d),size(%d)\n", iRet, u4ReadSize); + break; + } + + if (osal_memcmp(evt_buffer, WMT_SET_MCU_CLK_EVT, osal_sizeof(WMT_SET_MCU_CLK_EVT)) != 0) { + WMT_ERR_FUNC("WMT_SET_MCU_CLK_EVT compare fail:0x%02x,0x%02x,0x%02x,0x%02x,0x%02x\n", + evt_buffer[0], evt_buffer[1], evt_buffer[2], evt_buffer[3], evt_buffer[4], + evt_buffer[5], evt_buffer[6], evt_buffer[7]); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + if (MTK_WCN_BOOL_FALSE == fgFail) + WMT_INFO_FUNC("wmt-core:%s: ok!\n", set_mcu_clk_str[kind]); + + WMT_INFO_FUNC("wmt-core:%s: fail!\n", set_mcu_clk_str[kind]); + + return fgFail; +} + +static INT32 opfunc_adie_lpbk_test(P_WMT_OP pWmtOp) +{ + UINT8 *buffer = NULL; + MTK_WCN_BOOL fgFail; + UINT32 u4Res; + UINT32 aDieChipid = 0; + UINT8 soc_adie_chipid_cmd[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; + UINT8 soc_adie_chipid_evt[] = { 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00 }; + UINT8 evtbuf[20]; + INT32 iRet = -1; + + buffer = (PUINT8) pWmtOp->au4OpData[1]; + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + /* read A die chipid by wmt cmd */ + iRet = + wmt_core_tx((PUINT8) &soc_adie_chipid_cmd[0], osal_sizeof(soc_adie_chipid_cmd), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_cmd))) { + WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); + break; + } + osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, osal_sizeof(soc_adie_chipid_evt), &u4Res); + if (iRet || (u4Res != osal_sizeof(soc_adie_chipid_evt))) { + WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); + break; + } + osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); + osal_memcpy(buffer, &evtbuf[u4Res - 2], 2); + pWmtOp->au4OpData[0] = 2; + WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + + return fgFail; +} + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 opfunc_idc_msg_handling(P_WMT_OP pWmtOp) +{ + MTK_WCN_BOOL fgFail; + UINT32 u4Res; + UINT8 host_lte_btwf_coex_cmd[] = { 0x01, 0x10, 0x00, 0x00, 0x00 }; + UINT8 host_lte_btwf_coex_evt[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + UINT8 *pTxBuf = NULL; + UINT8 evtbuf[8] = { 0 }; + INT32 iRet = -1; + UINT16 msg_len = 0; + UINT32 total_len = 0; + UINT32 index = 0; + UINT8 *msg_local_buffer = NULL; + + msg_local_buffer = kmalloc(1300, GFP_KERNEL); + if (!msg_local_buffer) { + WMT_ERR_FUNC("msg_local_buffer kmalloc memory fail\n"); + return 0; + } + + pTxBuf = (UINT8 *) pWmtOp->au4OpData[0]; + if (NULL == pTxBuf) { + WMT_ERR_FUNC("idc msg buffer is NULL\n"); + return -1; + } + iRet = wmt_lib_idc_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", iRet); + return iRet; + } + osal_memcpy(&msg_len, &pTxBuf[0], osal_sizeof(msg_len)); + if (msg_len > 1200) { + wmt_lib_idc_lock_release(); + WMT_ERR_FUNC("abnormal idc msg len:%d\n", msg_len); + return -2; + } + msg_len += 1; /*flag byte */ + + osal_memcpy(&host_lte_btwf_coex_cmd[2], &msg_len, 2); + host_lte_btwf_coex_cmd[4] = (pWmtOp->au4OpData[1] & 0x00ff); + osal_memcpy(&msg_local_buffer[0], &host_lte_btwf_coex_cmd[0], osal_sizeof(host_lte_btwf_coex_cmd)); + osal_memcpy(&msg_local_buffer[osal_sizeof(host_lte_btwf_coex_cmd)], + &pTxBuf[osal_sizeof(msg_len)], msg_len - 1); + + wmt_lib_idc_lock_release(); + total_len = osal_sizeof(host_lte_btwf_coex_cmd) + msg_len - 1; + + WMT_DBG_FUNC("wmt_core:idc msg payload len form lte(%d),wmt msg total len(%d)\n", msg_len - 1, + total_len); + WMT_DBG_FUNC("wmt_core:idc msg payload:\n"); + + for (index = 0; index < total_len; index++) + WMT_DBG_FUNC("0x%02x ", msg_local_buffer[index]); + + + do { + fgFail = MTK_WCN_BOOL_TRUE; + + /* read A die chipid by wmt cmd */ + iRet = wmt_core_tx((PUINT8) &msg_local_buffer[0], total_len, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != total_len)) { + WMT_ERR_FUNC("wmt_core:send lte idc msg to connsys fail(%d),size(%d)\n", iRet, u4Res); + break; + } + osal_memset(evtbuf, 0, osal_sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, osal_sizeof(host_lte_btwf_coex_evt), &u4Res); + if (iRet || (u4Res != osal_sizeof(host_lte_btwf_coex_evt))) { + WMT_ERR_FUNC("wmt_core:recv host_lte_btwf_coex_evt fail(%d),size(%d)\n", iRet, u4Res); + break; + } + + fgFail = MTK_WCN_BOOL_FALSE; + + } while (0); + kfree(msg_local_buffer); + return fgFail; +} +#endif + +VOID wmt_core_set_coredump_state(ENUM_DRV_STS state) +{ + WMT_INFO_FUNC("wmt-core: set coredump state(%d)\n", state); + gMtkWmtCtx.eDrvStatus[WMTDRV_TYPE_COREDUMP] = state; +} +#ifdef CONFIG_MTK_COMBO_ANT +INT32 opfunc_ant_ram_down(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + size_t ctrlPa1 = pWmtOp->au4OpData[0]; + UINT32 ctrlPa2 = pWmtOp->au4OpData[1]; + PUINT8 pbuf = (PUINT8) ctrlPa1; + UINT32 fragSeq = 0; + UINT16 fragSize = 0; + UINT16 wmtCmdLen; + UINT16 wmtPktLen; + UINT32 u4Res = 0; + UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_DWN_EVT)]; +#if 1 + UINT32 ctrlPa3 = pWmtOp->au4OpData[2]; + + do { + fragSize = ctrlPa2; + fragSeq = ctrlPa3; + gAntBuf[5] = fragSeq; + + + wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_DWN_CMD) + 1; + + /*WMT command length cal */ + wmtCmdLen = wmtPktLen - 4; +#if 0 + WMT_ANT_RAM_DWN_CMD[2] = wmtCmdLen & 0xFF; + WMT_ANT_RAM_DWN_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; +#else + osal_memcpy(&WMT_ANT_RAM_DWN_CMD[2], &wmtCmdLen, 2); +#endif + + + + WMT_ANT_RAM_DWN_CMD[4] = 1; /*RAM CODE download */ + + osal_memcpy(gAntBuf, WMT_ANT_RAM_DWN_CMD, sizeof(WMT_ANT_RAM_DWN_CMD)); + + /*copy ram code content to global buffer */ + osal_memcpy(&gAntBuf[osal_sizeof(WMT_ANT_RAM_DWN_CMD) + 1], pbuf, fragSize); + + iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + wmtPktLen, u4Res, iRet); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, wmtPktLen, u4Res); + + osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); + + WMT_ANT_RAM_DWN_EVT[4] = 0; /*download result; 0 */ + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_DWN_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_ANT_RAM_DWN_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_ANT_RAM_DWN_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_DWN_EVT, sizeof(WMT_ANT_RAM_DWN_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_DWN_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], + antEvtBuf[4], sizeof(WMT_ANT_RAM_DWN_EVT), WMT_ANT_RAM_DWN_EVT[0], + WMT_ANT_RAM_DWN_EVT[1], WMT_ANT_RAM_DWN_EVT[2], WMT_ANT_RAM_DWN_EVT[3], + WMT_ANT_RAM_DWN_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_ANT_RAM_DWN_EVT length(%zu, %d) ok\n", + sizeof(WMT_ANT_RAM_DWN_EVT), u4Res); + + } while (0); +#else + UINT32 patchSize = ctrlPa2; + UINT32 patchSizePerFrag = 1000; + UINT32 offset; + UINT32 fragNum = 0; + /*cal patch fragNum */ + fragNum = (patchSize + patchSizePerFrag - 1) / patchSizePerFrag; + if (2 >= fragNum) { + WMT_WARN_FUNC("ANT ramcode size(%d) too short\n", patchSize); + return -1; + } + + while (fragSeq < fragNum) { + /*update fragNum */ + fragSeq++; + + if (1 == fragSeq) { + fragSize = patchSizePerFrag; + /*first package */ + gAntBuf[5] = 1; /*RAM CODE start */ + } else if (fragNum == fragSeq) { + /*last package */ + fragSize = patchSizePerFrag; + gAntBuf[5] = 3; /*RAM CODE end */ + } else { + /*middle package */ + fragSize = patchSize - ((fragNum - 1) * patchSizePerFrag); + gAntBuf[5] = 2; /*RAM CODE confinue */ + } + wmtPktLen = fragSize + sizeof(WMT_ANT_RAM_OP_CMD) + 1; + + /*WMT command length cal */ + wmtCmdLen = wmtPktLen - 4; + + WMT_ANT_RAM_OP_CMD[2] = wmtCmdLen & 0xFF; + WMT_ANT_RAM_OP_CMD[3] = (wmtCmdLen & 0xFF00) >> 16; + + WMT_ANT_RAM_OP_CMD[4] = 1; /*RAM CODE download */ + + osal_memcpy(gAntBuf, WMT_ANT_RAM_OP_CMD, sizeof(WMT_ANT_RAM_OP_CMD)); + + /*copy ram code content to global buffer */ + osal_memcpy(&gAntBuf[6], pbuf, fragSize); + + /*update offset */ + offset += fragSize; + pbuf += offset; + + iRet = wmt_core_tx(gAntBuf, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + wmtPktLen, u4Res, iRet); + iRet = -4; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, wmtPktLen, u4Res); + + osal_memset(antEvtBuf, 0, sizeof(antEvtBuf)); + + WMT_SET_RAM_OP_EVT[4] = 0; /*download result; 0 */ + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_SET_RAM_OP_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_SET_RAM_OP_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) fail(%d)\n", + sizeof(WMT_SET_RAM_OP_EVT), u4Res, iRet); + iRet = -5; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_SET_RAM_OP_EVT, sizeof(WMT_SET_RAM_OP_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_SET_RAM_OP_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], + antEvtBuf[4], sizeof(WMT_SET_RAM_OP_EVT), WMT_SET_RAM_OP_EVT[0], + WMT_SET_RAM_OP_EVT[1], WMT_SET_RAM_OP_EVT[2], WMT_SET_RAM_OP_EVT[3], + WMT_SET_RAM_OP_EVT[4]); + iRet = -6; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_SET_RAM_OP_EVT length(%d, %d) ok\n", + sizeof(WMT_SET_RAM_OP_EVT), u4Res); + + + } + if (fragSeq != fragNum) + iRet = -7; +#endif + return iRet; +} + + +INT32 opfunc_ant_ram_stat_get(P_WMT_OP pWmtOp) +{ + INT32 iRet = 0; + UINT32 u4Res = 0; + UINT32 wmtPktLen = osal_sizeof(WMT_ANT_RAM_STA_GET_CMD); + UINT32 u4AntRamStatus = 0; + UINT8 antEvtBuf[osal_sizeof(WMT_ANT_RAM_STA_GET_EVT)]; + + + iRet = wmt_core_tx(WMT_ANT_RAM_STA_GET_CMD, wmtPktLen, &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != wmtPktLen)) { + WMT_ERR_FUNC + ("wmt_core: write wmt and ramcode status query command failed, (%d, %d), iRet(%d)\n", + wmtPktLen, u4Res, iRet); + iRet = -4; + return iRet; + } + + + iRet = wmt_core_rx(antEvtBuf, sizeof(WMT_ANT_RAM_STA_GET_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_ANT_RAM_STA_GET_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_ANT_RAM_STA_GET_EVT length(%zu, %d) fail(%d)\n", + sizeof(WMT_ANT_RAM_STA_GET_EVT), u4Res, iRet); + iRet = -5; + return iRet; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(antEvtBuf, WMT_ANT_RAM_STA_GET_EVT, sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1) != + 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_ANT_RAM_STA_GET_EVT result error\n"); + WMT_ERR_FUNC("rx(%d):[%02X,%02X,%02X,%02X,%02X] exp(%zu):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, antEvtBuf[0], antEvtBuf[1], antEvtBuf[2], antEvtBuf[3], antEvtBuf[4], + sizeof(WMT_ANT_RAM_STA_GET_EVT), WMT_ANT_RAM_STA_GET_EVT[0], + WMT_ANT_RAM_STA_GET_EVT[1], WMT_ANT_RAM_STA_GET_EVT[2], + WMT_ANT_RAM_STA_GET_EVT[3], WMT_ANT_RAM_STA_GET_EVT[4]); + iRet = -6; + return iRet; + } +#endif + if (0 == iRet) { + u4AntRamStatus = antEvtBuf[sizeof(WMT_ANT_RAM_STA_GET_EVT) - 1]; + pWmtOp->au4OpData[2] = u4AntRamStatus; + WMT_INFO_FUNC("ANT ram code %s\n", + 1 == u4AntRamStatus ? "exist already" : "not exist"); + } + return iRet; +} +#endif + +#if CFG_WMT_LTE_COEX_HANDLING +/*TEST CODE*/ +static UINT32 g_open_wmt_lte_flag; +VOID wmt_core_set_flag_for_test(UINT32 enable) +{ + WMT_INFO_FUNC("%s wmt_lte_flag\n", enable ? "enable" : "disable"); + g_open_wmt_lte_flag = enable; +} + +UINT32 wmt_core_get_flag_for_test(VOID) +{ + return g_open_wmt_lte_flag; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c new file mode 100644 index 0000000000000..fa603c208e59b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c @@ -0,0 +1,1019 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CTRL]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "osal.h" + +#include "wmt_ctrl.h" +#include "wmt_core.h" +#include "wmt_ic.h" +#include "wmt_lib.h" +#include "wmt_dev.h" +#include "wmt_plat.h" +#include "stp_core.h" +#include "stp_dbg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* moved to wmt_ctrl.h */ +/*static INT32 wmt_ctrl_tx_ex (UINT8 *pData, UINT32 size, UINT32 *writtenSize, MTK_WCN_BOOL bRawFlag);*/ + +static INT32 wmt_ctrl_stp_conf_ex(WMT_STP_CONF_TYPE type, UINT32 value); + +static INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA); +#if 0 +static INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA); +#endif +static INT32 wmt_ctrl_hwidver_set(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_others(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData); +static INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_soc_paldo_ctrl(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_evt_err_trg_assert(P_WMT_CTRL_DATA); +static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData); +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA); +#endif + +static INT32 wmt_ctrl_rx_flush(P_WMT_CTRL_DATA); + +static INT32 wmt_ctrl_gps_sync_set(P_WMT_CTRL_DATA pData); + +static INT32 wmt_ctrl_gps_lna_set(P_WMT_CTRL_DATA pData); + +static INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData); + +/* TODO: [FixMe][GeorgeKuo]: remove unused function */ +/*static INT32 wmt_ctrl_hwver_get(P_WMT_CTRL_DATA);*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* GeorgeKuo: Use designated initializers described in + * http://gcc.gnu.org/onlinedocs/gcc-4.0.4/gcc/Designated-Inits.html + */ +static const WMT_CTRL_FUNC wmt_ctrl_func[] = { + [WMT_CTRL_HW_PWR_OFF] = wmt_ctrl_hw_pwr_off, + [WMT_CTRL_HW_PWR_ON] = wmt_ctrl_hw_pwr_on, + [WMT_CTRL_HW_RST] = wmt_ctrl_hw_rst, + [WMT_CTRL_STP_CLOSE] = wmt_ctrl_stp_close, + [WMT_CTRL_STP_OPEN] = wmt_ctrl_stp_open, + [WMT_CTRL_STP_CONF] = wmt_ctrl_stp_conf, + [WMT_CTRL_FREE_PATCH] = wmt_ctrl_free_patch, + [WMT_CTRL_GET_PATCH] = wmt_ctrl_get_patch, + [WMT_CTRL_GET_PATCH_NAME] = wmt_ctrl_get_patch_name, + [WMT_CTRL_HWIDVER_SET] = wmt_ctrl_hwidver_set, + [WMT_CTRL_STP_RST] = wmt_ctrl_stp_rst, + [WMT_CTRL_GET_WMT_CONF] = wmt_ctrl_get_wmt_conf, + [WMT_CTRL_TX] = wmt_ctrl_tx, + [WMT_CTRL_RX] = wmt_ctrl_rx, + [WMT_CTRL_RX_FLUSH] = wmt_ctrl_rx_flush, + [WMT_CTRL_GPS_SYNC_SET] = wmt_ctrl_gps_sync_set, + [WMT_CTRL_GPS_LNA_SET] = wmt_ctrl_gps_lna_set, + [WMT_CTRL_PATCH_SEARCH] = wmt_ctrl_patch_search, + [WMT_CTRL_CRYSTAL_TRIMING_GET] = wmt_ctrl_crystal_triming_get, + [WMT_CTRL_CRYSTAL_TRIMING_PUT] = wmt_ctrl_crystal_triming_put, + [WMT_CTRL_HW_STATE_DUMP] = wmt_ctrl_hw_state_show, + [WMT_CTRL_GET_PATCH_NUM] = wmt_ctrl_get_patch_num, + [WMT_CTRL_GET_PATCH_INFO] = wmt_ctrl_get_patch_info, + [WMT_CTRL_SOC_PALDO_CTRL] = wmt_ctrl_soc_paldo_ctrl, + [WMT_CTRL_SOC_WAKEUP_CONSYS] = wmt_ctrl_soc_wakeup_consys, + [WMT_CTRL_SET_STP_DBG_INFO] = wmt_ctrl_set_stp_dbg_info, + [WMT_CTRL_BGW_DESENSE_CTRL] = wmt_ctrl_bgw_desense_ctrl, + [WMT_CTRL_EVT_ERR_TRG_ASSERT] = wmt_ctrl_evt_err_trg_assert, +#if CFG_WMT_LTE_COEX_HANDLING + [WMT_CTRL_GET_TDM_REQ_ANTSEL] = wmt_ctrl_get_tdm_req_antsel, +#endif + [WMT_CTRL_EVT_PARSER] = wmt_ctrl_evt_parser, + [WMT_CTRL_MAX] = wmt_ctrl_others, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 wmt_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 ctrlId; + + if (NULL == pWmtCtrlData) { + osal_assert(0); + return -1; + } + + ctrlId = pWmtCtrlData->ctrlId; + /*1sanity check, including wmtCtrlId */ + if ((NULL == pWmtCtrlData) + || (WMT_CTRL_MAX <= ctrlId)) + /* || (ctrlId < WMT_CTRL_HW_PWR_OFF) ) [FixMe][GeorgeKuo]: useless comparison */ + { + osal_assert(NULL != pWmtCtrlData); + osal_assert(WMT_CTRL_MAX > ctrlId); + /* osal_assert(ctrlId >= WMT_CTRL_HW_PWR_OFF); [FixMe][GeorgeKuo]: useless comparison */ + return -2; + } + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + if (wmt_ctrl_func[ctrlId]) { + /*call servicd handling API */ + return (*(wmt_ctrl_func[ctrlId])) (pWmtCtrlData); /* serviceHandlerPack[ctrlId].serviceHandler */ + } + osal_assert(NULL != wmt_ctrl_func[ctrlId]); + return -3; + +} + +INT32 wmt_ctrl_tx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pData, UINT32 size, UINT32 *writtenSize */) +{ + UINT8 *pData = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + UINT32 size = pWmtCtrlData->au4CtrlData[1]; + PUINT32 writtenSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + MTK_WCN_BOOL bRawFlag = pWmtCtrlData->au4CtrlData[3]; + + return wmt_ctrl_tx_ex(pData, size, writtenSize, bRawFlag); +} + +INT32 wmt_ctrl_rx(P_WMT_CTRL_DATA pWmtCtrlData /*UINT8 *pBuff, UINT32 buffLen, UINT32 *readSize */) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 readLen; + long waitRet = -1; + PUINT8 pBuff = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + UINT32 buffLen = pWmtCtrlData->au4CtrlData[1]; + PUINT32 readSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + + if (readSize) + *readSize = 0; + + /* sanity check */ + if (!buffLen) { + WMT_WARN_FUNC("buffLen = 0\n"); + osal_assert(buffLen); + return 0; + } +#if 0 + if (!pDev) { + WMT_WARN_FUNC("gpDevWmt = NULL\n"); + osal_assert(pDev); + return -1; + } +#endif + + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { + WMT_WARN_FUNC("state(0x%lx)\n", pDev->state); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + return -2; + } + + /* sanity ok, proceeding rx operation */ + /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + + while (readLen == 0) { /* got nothing, wait for STP's signal */ + WMT_LOUD_FUNC("before wmt_dev_rx_timeout\n"); + /* iRet = wait_event_interruptible(pdev->rWmtRxWq, osal_test_bit(WMT_STAT_RX, &pdev->state)); */ + /* waitRet = wait_event_interruptible_timeout( + * pDev->rWmtRxWq, + * osal_test_bit(WMT_STAT_RX, &pdev->state), + * msecs_to_jiffies(WMT_LIB_RX_TIMEOUT)); + */ + pDev->rWmtRxWq.timeoutValue = WMT_LIB_RX_TIMEOUT; + /* waitRet = osal_wait_for_event_bit_timeout(&pDev->rWmtRxWq, &pDev->state, WMT_STAT_RX); */ + waitRet = wmt_dev_rx_timeout(&pDev->rWmtRxWq); + + WMT_LOUD_FUNC("wmt_dev_rx_timeout returned\n"); + + if (0 == waitRet) { + WMT_ERR_FUNC("wmt_dev_rx_timeout: timeout,jiffies(%lu),timeoutvalue(%d)\n", + jiffies, pDev->rWmtRxWq.timeoutValue); + return -1; + } else if (waitRet < 0) { + WMT_WARN_FUNC("wmt_dev_rx_timeout: interrupted by signal (%ld)\n", waitRet); + return waitRet; + } + WMT_DBG_FUNC("wmt_dev_rx_timeout, iRet(%ld)\n", waitRet); + /* read_len = mtk_wcn_stp_receive_data(data, size, WMT_TASK_INDX); */ + readLen = mtk_wcn_stp_receive_data(pBuff, buffLen, WMT_TASK_INDX); + + if (0 == readLen) + WMT_WARN_FUNC("wmt_ctrl_rx be signaled, but no rx data(%ld)\n", waitRet); + + } + + if (readSize) + *readSize = readLen; + + return 0; + +} + +INT32 wmt_ctrl_tx_ex(const PUINT8 pData, const UINT32 size, PUINT32 writtenSize, const MTK_WCN_BOOL bRawFlag) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + + if (NULL != writtenSize) + *writtenSize = 0; + + /* sanity check */ + if (0 == size) { + WMT_WARN_FUNC("size to tx is 0\n"); + osal_assert(size); + return -1; + } + + /* if STP is not enabled yet, can't use this function. Use tx_raw instead */ + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state) || !osal_test_bit(WMT_STAT_STP_EN, &pDev->state)) { + WMT_ERR_FUNC("wmt state(0x%lx)\n", pDev->state); + osal_assert(osal_test_bit(WMT_STAT_STP_EN, &pDev->state)); + osal_assert(osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)); + return -2; + } + + /* sanity ok, proceeding tx operation */ + /*retval = mtk_wcn_stp_send_data(data, size, WMTDRV_TYPE_WMT); */ + mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); + if (bRawFlag) + iRet = mtk_wcn_stp_send_data_raw(pData, size, WMT_TASK_INDX); + else + iRet = mtk_wcn_stp_send_data(pData, size, WMT_TASK_INDX); + + if (iRet != size) { + WMT_WARN_FUNC("write(%d) written(%d)\n", size, iRet); + osal_assert(iRet == size); + } + + if (writtenSize) + *writtenSize = iRet; + + return 0; + +} + +INT32 wmt_ctrl_rx_flush(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 type = pWmtCtrlData->au4CtrlData[0]; + + WMT_INFO_FUNC("flush rx %d queue\n", type); + mtk_wcn_stp_flush_rx_queue(type); + + return 0; +} + +INT32 wmt_ctrl_hw_pwr_off(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iret; + +/*psm should be disabled before wmt_ic_deinit*/ + P_DEV_WMT pDev = &gDevWmt; + + if (osal_test_and_clear_bit(WMT_STAT_PWR, &pDev->state)) { + WMT_DBG_FUNC("on->off\n"); + iret = wmt_plat_pwr_ctrl(FUNC_OFF); + } else { + WMT_WARN_FUNC("already off\n"); + iret = 0; + } + + return iret; +} + +INT32 wmt_ctrl_hw_pwr_on(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iret; + /*psm should be enabled right after wmt_ic_init */ + P_DEV_WMT pDev = &gDevWmt; + if (osal_test_and_set_bit(WMT_STAT_PWR, &pDev->state)) { + WMT_WARN_FUNC("already on\n"); + iret = 0; + } else { + WMT_DBG_FUNC("off->on\n"); + iret = wmt_plat_pwr_ctrl(FUNC_ON); + } + + return iret; +} + +INT32 wmt_ctrl_ul_cmd(P_DEV_WMT pWmtDev, const UINT8 *pCmdStr) +{ + INT32 waitRet = -1; + P_OSAL_SIGNAL pCmdSignal; + P_OSAL_EVENT pCmdReq; + + if (osal_test_and_set_bit(WMT_STAT_CMD, &pWmtDev->state)) { + WMT_WARN_FUNC("cmd buf is occupied by (%s)\n", pWmtDev->cCmd); + return -1; + } + + /* indicate baud rate change to user space app */ +#if 0 + INIT_COMPLETION(pWmtDev->cmd_comp); + pWmtDev->cmd_result = -1; + strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); + pWmtDev->cCmd[NAME_MAX] = '\0'; + wake_up_interruptible(&pWmtDev->cmd_wq); +#endif + + pCmdSignal = &pWmtDev->cmdResp; + osal_signal_init(pCmdSignal); + pCmdSignal->timeoutValue = 2000; + osal_strncpy(pWmtDev->cCmd, pCmdStr, NAME_MAX); + pWmtDev->cCmd[NAME_MAX] = '\0'; + + pCmdReq = &pWmtDev->cmdReq; + + osal_trigger_event(&pWmtDev->cmdReq); + WMT_DBG_FUNC("str(%s) request ok\n", pCmdStr); + +/* waitRet = wait_for_completion_interruptible_timeout(&pWmtDev->cmd_comp, msecs_to_jiffies(2000)); */ + waitRet = osal_wait_for_signal_timeout(pCmdSignal); + WMT_LOUD_FUNC("wait signal iRet:%d\n", waitRet); + if (0 == waitRet) { + WMT_ERR_FUNC("wait signal timeout\n"); + return -2; + } + + WMT_DBG_FUNC("str(%s) result(%d)\n", pCmdStr, pWmtDev->cmdResult); + + return pWmtDev->cmdResult; +} + +INT32 wmt_ctrl_hw_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_RST); + return 0; +} + +INT32 wmt_ctrl_hw_state_show(P_WMT_CTRL_DATA pWmtCtrlData) +{ + wmt_plat_pwr_ctrl(FUNC_STAT); + return 0; +} + +INT32 wmt_ctrl_stp_close(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet = 0; + /* un-register to STP-core for rx */ + iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, NULL); /* mtk_wcn_stp_register_event_cb */ + if (iRet) { + WMT_WARN_FUNC("stp_reg cb unregister fail(%d)\n", iRet); + return -1; + } + + /*un-register rxcb to btif */ + iRet = mtk_wcn_stp_rxcb_register(NULL); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_rxcb_unregister fail(%d)\n", iRet); + return -2; + } + + iRet = mtk_wcn_stp_close_btif(); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_close_btif fail(%d)\n", iRet); + return -3; + } + osal_clear_bit(WMT_STAT_STP_OPEN, &pDev->state); + + return 0; +} + +INT32 wmt_ctrl_stp_open(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + + iRet = mtk_wcn_stp_open_btif(); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_open_btif fail(%d)\n", iRet); + return -1; + } + + /*register stp rx call back to btif */ + iRet = mtk_wcn_stp_rxcb_register((MTK_WCN_BTIF_RX_CB) mtk_wcn_stp_parser_data); + if (iRet) { + WMT_WARN_FUNC("mtk_wcn_stp_rxcb_register fail(%d)\n", iRet); + return -2; + } + /* register to STP-core for rx */ + iRet = mtk_wcn_stp_register_event_cb(WMT_TASK_INDX, wmt_dev_rx_event_cb); + if (iRet) { + WMT_WARN_FUNC("stp_reg cb fail(%d)\n", iRet); + return -3; + } + + osal_set_bit(WMT_STAT_STP_OPEN, &pDev->state); + +#if 0 + iRet = mtk_wcn_stp_lpbk_ctrl(1); +#endif + + return 0; +} + +INT32 wmt_ctrl_patch_search(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + INT32 iRet; + UINT8 cmdStr[NAME_MAX + 1] = { 0 }; + + osal_snprintf(cmdStr, NAME_MAX, "srh_patch"); + iRet = wmt_ctrl_ul_cmd(pDev, cmdStr); + if (iRet) { + WMT_WARN_FUNC("wmt_ctrl_ul_cmd fail(%d)\n", iRet); + return -1; + } + return 0; +} + +INT32 wmt_ctrl_get_patch_num(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + pWmtCtrlData->au4CtrlData[0] = pDev->patchNum; + return 0; +} + +INT32 wmt_ctrl_get_patch_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 downLoadSeq = 0; + P_WMT_PATCH_INFO pPatchinfo = NULL; + PUINT8 pNbuf = NULL; + PUINT8 pAbuf = NULL; + + downLoadSeq = pWmtCtrlData->au4CtrlData[0]; + WMT_DBG_FUNC("download seq is %d\n", downLoadSeq); + + pPatchinfo = pDev->pWmtPatchInfo + downLoadSeq - 1; + pNbuf = (PUINT8) pWmtCtrlData->au4CtrlData[1]; + pAbuf = (PUINT8) pWmtCtrlData->au4CtrlData[2]; + if (pPatchinfo) { + osal_memcpy(pNbuf, pPatchinfo->patchName, osal_sizeof(pPatchinfo->patchName)); + osal_memcpy(pAbuf, pPatchinfo->addRess, osal_sizeof(pPatchinfo->addRess)); + WMT_DBG_FUNC("get 4 address bytes is 0x%2x,0x%2x,0x%2x,0x%2x", pAbuf[0], pAbuf[1], pAbuf[2], pAbuf[3]); + } else { + WMT_ERR_FUNC("NULL patchinfo pointer\n"); + } + + return 0; +} + +INT32 wmt_ctrl_soc_paldo_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + ENUM_PALDO_TYPE ept = pWmtCtrlData->au4CtrlData[0]; + ENUM_PALDO_OP epo = pWmtCtrlData->au4CtrlData[1]; + + WMT_DBG_FUNC("ept(%d),epo(%d)\n", ept, epo); + iRet = wmt_plat_soc_paldo_ctrl(ept, epo); + if (iRet) { + if (PMIC_CHIPID_PALDO == ept) { + /* special handling for PMIC CHIPID */ + pWmtCtrlData->au4CtrlData[2] = iRet; + } else { + /* for other PA handling */ + WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); + } + } + + return iRet; +} + +INT32 wmt_ctrl_soc_wakeup_consys(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + + iRet = mtk_wcn_stp_wakeup_consys(); + if (iRet) + WMT_ERR_FUNC("soc palod ctrl fail(%d)\n", iRet); + + return iRet; +} + +INT32 wmt_ctrl_stp_conf_ex(WMT_STP_CONF_TYPE type, UINT32 value) +{ + INT32 iRet = -1; + + switch (type) { + case WMT_STP_CONF_EN: + iRet = mtk_wcn_stp_enable(value); + break; + + case WMT_STP_CONF_RDY: + iRet = mtk_wcn_stp_ready(value); + break; + + case WMT_STP_CONF_MODE: + mtk_wcn_stp_set_mode(value); + iRet = 0; + break; + + default: + WMT_WARN_FUNC("invalid type(%d) value(%d)\n", type, value); + break; + } + return iRet; +} + +INT32 wmt_ctrl_stp_conf(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + UINT32 type; + UINT32 value; + + if (!osal_test_bit(WMT_STAT_STP_OPEN, &pDev->state)) { + WMT_WARN_FUNC("CTRL_STP_ENABLE but invalid Handle of WmtStp\n"); + return -1; + } + + type = pWmtCtrlData->au4CtrlData[0]; + value = pWmtCtrlData->au4CtrlData[1]; + iRet = wmt_ctrl_stp_conf_ex(type, value); + + if (!iRet) { + if (WMT_STP_CONF_EN == type) { + if (value) { + osal_set_bit(WMT_STAT_STP_EN, &pDev->state); + WMT_DBG_FUNC("enable STP\n"); + } else { + osal_clear_bit(WMT_STAT_STP_EN, &pDev->state); + WMT_DBG_FUNC("disable STP\n"); + } + } + } + + return iRet; +} + +INT32 wmt_ctrl_free_patch(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 patchSeq = pWmtCtrlData->au4CtrlData[0]; + + WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (NULL != gDevWmt.pPatch) + wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pPatch)); + + WMT_DBG_FUNC("AF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (patchSeq == gDevWmt.patchNum) { + WMT_DBG_FUNC("the %d patch has been download\n", patchSeq); + wmt_dev_patch_info_free(); + } + return 0; +} + +INT32 wmt_ctrl_get_patch_name(P_WMT_CTRL_DATA pWmtCtrlData) +{ + PUINT8 pBuf = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + + osal_memcpy(pBuf, gDevWmt.cPatchName, osal_sizeof(gDevWmt.cPatchName)); + return 0; +} + +INT32 wmt_ctrl_crystal_triming_put(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_DBG_FUNC("BF free patch, gDevWmt.pPatch(0x%08x)\n", gDevWmt.pPatch); + if (NULL != gDevWmt.pNvram) + wmt_dev_patch_put((osal_firmware **) &(gDevWmt.pNvram)); + + WMT_DBG_FUNC("AF free patch, gDevWmt.pNvram(0x%08x)\n", gDevWmt.pNvram); + return 0; +} + +INT32 wmt_ctrl_crystal_triming_get(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0x0; + PUINT8 pFileName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + PPUINT8 ppBuf = (PPUINT8) pWmtCtrlData->au4CtrlData[1]; + PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[2]; + + osal_firmware *pNvram = NULL; + + if ((NULL == pFileName) || (NULL == pSize)) { + WMT_ERR_FUNC("parameter error, pFileName(0x%08x), pSize(0x%08x)\n", pFileName, pSize); + iRet = -1; + return iRet; + } + if (0 == wmt_dev_patch_get(pFileName, &pNvram, 0)) { + *ppBuf = (PUINT8) (pNvram)->data; + *pSize = (pNvram)->size; + gDevWmt.pNvram = pNvram; + return 0; + } + return -1; + +} + +INT32 wmt_ctrl_get_patch(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT8 *pFullPatchName = NULL; + UINT8 *pDefPatchName = NULL; + PUINT8 *ppBuf = (PUINT8 *) pWmtCtrlData->au4CtrlData[2]; + PUINT32 pSize = (PUINT32) pWmtCtrlData->au4CtrlData[3]; + + osal_firmware *pPatch = NULL; + + pFullPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[1]; + WMT_DBG_FUNC("BF get patch, pPatch(0x%08x)\n", pPatch); + if ((NULL != pFullPatchName) + && (0 == wmt_dev_patch_get(pFullPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM))) { + /*get full name patch success */ + WMT_DBG_FUNC("get full patch name(%s) buf(0x%p) size(%d)\n", + pFullPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); + *ppBuf = (PUINT8) (pPatch)->data; + *pSize = (pPatch)->size; + gDevWmt.pPatch = pPatch; + return 0; + } + + pDefPatchName = (PUINT8) pWmtCtrlData->au4CtrlData[0]; + if ((NULL != pDefPatchName) + && (0 == wmt_dev_patch_get(pDefPatchName, &pPatch, BCNT_PATCH_BUF_HEADROOM))) { + WMT_DBG_FUNC("get def patch name(%s) buf(0x%p) size(%d)\n", + pDefPatchName, (pPatch)->data, (pPatch)->size); + WMT_DBG_FUNC("AF get patch, pPatch(0x%08x)\n", pPatch); + /*get full name patch success */ + *ppBuf = (PUINT8) (pPatch)->data; + *pSize = (pPatch)->size; + gDevWmt.pPatch = pPatch; + return 0; + } + return -1; + +} + +/*do not need contol uart because B/G/F send/receive data by BTIF*/ +#if 0 +INT32 wmt_ctrl_host_baudrate_set(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + char cmdStr[NAME_MAX + 1] = { 0 }; + UINT32 u4Baudrate = pWmtCtrlData->au4CtrlData[0]; + UINT32 u4FlowCtrl = pWmtCtrlData->au4CtrlData[1]; + + WMT_DBG_FUNC("baud(%d), flowctrl(%d)\n", u4Baudrate, u4FlowCtrl); + + if (osal_test_bit(WMT_STAT_STP_OPEN, &gDevWmt.state)) { + osal_snprintf(cmdStr, NAME_MAX, "baud_%d_%d", u4Baudrate, u4FlowCtrl); + iRet = wmt_ctrl_ul_cmd(&gDevWmt, cmdStr); + if (iRet) { + WMT_WARN_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) fail(%d)\n", + u4Baudrate, pWmtCtrlData->au4CtrlData[1], iRet); + } else { + WMT_DBG_FUNC("CTRL_BAUDRATE baud(%d), flowctrl(%d) ok\n", u4Baudrate, u4FlowCtrl); + } + } else { + WMT_INFO_FUNC("CTRL_BAUDRATE but invalid Handle of WmtStp\n"); + } + return iRet; +} +#endif +/*do not need control SDIO because wifi send/receive data by sdio*/ +#if 0 +INT32 wmt_ctrl_sdio_hw(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = 0; + UINT32 statBit = WMT_STAT_SDIO1_ON; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + WMT_SDIO_SLOT_NUM sdioSlotNum = pWmtCtrlData->au4CtrlData[0]; + ENUM_FUNC_STATE funcState = pWmtCtrlData->au4CtrlData[1]; + + if ((WMT_SDIO_SLOT_INVALID == sdioSlotNum) + || (WMT_SDIO_SLOT_MAX <= sdioSlotNum)) { + WMT_WARN_FUNC("CTRL_SDIO_SLOT(%d) but invalid slot num\n", sdioSlotNum); + return -1; + } + + WMT_DBG_FUNC("WMT_CTRL_SDIO_HW (0x%x, %d)\n", sdioSlotNum, funcState); + + if (WMT_SDIO_SLOT_SDIO2 == sdioSlotNum) + statBit = WMT_STAT_SDIO2_ON; + + if (funcState) { + if (osal_test_and_set_bit(statBit, &pDev->state)) { + WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already ON\n", sdioSlotNum); + /* still return 0 */ + iRet = 0; + } else { + iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_ON); + } + } else { + if (osal_test_and_clear_bit(statBit, &pDev->state)) { + iRet = wmt_plat_sdio_ctrl(sdioSlotNum, FUNC_OFF); + } else { + WMT_WARN_FUNC("CTRL_SDIO_SLOT slotNum(%d) already OFF\n", sdioSlotNum); + /* still return 0 */ + iRet = 0; + } + } + + return iRet; +} + +INT32 wmt_ctrl_sdio_func(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + UINT32 statBit = WMT_STAT_SDIO_WIFI_ON; + INT32 retry = 10; + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + WMT_SDIO_FUNC_TYPE sdioFuncType = pWmtCtrlData->au4CtrlData[0]; + UINT32 u4On = pWmtCtrlData->au4CtrlData[1]; + + if (WMT_SDIO_FUNC_MAX <= sdioFuncType) { + WMT_ERR_FUNC("CTRL_SDIO_FUNC, invalid func type (%d)\n", sdioFuncType); + return -1; + } + + if (WMT_SDIO_FUNC_STP == sdioFuncType) + statBit = WMT_STAT_SDIO_STP_ON; + + if (u4On) { + if (osal_test_bit(statBit, &pDev->state)) { + WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already ON\n", sdioFuncType); + iRet = 0; + } else { + while (retry-- > 0 && iRet != 0) { + if (iRet) { + /* sleep 150ms before sdio slot ON ready */ + osal_sleep_ms(150); + } + iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_TRUE); + if (HIF_SDIO_ERR_NOT_PROBED == iRet) { + /* not probed case, retry */ + continue; + } else if (HIF_SDIO_ERR_CLT_NOT_REG == iRet) { + /* For WiFi, client not reg yet, no need to retry, + *WiFi function can work any time when wlan.ko + *is insert into system + */ + iRet = 0; + } else { + /* other fail cases, stop */ + break; + } + } + if (!retry || iRet) { + WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, TRUE) fail(%d) retry(%d)\n", + sdioFuncType, iRet, retry); + } else { + osal_set_bit(statBit, &pDev->state); + } + } + } else { + if (osal_test_bit(statBit, &pDev->state)) { + iRet = mtk_wcn_hif_sdio_wmt_control(sdioFuncType, MTK_WCN_BOOL_FALSE); + if (iRet) + WMT_ERR_FUNC("mtk_wcn_hif_sdio_wmt_control(%d, FALSE) fail(%d)\n", sdioFuncType, iRet); + /*any way, set to OFF state */ + osal_clear_bit(statBit, &pDev->state); + } else { + WMT_WARN_FUNC("CTRL_SDIO_FUNC(%d) but already OFF\n", sdioFuncType); + iRet = 0; + } + } + + return iRet; +} +#endif + + +INT32 wmt_ctrl_hwidver_set(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + /* input sanity check is done in wmt_ctrl() */ + pDev->chip_id = (pWmtCtrlData->au4CtrlData[0] & 0xFFFF0000) >> 16; + pDev->hw_ver = pWmtCtrlData->au4CtrlData[0] & 0x0000FFFF; + pDev->fw_ver = pWmtCtrlData->au4CtrlData[1] & 0x0000FFFF; + + /* TODO: [FixMe][GeorgeKuo] remove translated ENUM_WMTHWVER_TYPE_T in the future!!! */ + /* Only use hw_ver read from hw. */ + pDev->eWmtHwVer = (ENUM_WMTHWVER_TYPE_T) (pWmtCtrlData->au4CtrlData[1] & 0xFFFF0000) >> 16; + + return 0; +} + +INT32 wmt_ctrl_set_stp_dbg_info(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT8 *pRomVer = NULL; + P_WMT_PATCH pPatch = NULL; + UINT32 chipID = 0; + + chipID = pWmtCtrlData->au4CtrlData[0]; + pRomVer = (PUINT8) (pWmtCtrlData->au4CtrlData[1]); + pPatch = (P_WMT_PATCH) (pWmtCtrlData->au4CtrlData[2]); + if (!pRomVer) { + WMT_ERR_FUNC("pRomVer null pointer\n"); + return -1; + } + if (!pPatch) { + WMT_ERR_FUNC("pPatch null pointer\n"); + return -2; + } + WMT_DBG_FUNC("chipid(0x%x),rom(%s),patch date(%s),patch plat(%s)\n", chipID, pRomVer, pPatch->ucDateTime, + pPatch->ucPLat); + return stp_dbg_set_version_info(chipID, pRomVer, &(pPatch->ucDateTime[0]), &(pPatch->ucPLat[0])); +} + +static INT32 wmt_ctrl_bgw_desense_ctrl(P_WMT_CTRL_DATA pWmtCtrlData) +{ + UINT32 cmd = pWmtCtrlData->au4CtrlData[0]; + + WMT_INFO_FUNC("wmt-ctrl:send native cmd(%d)\n", cmd); + wmt_dev_send_cmd_to_daemon(cmd); + + return 0; +} + +static INT32 wmt_ctrl_evt_err_trg_assert(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 iRet = -1; + + ENUM_WMTDRV_TYPE_T drv_type; + UINT32 reason = 0; + + drv_type = pWmtCtrlData->au4CtrlData[0]; + reason = pWmtCtrlData->au4CtrlData[1]; + WMT_WARN_FUNC("wmt-ctrl:drv_type(%d),reason(%d)\n", drv_type, reason); + + if (0 == mtk_wcn_stp_get_wmt_evt_err_trg_assert()) { + mtk_wcn_stp_set_wmt_evt_err_trg_assert(1); + wmt_lib_set_host_assert_info(drv_type, reason, 1); + + iRet = mtk_wcn_stp_wmt_evt_err_trg_assert(); + if (iRet) + mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); + } else { + /* maybe assert triggered by stp noack*/ + WMT_INFO_FUNC("do trigger assert & chip reset in stp noack\n"); + } + return 0; +} + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_ctrl_get_tdm_req_antsel(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 antsel_index = wmt_plat_get_tdm_antsel_index(); + + if (0 <= antsel_index) + pWmtCtrlData->au4CtrlData[0] = antsel_index; + else + pWmtCtrlData->au4CtrlData[0] = 0xff; + + WMT_INFO_FUNC("get tdm req antsel index is %d\n", antsel_index); + + return 0; +} +#endif + +static INT32 wmt_ctrl_evt_parser(P_WMT_CTRL_DATA pWmtCtrlData) +{ + INT32 ret = -1; + UINT32 evt_idx = (UINT32) pWmtCtrlData->au4CtrlData[0]; + UINT8 *p_buf = NULL; + + static UINT8 sleep_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x01 }; + static UINT8 wakeup_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; + static UINT8 hostawake_evt[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x02 }; + static UINT8 *evt_array[] = { sleep_evt, wakeup_evt, hostawake_evt }; + + p_buf = evt_array[evt_idx - 1]; + + WMT_INFO_FUNC("evt index:%d,p_buf:%p\n", evt_idx, p_buf); + + ret = mtk_wcn_consys_stp_btif_parser_wmt_evt(p_buf, 6); + if (ret == 1) { + WMT_INFO_FUNC("parser wmt evt from BTIF buf is OK\n"); + return 0; + } + WMT_ERR_FUNC("parser wmt evt from BTIF buf fail(%d)\n", ret); + return -1; +} + +static INT32 wmt_ctrl_gps_sync_set(P_WMT_CTRL_DATA pData) +{ + INT32 iret; + + WMT_INFO_FUNC("ctrl GPS_SYNC(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); + iret = wmt_plat_gpio_ctrl(PIN_GPS_SYNC, (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX); + + if (iret) { + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_MUX, iret); + } + + return 0; +} + +static INT32 wmt_ctrl_gps_lna_set(P_WMT_CTRL_DATA pData) +{ + INT32 iret; + + WMT_INFO_FUNC("ctrl GPS_LNA(%d)\n", (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + iret = wmt_plat_gpio_ctrl(PIN_GPS_LNA, (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H); + + if (iret) { + WMT_WARN_FUNC("ctrl GPS_SYNC(%d) fail!(%d) ignore it...\n", + (0 == pData->au4CtrlData[0]) ? PIN_STA_DEINIT : PIN_STA_OUT_H, iret); + } + + return 0; +} + +INT32 wmt_ctrl_stp_rst(P_WMT_CTRL_DATA pWmtCtrlData) +{ + return 0; +} + +INT32 wmt_ctrl_get_wmt_conf(P_WMT_CTRL_DATA pWmtCtrlData) +{ + P_DEV_WMT pDev = &gDevWmt; /* single instance */ + + pWmtCtrlData->au4CtrlData[0] = (SIZE_T) &pDev->rWmtGenConf; + + return 0; +} + +INT32 wmt_ctrl_others(P_WMT_CTRL_DATA pWmtCtrlData) +{ + WMT_ERR_FUNC("wmt_ctrl_others, invalid CTRL ID (%d)\n", pWmtCtrlData->ctrlId); + return -1; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c new file mode 100644 index 0000000000000..d42d572c92922 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_func.c @@ -0,0 +1,713 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-FUNC]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_func.h" +#include "wmt_lib.h" +#include "wmt_core.h" +#include "wmt_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if CFG_FUNC_BT_SUPPORT + +static INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_bt_ops = { + /* BT subsystem function on/off */ + .func_on = wmt_func_bt_on, + .func_off = wmt_func_bt_off +}; +#endif + +#if CFG_FUNC_FM_SUPPORT + +static INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_fm_ops = { + /* FM subsystem function on/off */ + .func_on = wmt_func_fm_on, + .func_off = wmt_func_fm_off +}; +#endif + +#if CFG_FUNC_GPS_SUPPORT + +static INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_gps_ops = { + /* GPS subsystem function on/off */ + .func_on = wmt_func_gps_on, + .func_off = wmt_func_gps_off +}; + +#endif + +#if CFG_FUNC_WIFI_SUPPORT +static INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); +static INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf); + +WMT_FUNC_OPS wmt_func_wifi_ops = { + /* Wi-Fi subsystem function on/off */ + .func_on = wmt_func_wifi_on, + .func_off = wmt_func_wifi_off +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_FUNC_GPS_SUPPORT +CMB_PIN_CTRL_REG eediPinOhRegs[] = { + { + /* pull down ctrl register */ + .regAddr = 0x80050020, + .regValue = ~(0x1 << 5), + .regMask = 0x00000020, + }, + { + /* pull up ctrl register */ + .regAddr = 0x80050000, + .regValue = 0x1 << 5, + .regMask = 0x00000020, + }, + { + /* iomode ctrl register */ + .regAddr = 0x80050110, + .regValue = 0x1 << 0, + .regMask = 0x00000007, + }, + { + /* output high/low ctrl register */ + .regAddr = 0x80050040, + .regValue = 0x1 << 5, + .regMask = 0x00000020, + } + +}; + +CMB_PIN_CTRL_REG eediPinOlRegs[] = { + { + .regAddr = 0x80050020, + .regValue = 0x1 << 5, + .regMask = 0x00000020UL, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1 << 5), + .regMask = 0x00000020, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1 << 0, + .regMask = 0x00000007, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1 << 5), + .regMask = 0x00000020, + } +}; + +CMB_PIN_CTRL_REG eedoPinOhRegs[] = { + { + .regAddr = 0x80050020, + .regValue = ~(0x1 << 7), + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050000, + .regValue = 0x1 << 7, + .regMask = 0x00000080UL, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1 << 12, + .regMask = 0x00007000UL, + }, + { + .regAddr = 0x80050040, + .regValue = 0x1 << 7, + .regMask = 0x00000080, + } +}; + +CMB_PIN_CTRL_REG eedoPinOlRegs[] = { + { + .regAddr = 0x80050020, + .regValue = 0x1 << 7, + .regMask = 0x00000080, + }, + { + .regAddr = 0x80050000, + .regValue = ~(0x1 << 7), + .regMask = 0x00000080, + }, + { + .regAddr = 0x80050110, + .regValue = 0x1 << 12, + .regMask = 0x00007000, + }, + { + .regAddr = 0x80050040, + .regValue = ~(0x1 << 7), + .regMask = 0x00000080, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOnRegs[] = { + { + .regAddr = 0x80050110, + .regValue = 0x3 << 20, + .regMask = 0x7 << 20, + } + +}; + +CMB_PIN_CTRL_REG gsyncPinOffRegs[] = { + { + .regAddr = 0x80050110, + .regValue = 0x0 << 20, + .regMask = 0x7 << 20, + } +}; + +/* templete usage for GPIO control */ +CMB_PIN_CTRL gCmbPinCtrl[3] = { + { + .pinId = CMB_PIN_EEDI_ID, + .regNum = 4, + .pFuncOnArray = eediPinOhRegs, + .pFuncOffArray = eediPinOlRegs, + }, + { + .pinId = CMB_PIN_EEDO_ID, + .regNum = 4, + .pFuncOnArray = eedoPinOhRegs, + .pFuncOffArray = eedoPinOlRegs, + }, + { + .pinId = CMB_PIN_GSYNC_ID, + .regNum = 1, + .pFuncOnArray = gsyncPinOnRegs, + .pFuncOffArray = gsyncPinOffRegs, + } +}; +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#if CFG_FUNC_BT_SUPPORT + +INT32 _osal_inline_ wmt_func_bt_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn BT subsystem wmt command */ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_bt_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + /* return wmt_func_bt_ctrl(FUNC_ON); */ + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl failed(%d)(%d)(%d)\n", iRet, ctrlPa1, ctrlPa2); + return -1; + } + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_TRUE); + if (iRet) { + WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_on) failed(%d)\n", iRet); + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + /*do coredump when bt on fail */ + wmt_core_set_coredump_state(DRV_STS_FUNC_ON); + ctrlPa1 = WMTDRV_TYPE_BT; + ctrlPa2 = 32; + wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &ctrlPa1, &ctrlPa2); + return -2; + } + osal_set_bit(WMT_BT_ON, &gBtWifiGpsState); + if (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState)) { + /* send msg to GPS native for sending de-sense CMD */ + ctrlPa1 = 1; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + return 0; +} + +INT32 wmt_func_bt_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + /* return wmt_func_bt_ctrl(FUNC_OFF); */ + INT32 iRet1 = -1; + INT32 iRet2 = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + iRet1 = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_BT, MTK_WCN_BOOL_FALSE); + if (iRet1) + WMT_ERR_FUNC("wmt-func: wmt_core_func_ctrl_cmd(bt_off) failed(%d)\n", iRet1); + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet2 = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + if (iRet2) + WMT_ERR_FUNC("wmt-func: wmt_ctrl_soc_paldo_ctrl(bt_off) failed(%d)\n", iRet2); + + if (iRet1 + iRet2) { + /*do coredump when bt off fail */ + wmt_core_set_coredump_state(DRV_STS_FUNC_ON); + ctrlPa1 = WMTDRV_TYPE_BT; + ctrlPa2 = 32; + wmt_core_ctrl(WMT_CTRL_EVT_ERR_TRG_ASSERT, &ctrlPa1, &ctrlPa2); + return -1; + } + + osal_clear_bit(WMT_BT_ON, &gBtWifiGpsState); + if ((!osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState)) && (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState))) { + /* send msg to GPS native for stopping send de-sense CMD */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + return 0; +} + +#endif + +#if CFG_FUNC_GPS_SUPPORT + +INT32 _osal_inline_ wmt_func_gps_ctrl(ENUM_FUNC_STATE funcState) +{ + /*send turn GPS subsystem wmt command */ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_GPS, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_gps_pre_ctrl(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf, ENUM_FUNC_STATE funcStatus) +{ + UINT32 i = 0; + INT32 iRet = 0; + UINT32 regAddr = 0; + UINT32 regValue = 0; + UINT32 regMask = 0; + UINT32 regNum = 0; + P_CMB_PIN_CTRL_REG pReg; + P_CMB_PIN_CTRL pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; + WMT_CTRL_DATA ctrlData; + WMT_IC_PIN_ID wmtIcPinId = WMT_IC_PIN_MAX; + /* sanity check */ + if (FUNC_ON != funcStatus && FUNC_OFF != funcStatus) { + WMT_ERR_FUNC("invalid funcStatus(%d)\n", funcStatus); + return -1; + } + /* turn on GPS sync function on both side */ + ctrlData.ctrlId = WMT_CTRL_GPS_SYNC_SET; + ctrlData.au4CtrlData[0] = (FUNC_ON == funcStatus) ? 1 : 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /*we suppose this would never print */ + WMT_ERR_FUNC("ctrl GPS_SYNC_SET(%d) fail, ret(%d)\n", funcStatus, iRet); + /* TODO:[FixMe][George] error handling? */ + return -2; + } + WMT_INFO_FUNC("ctrl GPS_SYNC_SET(%d) ok\n", funcStatus); + + + if ((NULL == pOps->ic_pin_ctrl) || + (0 > pOps->ic_pin_ctrl( + WMT_IC_PIN_GSYNC, + FUNC_ON == funcStatus ? WMT_IC_PIN_MUX : WMT_IC_PIN_GPIO, + 1))) { /*WMT_IC_PIN_GSYNC */ + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_GSYNC_ID]; + regNum = pCmbPinCtrl->regNum; + for (i = 0; i < regNum; i++) { + if (FUNC_ON == funcStatus) + pReg = &pCmbPinCtrl->pFuncOnArray[i]; + else + pReg = &pCmbPinCtrl->pFuncOffArray[i]; + + regAddr = pReg->regAddr; + regValue = pReg->regValue; + regMask = pReg->regMask; + + iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC("set reg for GPS_SYNC function fail(%d)\n", iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -2; + } + + } + } else { + WMT_INFO_FUNC("set reg for GPS_SYNC function okay by chip ic_pin_ctrl\n"); + } + WMT_INFO_FUNC("ctrl combo chip gps sync function succeed\n"); + /* turn on GPS lna ctrl function */ + if (NULL != pConf) { + if (0 == pConf->wmt_gps_lna_enable) { + + WMT_INFO_FUNC("host pin used for gps lna\n"); + /* host LNA ctrl pin needed */ + ctrlData.ctrlId = WMT_CTRL_GPS_LNA_SET; + ctrlData.au4CtrlData[0] = FUNC_ON == funcStatus ? 1 : 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + /*we suppose this would never print */ + WMT_ERR_FUNC("ctrl host GPS_LNA output high fail, ret(%d)\n", iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -3; + } + WMT_INFO_FUNC("ctrl host gps lna function succeed\n"); + } else { + WMT_INFO_FUNC("combo chip pin(%s) used for gps lna\n", + 0 == pConf->wmt_gps_lna_pin ? "EEDI" : "EEDO"); + wmtIcPinId = 0 == pConf->wmt_gps_lna_pin ? WMT_IC_PIN_EEDI : WMT_IC_PIN_EEDO; + if ((NULL == pOps->ic_pin_ctrl) || + (0 > pOps->ic_pin_ctrl( + wmtIcPinId, + FUNC_ON == funcStatus ? WMT_IC_PIN_GPIO_HIGH : WMT_IC_PIN_GPIO_LOW, + 1))) { /*WMT_IC_PIN_GSYNC */ + if (0 == pConf->wmt_gps_lna_pin) { + /* EEDI needed */ + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDI_ID]; + } else if (1 == pConf->wmt_gps_lna_pin) { + /* EEDO needed */ + pCmbPinCtrl = &gCmbPinCtrl[CMB_PIN_EEDO_ID]; + } + regNum = pCmbPinCtrl->regNum; + for (i = 0; i < regNum; i++) { + if (FUNC_ON == funcStatus) + pReg = &pCmbPinCtrl->pFuncOnArray[i]; + else + pReg = &pCmbPinCtrl->pFuncOffArray[i]; + regAddr = pReg->regAddr; + regValue = pReg->regValue; + regMask = pReg->regMask; + + iRet = wmt_core_reg_rw_raw(1, regAddr, ®Value, regMask); + if (iRet) { + WMT_ERR_FUNC("set reg for GPS_LNA function fail(%d)\n", iRet); + /* TODO:[FixMe][Chaozhong] error handling? */ + return -3; + } + } + WMT_INFO_FUNC("ctrl combo chip gps lna succeed\n"); + } else { + WMT_INFO_FUNC("set reg for GPS_LNA function okay by chip ic_pin_ctrl\n"); + } + } + } + return 0; + +} + +INT32 wmt_func_gps_pre_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_ON); +} + +INT32 wmt_func_gps_pre_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + + return wmt_func_gps_pre_ctrl(pOps, pConf, FUNC_OFF); +} + +INT32 wmt_func_gps_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) { /* use SOC external LNA */ + if (!osal_test_bit(WMT_FM_ON, &gGpsFmState)) { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_INFO_FUNC("LDO VCN28 has been turn on by FM\n"); + } + } + + iRet = wmt_func_gps_pre_on(pOps, pConf); + if (0 == iRet) { + iRet = wmt_func_gps_ctrl(FUNC_ON); + if (!iRet) { + osal_set_bit(WMT_GPS_ON, &gBtWifiGpsState); + if ((osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) + || (osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState))) { + /* send msg to GPS native for sending de-sense CMD */ + ctrlPa1 = 1; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + + if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) /* use SOC external LNA */ + osal_set_bit(WMT_GPS_ON, &gGpsFmState); + } + } + return iRet; +} + +INT32 wmt_func_gps_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + iRet = wmt_func_gps_pre_off(pOps, pConf); + if (0 == iRet) { + iRet = wmt_func_gps_ctrl(FUNC_OFF); + if (!iRet) { + osal_clear_bit(WMT_GPS_ON, &gBtWifiGpsState); + if ((osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) + || (osal_test_bit(WMT_WIFI_ON, &gBtWifiGpsState))) { + /* send msg to GPS native for stop sending de-sense CMD */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + } + } + + if ((co_clock_type) && (0 == pConf->wmt_gps_lna_enable)) { /* use SOC external LNA */ + if (osal_test_bit(WMT_FM_ON, &gGpsFmState)) + WMT_INFO_FUNC("FM is still on, do not turn off LDO VCN28\n"); + else { + ctrlPa1 = GPS_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } + + osal_clear_bit(WMT_GPS_ON, &gGpsFmState); + } + + return iRet; + +} +#endif + +#if CFG_FUNC_FM_SUPPORT + +INT32 _osal_inline_ wmt_func_fm_ctrl(ENUM_FUNC_STATE funcState) +{ + /*only need to send turn FM subsystem wmt command */ + return wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, (FUNC_ON == funcState) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); +} + +INT32 wmt_func_fm_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + /* return wmt_func_fm_ctrl(FUNC_ON); */ + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + INT32 iRet = -1; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + if (co_clock_type) { + if (!osal_test_bit(WMT_GPS_ON, &gGpsFmState)) { + ctrlPa1 = FM_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_INFO_FUNC("LDO VCN28 has been turn on by GPS\n"); + } + } + + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_TRUE); + if (!iRet) { + if (co_clock_type) + osal_set_bit(WMT_FM_ON, &gGpsFmState); + } + + return iRet; +} + +INT32 wmt_func_fm_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + /* return wmt_func_fm_ctrl(FUNC_OFF); */ + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + INT32 iRet = -1; + UINT8 co_clock_type = (pConf->co_clock_flag & 0x0f); + + iRet = wmt_core_func_ctrl_cmd(WMTDRV_TYPE_FM, MTK_WCN_BOOL_FALSE); + + if (co_clock_type) { + if (osal_test_bit(WMT_GPS_ON, &gGpsFmState)) { + WMT_INFO_FUNC("GPS is still on, do not turn off LDO VCN28\n"); + } else { + ctrlPa1 = FM_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } + + osal_clear_bit(WMT_FM_ON, &gGpsFmState); + } + + return iRet; +} + +#endif + +#if CFG_FUNC_WIFI_SUPPORT + +/*in soc, wmt turn on wifi directly, no not need operate SDIO*/ +#if 0 +INT32 wmt_func_wifi_ctrl(ENUM_FUNC_STATE funcState) +{ + INT32 iRet = 0; + unsigned long ctrlPa1 = WMT_SDIO_FUNC_WIFI; + unsigned long ctrlPa2 = (FUNC_ON == funcState) ? 1 : 0; /* turn on Wi-Fi driver */ + + iRet = wmt_core_ctrl(WMT_CTRL_SDIO_FUNC, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: turn on WIFI function fail (%d)", iRet); + return -1; + } + return 0; +} +#endif + +INT32 wmt_func_wifi_on(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + int iRet = 0; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + if (NULL != mtk_wcn_wlan_probe) { + + WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan probe\n"); + iRet = (*mtk_wcn_wlan_probe) (); + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: wmt call wlan probe fail(%d)\n", iRet); + iRet = -1; + } else { + WMT_WARN_FUNC("WMT-FUNC: wmt call wlan probe ok\n"); + } + } else { + WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_probe\n"); + gWifiProbed = 1; + iRet = -2; + } + + if (!iRet) { + osal_set_bit(WMT_WIFI_ON, &gBtWifiGpsState); + if (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState)) { + /* send msg to GPS native for sending de-sense CMD */ + ctrlPa1 = 1; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + } + return iRet; +#if 0 + return wmt_func_wifi_ctrl(FUNC_ON); +#endif +} + +INT32 wmt_func_wifi_off(P_WMT_IC_OPS pOps, P_WMT_GEN_CONF pConf) +{ + int iRet = 0; + + unsigned long ctrlPa1 = 0; + unsigned long ctrlPa2 = 0; + + if (NULL != mtk_wcn_wlan_remove) { + + WMT_WARN_FUNC("WMT-FUNC: wmt wlan func on before wlan remove\n"); + iRet = (*mtk_wcn_wlan_remove) (); + if (iRet) { + WMT_ERR_FUNC("WMT-FUNC: wmt call wlan remove fail(%d)\n", iRet); + iRet = -1; + } else { + WMT_WARN_FUNC("WMT-FUNC: wmt call wlan remove ok\n"); + } + } else { + WMT_ERR_FUNC("WMT-FUNC: null pointer mtk_wcn_wlan_remove\n"); + iRet = -2; + } + + if (!iRet) { + osal_clear_bit(WMT_WIFI_ON, &gBtWifiGpsState); + if ((!osal_test_bit(WMT_BT_ON, &gBtWifiGpsState)) && (osal_test_bit(WMT_GPS_ON, &gBtWifiGpsState))) { + /* send msg to GPS native for stopping send de-sense CMD */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_BGW_DESENSE_CTRL, &ctrlPa1, &ctrlPa2); + } + } + return iRet; +#if 0 + return wmt_func_wifi_ctrl(FUNC_OFF); +#endif +} +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c new file mode 100644 index 0000000000000..c07052bce8e6d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ic_soc.c @@ -0,0 +1,2452 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-IC]" +#define CFG_IC_SOC 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_ic.h" +#include "wmt_core.h" +#include "wmt_lib.h" +#include "stp_core.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define DEFAULT_PATCH_FRAG_SIZE (1000) +#define WMT_PATCH_FRAG_1ST (0x1) +#define WMT_PATCH_FRAG_MID (0x2) +#define WMT_PATCH_FRAG_LAST (0x3) + +#define CFG_CHECK_WMT_RESULT (1) +/* BT Port 2 Feature. this command does not need + * after coex command is downconfirmed by LC, + */ +#define CFG_WMT_BT_PORT2 (0) + +#define CFG_SET_OPT_REG (0) +#define CFG_WMT_I2S_DBGUART_SUPPORT (0) +#define CFG_SET_OPT_REG_SWLA (0) +#define CFG_SET_OPT_REG_MCUCLK (0) +#define CFG_SET_OPT_REG_MCUIRQ (0) + +#define CFG_SUBSYS_COEX_NEED 0 + +#define CFG_WMT_COREDUMP_ENABLE 0 + +#define CFG_WMT_MULTI_PATCH (1) + +#define CFG_WMT_CRYSTAL_TIMING_SET (0) + +#define CFG_WMT_SDIO_DRIVING_SET (0) + +#define CFG_WMT_UART_HIF_USE (0) + +#define CFG_WMT_WIFI_5G_SUPPORT (1) + +#define CFG_WMT_PATCH_DL_OPTM (1) +#if CFG_WMT_LTE_COEX_HANDLING +#define CFG_WMT_FILTER_MODE_SETTING (1) +#else +#define CFG_WMT_FILTER_MODE_SETTING (0) +#endif +#define MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT (0) + +#define CFG_WMT_POWER_ON_DLM (1) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT8 gFullPatchName[NAME_MAX + 1]; +static const WMT_IC_INFO_S *gp_soc_info; +static WMT_PATCH gp_soc_patch_info; +static WMT_CO_CLOCK gCoClockEn = WMT_CO_CLOCK_DIS; +#if 0 +static UINT8 WMT_WAKEUP_DIS_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x04 }; +static UINT8 WMT_WAKEUP_DIS_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x04 }; + +static UINT8 WMT_WAKEUP_EN_GATE_CMD[] = { 0x1, 0x3, 0x01, 0x00, 0x05 }; +static UINT8 WMT_WAKEUP_EN_GATE_EVT[] = { 0x2, 0x3, 0x02, 0x0, 0x0, 0x05 }; +#endif + +#if CFG_WMT_UART_HIF_USE +static UINT8 WMT_QUERY_BAUD_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x02 }; +static UINT8 WMT_QUERY_BAUD_EVT_115200[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0x00, 0xC2, 0x01, 0x00 }; +static UINT8 WMT_QUERY_BAUD_EVT_X[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x02, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_CMD_X[] = { 0x01, 0x04, 0x05, 0x00, 0x01, 0xAA, 0xAA, 0xAA, 0xBB }; +static UINT8 WMT_SET_BAUD_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x01 }; +static UINT8 WMT_SET_WAKEUP_WAKE_CMD_RAW[] = { 0xFF }; +static UINT8 WMT_SET_WAKEUP_WAKE_EVT[] = { 0x02, 0x03, 0x02, 0x00, 0x00, 0x03 }; +#endif +static UINT8 WMT_QUERY_STP_CMD[] = { 0x01, 0x04, 0x01, 0x00, 0x04 }; +static UINT8 WMT_QUERY_STP_EVT_DEFAULT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0x11, 0x00, 0x00, 0x00 }; +static UINT8 WMT_QUERY_STP_EVT[] = { 0x02, 0x04, 0x06, 0x00, 0x00, 0x04, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_PATCH_CMD[] = { 0x01, 0x01, 0x00, 0x00, 0x00 }; +static UINT8 WMT_PATCH_EVT[] = { 0x02, 0x01, 0x01, 0x00, 0x00 }; +static UINT8 WMT_RESET_CMD[] = { 0x01, 0x07, 0x01, 0x00, 0x04 }; +static UINT8 WMT_RESET_EVT[] = { 0x02, 0x07, 0x01, 0x00, 0x00 }; + +#if CFG_WMT_BT_PORT2 +static UINT8 WMT_BTP2_CMD[] = { 0x01, 0x10, 0x03, 0x00, 0x01, 0x03, 0x01 }; +static UINT8 WMT_BTP2_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +/*soc patial patch address cmd & evt need firmware owner provide*/ +#if CFG_WMT_MULTI_PATCH +static UINT8 WMT_PATCH_ADDRESS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x3c, 0x02, 0x09, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_PATCH_P_ADDRESS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0xc4, 0x04, 0x09, 0x02, + 0x00, 0x3f, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_PATCH_P_ADDRESS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +/*coex cmd/evt++*/ +static UINT8 WMT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +#if CFG_SUBSYS_COEX_NEED +static UINT8 WMT_BT_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0B, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_BT_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0C, + 0x00, 0x03, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA +}; +static UINT8 WMT_WIFI_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x0A, + 0x00, 0x04, + 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xEE, 0xFF, 0xFF, 0xFE +}; +static UINT8 WMT_PTA_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_CMD[] = { 0x01, 0x10, 0x09, + 0x00, 0x05, + 0xAA, 0xAA, 0xAA, 0xAA, + 0xBB, 0xBB, 0xBB, 0xBB +}; +static UINT8 WMT_MISC_COEX_SETTING_CONFIG_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; +#endif + +/*coex cmd/evt--*/ +static UINT8 WMT_SET_STP_CMD[] = { 0x01, 0x04, 0x05, 0x00, 0x03, 0xDF, 0x0E, 0x68, 0x01 }; +static UINT8 WMT_SET_STP_EVT[] = { 0x02, 0x04, 0x02, 0x00, 0x00, 0x03 }; +static UINT8 WMT_STRAP_CONF_CMD_FM_COMM[] = { 0x01, 0x05, 0x02, 0x00, 0x02, 0x02 }; +static UINT8 WMT_STRAP_CONF_EVT[] = { 0x02, 0x05, 0x02, 0x00, 0x00, 0x02 }; + +#if 0 +static UINT8 WMT_SET_OSC32K_BYPASS_CMD[] = { 0x01, 0x0A, 0x01, 0x00, 0x05 }; +static UINT8 WMT_SET_OSC32K_BYPASS_EVT[] = { 0x02, 0x0A, 0x01, 0x00, 0x00 }; +#endif + +#if 0 +/* to enable dump feature */ +static UINT8 WMT_CORE_DUMP_EN_CMD[] = { 0x01, 0x0F, 0x02, 0x00, 0x03, 0x01 }; +static UINT8 WMT_CORE_DUMP_EN_EVT[] = { 0x02, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_01_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_01_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get task and system stack dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_02_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_02_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +/* to get bt related memory dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_03_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x03, 0x00, 0x00, 0x09, 0xF0, 0x00, 0x0A }; +static UINT8 WMT_CORE_DUMP_LEVEL_03_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; +#endif +/* to get full dump when f/w assert */ +static UINT8 WMT_CORE_DUMP_LEVEL_04_CMD[] = { 0x1, 0x0F, 0x07, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static UINT8 WMT_CORE_DUMP_LEVEL_04_EVT[] = { 0x2, 0x0F, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_CO_CLOCK_CMD[] = { 0x1, 0x0A, 0x02, 0x00, 0x08, 0x03 }; +static UINT8 WMT_CORE_CO_CLOCK_EVT[] = { 0x2, 0x0A, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_CORE_START_RF_CALIBRATION_CMD[] = { 0x1, 0x14, 0x1, 0x00, 0x01 }; +static UINT8 WMT_CORE_START_RF_CALIBRATION_EVT[] = { 0x2, 0x14, 0x02, 0x00, 0x00, 0x01 }; + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static UINT8 WMT_SET_I2S_SLAVE_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x78, 0x00, 0x05, 0x80 /*addr:0x80050078 */ + , 0x00, 0x00, 0x11, 0x01 /*value:0x11010000 */ + , 0x00, 0x00, 0x77, 0x07 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_I2S_SLAVE_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x74, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x44, 0x44, 0x00, 0x00 /*value:0x11010000 */ + , 0x77, 0x77, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_TO_PAD_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +static UINT8 WMT_SET_DAI_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0xA0, 0x00, 0x05, 0x80 /*addr:0x80050074 */ + , 0x04, 0x00, 0x00, 0x00 /*value:0x11010000 */ + , 0x04, 0x00, 0x00, 0x00 /*mask:0x07770000 */ +}; + +static UINT8 WMT_SET_DAI_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; +#endif + +#if !(CFG_IC_SOC) /* For MT6628 no need to set ALLEINT registers, done in f/w */ +/* enable all interrupt */ +static UINT8 WMT_SET_ALLINT_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x00, 0x03, 0x05, 0x80 /*addr:0x80050300 */ + , 0x00, 0xC4, 0x00, 0x00 /*value:0x0000C400 */ + , 0x00, 0xC4, 0x00, 0x00 /*mask:0x0000C400 */ +}; + +static UINT8 WMT_SET_ALLINT_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; + +#endif + +#if CFG_SET_OPT_REG_SWLA /* enable swla: eesk(7) eecs(8) oscen(19) sck0(24) scs0(25) */ +static UINT8 WMT_SET_SWLA_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x10, 0x01, 0x05, 0x80 /*addr:0x80050110 */ + , 0x10, 0x10, 0x01, 0x00 /*value:0x00011010 */ + , 0xF0, 0xF0, 0x0F, 0x00 /*mask:0x000FF0F0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x10, 0x01, 0x00 /*value:0x00011000 */ + , 0x00, 0xF0, 0x0F, 0x00 /*mask:0x000FF000 */ +}; + +static UINT8 WMT_SET_SWLA_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUCLK /* enable mcu clk: antsel_4, eedi */ +static UINT8 WMT_SET_MCUCLK_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000 0400 */ + , 0x00, 0x14, 0x00, 0x00 /* value:0x0000 1400(osc, hclk), 0x0000 1501(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005 0180 */ + , 0x12, 0x13, 0x00, 0x00 /* value:0x0000 1312(osc, hclk), 0x0000 1a19(PLL, en) */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000 FFFF */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005 0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002 0000 */ + , 0x00, 0x00, 0x0F, 0x00 /* mask:0x000F 0000 */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005 0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000 0002 */ + , 0x0F, 0x00, 0x00, 0x00 /* mask:0x0000 000F */ +}; + +static UINT8 WMT_SET_MCUCLK_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ +}; +#endif + +#if CFG_WMT_I2S_DBGUART_SUPPORT /* register write for debug uart */ +static UINT8 WMT_SET_DBGUART_REG_CMD[] = { 0x01, 0x08, 0x1C, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ + , 0x30, 0x01, 0x05, 0x80 /*addr:0x80050130 */ + , 0x00, 0x00, 0x00, 0x00 /*value:0x00000000 */ + , 0xF0, 0x0F, 0x00, 0x00 /*mask:0x00000FF0 */ + , 0x40, 0x01, 0x05, 0x80 /*addr:0x80050140 */ + , 0x00, 0x01, 0x00, 0x00 /*value:0x00000100 */ + , 0x00, 0x01, 0x00, 0x00 /*mask:0x00000100 */ +}; + +static UINT8 WMT_SET_DBGUART_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x02 /*2 registers */ +}; +#endif + +#if CFG_SET_OPT_REG_MCUIRQ /* enable mcu irq: antsel_4, wlan_act */ +#if 1 /* Ray */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 4), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 4 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x03, 0x14, 0x00, 0x00 /* value:0x0000_1403 check confg debug flag 3 low word */ + , 0xFF, 0xFF, 0x00, 0x00 /* mask:0x0000_FFFF */ + /* cirq_int_n */ + , 0x10, 0x01, 0x05, 0x80 /* addr:0x8005_0110 */ + , 0x02, 0x00, 0x00, 0x00 /* value:0x0000_0002 set EEDI as cirq_int_n debug flag (monitor flag2) */ + , 0x07, 0x00, 0x00, 0x00 /* mask:0x0000_0007 */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0, ahb_x2_gt_ck debug flag) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x1F, 0x1E, 0x00, 0x00 /* value:0x0000_1E1F check mcusys debug flag */ + , 0x7F, 0x7F, 0x00, 0x00 /* mask:0x0000_7F7F */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x04 /* 5 registers */ +}; +#elif 0 /* KC */ +static UINT8 WMT_SET_MCUIRQ_REG_CMD[] = { 0x01, 0x08, (4 + 12 * 5), 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ + , 0x00, 0x04, 0x00, 0x80 /* addr:0x8000_0400 */ + , 0x00, 0x02, 0x00, 0x00 /* value:0x0000_0200 [15:8]=0x2 arm irq_b, 0xA irq_bus[5] bt_timcon_irq_b */ + , 0x00, 0xFF, 0x00, 0x00 /* mask:0x0000_FF00 */ + /* 1. ARM irq_b, monitor flag 0 */ + , 0x80, 0x01, 0x05, 0x80 /* addr:0x8005_0180 */ + , 0x18, 0x00, 0x00, 0x00 /* value:0x0000_0018 [6:0]=001_1000 (monitor flag 0 select, MCUSYS, SEL:8) */ + , 0x7F, 0x00, 0x00, 0x00 /* mask:0x0000_007F */ + , 0x00, 0x01, 0x05, 0x80 /* addr:0x8005_0100 */ + , 0x00, 0x00, 0x02, 0x00 /* value:0x0002_0000 (ANTSEL4=>monitor flag 0) */ + , 0x00, 0x00, 0x07, 0x00 /* mask:0x0007_0000 */ + /* 2. irq_bus[5] bt_timcon_irq_b monitor flag 15 */ + , 0xB0, 0x01, 0x05, 0x80 /* addr:0x8005_01B0 */ + , 0x00, 0x00, 0x00, 0x16 /* value:0x1600_0000 [30:24]=001_0110 (monitor flag 15 select, MCUSYS, SEL:6) */ + , 0x00, 0x00, 0x00, 0x7F /* mask:0x7F00_0000 */ + , 0x30, 0x01, 0x05, 0x80 /* addr:0x8005_0130 */ + , 0x00, 0x20, 0x00, 0x00 /* value:0x0000_2000 (WLAN_ACT=>monitor flag 15) */ + , 0x00, 0x70, 0x00, 0x00 /* mask:0x0000_7000 */ +}; + +static UINT8 WMT_SET_MCUIRQ_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /* S: 0 */ + , 0x00 /* type: reg */ + , 0x00 /* rev */ + , 0x05 /* 5 registers */ +}; +#endif +#endif + +#if CFG_WMT_CRYSTAL_TIMING_SET +static UINT8 WMT_SET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x01, 0x00 }; +static UINT8 WMT_SET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x01, 0x00 }; + +static UINT8 WMT_GET_CRYSTAL_TRIMING_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x00, 0x00 }; +static UINT8 WMT_GET_CRYSTAL_TRIMING_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x00, 0x00 }; +#endif + +#ifdef CFG_WMT_READ_EFUSE_VCN33 +static UINT8 WMT_GET_EFUSE_VCN33_CMD[] = { 0x01, 0x12, 0x02, 0x00, 0x04, 0x00 }; +static UINT8 WMT_GET_EFUSE_VCN33_EVT[] = { 0x02, 0x12, 0x02, 0x00, 0x04, 0x00 }; +#endif + +/* set sdio driving */ +#if CFG_WMT_SDIO_DRIVING_SET +static UINT8 WMT_SET_SDIO_DRV_REG_CMD[] = { 0x01, 0x08, 0x10, 0x00 /*length */ + , 0x01 /* op: w */ + , 0x01 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ + , 0x50, 0x00, 0x05, 0x80 /*addr:0x80050050 */ + , 0x44, 0x44, 0x04, 0x00 /*value:0x00044444 */ + , 0x77, 0x77, 0x07, 0x00 /*mask:0x00077777 */ +}; + +static UINT8 WMT_SET_SDIO_DRV_REG_EVT[] = { 0x02, 0x08, 0x04, 0x00 /*length */ + , 0x00 /*S: 0 */ + , 0x00 /*type: reg */ + , 0x00 /*rev */ + , 0x01 /*1 registers */ +}; +#endif + +#if CFG_WMT_WIFI_5G_SUPPORT +static UINT8 WMT_GET_SOC_ADIE_CHIPID_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x24, 0x00 }; +static UINT8 WMT_GET_SOC_ADIE_CHIPID_EVT[] = { + 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x24, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_GET_SOC_6625_L_CMD[] = { 0x01, 0x13, 0x04, 0x00, 0x02, 0x04, 0x20, 0x01 }; +static UINT8 WMT_GET_SOC_6625_L_EVT[] = { + 0x02, 0x13, 0x09, 0x00, 0x00, 0x02, 0x04, 0x20, + 0x01, 0x00, 0x00, 0x00, 0x00 +}; +#endif + +#if CFG_WMT_PATCH_DL_OPTM +static UINT8 WMT_SET_MCU_CLK_EN_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x34, 0x03, 0x00, 0x80, + 0x00, 0x00, 0x01, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_EN_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_138_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, + 0x59, 0x4d, 0x84, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_138_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_26_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, + 0x00, 0x4d, 0x84, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_26_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +static UINT8 WMT_SET_MCU_CLK_DIS_CMD[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x34, 0x03, 0x00, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff +}; +static UINT8 WMT_SET_MCU_CLK_DIS_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; + +/*only for 6797,enable high clock frequency*/ +/*CLK EN*/ +static UINT8 WMT_SET_MCU_CLK_EN_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x10, + 0x00, 0x00, 0x00, 0x10 +}; +/*RATIO SET*/ +static UINT8 WMT_SET_MCU_RATIO_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, 0x40, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00 +}; +/*DIV SET*/ +static UINT8 WMT_SET_MCU_DIV_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x18, 0x11, 0x02, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x3f, 0x00, 0x00, 0x00 +}; +/*HCLK SET*/ +static UINT8 WMT_SET_MCU_HCLK_SET_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x00, 0x11, 0x02, 0x81, 0x04, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00 +}; + +/*Change clock to 26MHz*/ +/*HCLK DIS*/ +static UINT8 WMT_SET_MCU_HCLK_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x00, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00 +}; +/*RATIO DIS*/ +static UINT8 WMT_SET_MCU_RATIO_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x0c, 0x01, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0xc0, 0x00, 0x00, 0x00 +}; +/*CLK DIS*/ +static UINT8 WMT_SET_MCU_CLK_DIS_6797[] = { + 0x01, 0x08, 0x10, 0x00, 0x01, 0x01, 0x00, 0x01, + 0x10, 0x11, 0x02, 0x81, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x10 +}; + +static UINT8 WMT_SET_MCU_CLK_EVT_6797[] = { + 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 +}; + +#endif + +#if CFG_WMT_FILTER_MODE_SETTING +static UINT8 WMT_COEX_EXT_COMPONENT_CMD[] = {0x01, 0x10, 0x03, 0x00, 0x0d, 0x00, 0x00}; +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, + 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x00, 0x0a, 0x0c, 0x0e, + 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xd4, + 0x09, 0xe3, 0x09, 0x5a, 0x0a, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x60, 0x09, 0xd3, 0x09, 0xe2, + 0x09, 0x59, 0x0a, 0x8B, 0x0a}; +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; +static UINT8 WMT_COEX_IS_LTE_L_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x21, 0x01 }; + +#if 0 +static UINT8 WMT_COEX_SPLIT_FILTER_CMD_TEST[] = { + 0x01, 0x10, 0x19, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x00, 0x6c, 0x09, 0x8a, 0x09, 0x8a, 0x09, 0x9e, + 0x09, 0x01, 0x07, 0x07, 0x0b, 0x07, 0x07, 0x00, + 0x32, 0x27, 0x4e, 0x27, 0x32 +}; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_TEST[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x07, 0x07, 0x07, 0x54, 0x54, 0x00, 0x00, + 0x00, 0x50, 0x50, 0x50, 0x54, 0x54, 0x39, 0x39, + 0x39, 0x02, 0x02, 0x02, 0x0e, 0x0e, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0a, 0x0a, + 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, + 0x09, 0xf6, 0x09, 0x0f, 0xaf, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, + 0x09, 0x0d, 0x0a, 0x27, 0x0a +}; +static UINT8 WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST[] = { 0x01, 0x10, 0x02, 0x00, 0x13, 0x00 }; +static UINT8 WMT_COEX_EXT_COMPONENT_CMD_TEST[] = { 0x01, 0x10, 0x03, 0x00, 0x0d, 0x7f, 0x03 }; +#endif + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_0[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x16, 0x16, 0x16, 0x16, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x63, 0x3c, 0x3c, 0x3c, + 0x3c, 0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, + 0x01, 0x0e, 0x0e, 0x0e, 0x0e, 0x0b, 0x0b, 0x0b, + 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xfc, 0x08, 0x15, + 0x09, 0x2e, 0x09, 0x47, 0x09, 0xc4, 0x09, 0xdd, + 0x09, 0xf6, 0x09, 0x0f, 0x0a, 0x14, 0x09, 0x2d, + 0x09, 0x46, 0x09, 0x5f, 0x09, 0xdd, 0x09, 0xf5, + 0x09, 0x0d, 0x0a, 0x27, 0x0a +}; +static UINT8 WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x14, 0x00 }; +static UINT8 WMT_COEX_IS_LTE_PROJ_CMD[] = { 0x01, 0x10, 0x02, 0x00, 0x15, 0x01 }; +static UINT8 WMT_COEX_SPLIT_MODE_EVT[] = { 0x02, 0x10, 0x01, 0x00, 0x00 }; + +static UINT8 WMT_COEX_FILTER_SPEC_CMD_6752[] = { + 0x01, 0x10, 0x45, 0x00, 0x11, 0x00, 0x00, 0x01, + 0x00, 0x11, 0x11, 0x16, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x63, 0x63, 0x63, 0x00, 0x39, 0x43, 0x63, + 0x63, 0x02, 0x02, 0x03, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x0E, 0x0E, 0x0E, 0x00, 0x0A, 0x0C, 0x0E, + 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00 +}; + +static UINT8 WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752[] = { + 0x01, 0x10, 0x21, 0x00, 0x12, 0xFC, 0x08, 0x15, + 0x09, 0x2E, 0x09, 0x47, 0x09, 0xC4, 0x09, 0xD4, + 0x09, 0xE3, 0x09, 0x5A, 0x0A, 0x14, 0x09, 0x2D, + 0x09, 0x46, 0x09, 0x60, 0x09, 0xD3, 0x09, 0xE2, + 0x09, 0x59, 0x0A, 0x8B, 0x0A +}; +#endif + +#if CFG_WMT_POWER_ON_DLM +static UINT8 WMT_POWER_CTRL_DLM_CMD1[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0x00, 0x00 +}; + +static UINT8 WMT_POWER_CTRL_DLM_CMD2[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0xf0, 0x00, 0x00, 0x00 +}; + +static UINT8 WMT_POWER_CTRL_DLM_CMD3[] = { + 0x01, 0x08, 0x10, 0x00, + 0x01, 0x01, 0x00, 0x01, + 0x60, 0x00, 0x10, 0x80, + 0x00, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00 +}; +static UINT8 WMT_POWER_CTRL_DLM_EVT[] = { 0x02, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01 }; +#endif + +#if (!CFG_IC_SOC) + +/* stp sdio init scripts */ +static struct init_script init_table_1_1[] = { + /* table_1_1 is only applied to common SDIO interface */ + INIT_CMD(WMT_SET_ALLINT_REG_CMD, WMT_SET_ALLINT_REG_EVT, "enable all interrupt"), + /* applied to MT6628 ? */ + INIT_CMD(WMT_WAKEUP_DIS_GATE_CMD, WMT_WAKEUP_DIS_GATE_EVT, "disable gating"), +}; + +#endif + +static struct init_script init_table_1_2[] = { + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT_DEFAULT, "query stp default"), +}; + +#if CFG_WMT_UART_HIF_USE +static struct init_script init_table_2[] = { + INIT_CMD(WMT_QUERY_BAUD_CMD, WMT_QUERY_BAUD_EVT_X, "query baud X"), +}; +#endif + +static struct init_script init_table_3[] = { + INIT_CMD(WMT_RESET_CMD, WMT_RESET_EVT, "wmt reset"), +#if CFG_WMT_BT_PORT2 + INIT_CMD(WMT_BTP2_CMD, WMT_BTP2_EVT, "set bt port2"), +#endif +}; + +#if CFG_WMT_CRYSTAL_TIMING_SET +static struct init_script set_crystal_timing_script[] = { + INIT_CMD(WMT_SET_CRYSTAL_TRIMING_CMD, WMT_SET_CRYSTAL_TRIMING_EVT, "set crystal trim value"), +}; + +static struct init_script get_crystal_timing_script[] = { + INIT_CMD(WMT_GET_CRYSTAL_TRIMING_CMD, WMT_GET_CRYSTAL_TRIMING_EVT, "get crystal trim value"), +}; +#endif +#ifdef CFG_WMT_READ_EFUSE_VCN33 +static struct init_script get_efuse_vcn33_script[] = { + INIT_CMD(WMT_GET_EFUSE_VCN33_CMD, WMT_GET_EFUSE_VCN33_EVT, "get efuse vcn33 value"), +}; +#endif + +static struct init_script init_table_4[] = { + INIT_CMD(WMT_SET_STP_CMD, WMT_SET_STP_EVT, "set stp"), +}; + +static struct init_script init_table_5[] = { + INIT_CMD(WMT_QUERY_STP_CMD, WMT_QUERY_STP_EVT, "query stp"), +}; + +static struct init_script init_table_5_1[] = { + INIT_CMD(WMT_STRAP_CONF_CMD_FM_COMM, WMT_STRAP_CONF_EVT, "configure FM comm"), +}; + +static struct init_script init_table_6[] = { + INIT_CMD(WMT_CORE_DUMP_LEVEL_04_CMD, WMT_CORE_DUMP_LEVEL_04_EVT, "setup core dump level"), +}; + +static struct init_script calibration_table[] = { + INIT_CMD(WMT_CORE_START_RF_CALIBRATION_CMD, WMT_CORE_START_RF_CALIBRATION_EVT, "start RF calibration data"), +}; + +#if CFG_WMT_PATCH_DL_OPTM +static struct init_script set_mcuclk_table_1[] = { + INIT_CMD(WMT_SET_MCU_CLK_EN_CMD, WMT_SET_MCU_CLK_EN_EVT, "enable set mcu clk"), + INIT_CMD(WMT_SET_MCU_CLK_138_CMD, WMT_SET_MCU_CLK_138_EVT, "set mcu clk to 138.67MH"), +}; + +static struct init_script set_mcuclk_table_2[] = { + INIT_CMD(WMT_SET_MCU_CLK_26_CMD, WMT_SET_MCU_CLK_26_EVT, "set mcu clk to 26MH"), + INIT_CMD(WMT_SET_MCU_CLK_DIS_CMD, WMT_SET_MCU_CLK_DIS_EVT, "disable set mcu clk"), +}; + +static struct init_script set_mcuclk_table_3[] = { + INIT_CMD(WMT_SET_MCU_CLK_EN_6797, WMT_SET_MCU_CLK_EVT_6797, "enable set mcu clk"), + INIT_CMD(WMT_SET_MCU_RATIO_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu ratio set"), + INIT_CMD(WMT_SET_MCU_DIV_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "mcu div set"), + INIT_CMD(WMT_SET_MCU_HCLK_SET_6797, WMT_SET_MCU_CLK_EVT_6797, "set mcu clk to hclk"), +}; +static struct init_script set_mcuclk_table_4[] = { + INIT_CMD(WMT_SET_MCU_HCLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu hclk"), + INIT_CMD(WMT_SET_MCU_RATIO_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu ratio set"), + INIT_CMD(WMT_SET_MCU_CLK_DIS_6797, WMT_SET_MCU_CLK_EVT_6797, "disable mcu clk set"), +}; + +#endif + +#if CFG_WMT_FILTER_MODE_SETTING +static struct init_script set_wifi_lte_coex_table_1[] = { + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_6752, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), + INIT_CMD(WMT_COEX_IS_LTE_PROJ_CMD, WMT_COEX_SPLIT_MODE_EVT, "set LTE project"), +}; + +static struct init_script set_wifi_lte_coex_table_2[] = { + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte ext component"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq id table"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi lte unsafe channel"), + INIT_CMD(WMT_COEX_IS_LTE_L_CMD, WMT_COEX_SPLIT_MODE_EVT, "wifi coex is L branch"), +}; + +static struct init_script set_wifi_lte_coex_table_0[] = { +#if 0 + INIT_CMD(WMT_COEX_SPLIT_FILTER_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex split filter"), + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte freq idx"), + INIT_CMD(WMT_COEX_LTE_CHAN_UNSAFE_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi lte channel unsafe"), + INIT_CMD(WMT_COEX_EXT_COMPONENT_CMD_TEST, WMT_COEX_SPLIT_MODE_EVT, "wifi coex ext component"), +#endif + INIT_CMD(WMT_COEX_FILTER_SPEC_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte coex filter spec"), + INIT_CMD(WMT_COEX_LTE_FREQ_IDX_TABLE_CMD_0, WMT_COEX_SPLIT_MODE_EVT, "def wifi lte freq idx"), +}; + +static struct init_script get_tdm_req_antsel_num_table[] = { + INIT_CMD(WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD, WMT_COEX_SPLIT_MODE_EVT, "get tdm req antsel num"), +}; +#endif + +#if CFG_SET_OPT_REG +static struct init_script set_registers[] = { + /* INIT_CMD(WMT_SET_GPS_REG_CMD, WMT_SET_GPS_REG_EVT, "set wmt registers"), */ + /* INIT_CMD(WMT_SET_SDIODRV_REG_CMD, WMT_SET_SDIODRV_REG_EVT, "set SDIO driving registers") */ +#if CFG_WMT_I2S_DBGUART_SUPPORT + INIT_CMD(WMT_SET_DBGUART_REG_CMD, WMT_SET_DBGUART_REG_EVT, "set debug uart registers"), +#endif +#if CFG_SET_OPT_REG_SWLA + INIT_CMD(WMT_SET_SWLA_REG_CMD, WMT_SET_SWLA_REG_EVT, "set swla registers"), +#endif +#if CFG_SET_OPT_REG_MCUCLK + INIT_CMD(WMT_SET_MCUCLK_REG_CMD, WMT_SET_MCUCLK_REG_EVT, "set mcuclk dbg registers"), +#endif +#if CFG_SET_OPT_REG_MCUIRQ + INIT_CMD(WMT_SET_MCUIRQ_REG_CMD, WMT_SET_MCUIRQ_REG_EVT, "set mcu irq dbg registers"), +#endif +}; +#endif + +static struct init_script coex_table[] = { + INIT_CMD(WMT_COEX_SETTING_CONFIG_CMD, WMT_COEX_SETTING_CONFIG_EVT, "coex_wmt"), + +#if CFG_SUBSYS_COEX_NEED +/* no need in MT6628 */ + INIT_CMD(WMT_BT_COEX_SETTING_CONFIG_CMD, WMT_BT_COEX_SETTING_CONFIG_EVT, "coex_bt"), + INIT_CMD(WMT_WIFI_COEX_SETTING_CONFIG_CMD, WMT_WIFI_COEX_SETTING_CONFIG_EVT, "coex_wifi"), + INIT_CMD(WMT_PTA_COEX_SETTING_CONFIG_CMD, WMT_PTA_COEX_SETTING_CONFIG_EVT, "coex_ext_pta"), + INIT_CMD(WMT_MISC_COEX_SETTING_CONFIG_CMD, WMT_MISC_COEX_SETTING_CONFIG_EVT, "coex_misc"), +#endif +}; + +static struct init_script osc_type_table[] = { + INIT_CMD(WMT_CORE_CO_CLOCK_CMD, WMT_CORE_CO_CLOCK_EVT, "osc_type"), +}; + +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) +static struct init_script merge_pcm_table[] = { + INIT_CMD(WMT_SET_I2S_SLAVE_REG_CMD, WMT_SET_I2S_SLAVE_REG_EVT, "I2S_Slave"), + INIT_CMD(WMT_SET_DAI_TO_PAD_REG_CMD, WMT_SET_DAI_TO_PAD_REG_EVT, "DAI_PAD"), + INIT_CMD(WMT_SET_DAI_REG_CMD, WMT_SET_DAI_REG_EVT, "DAI_EVT"), +}; +#endif + +#if CFG_WMT_SDIO_DRIVING_SET +static struct init_script sdio_driving_table[] = { + INIT_CMD(WMT_SET_SDIO_DRV_REG_CMD, WMT_SET_SDIO_DRV_REG_EVT, "sdio_driving"), +}; +#endif + +#if CFG_WMT_POWER_ON_DLM +static struct init_script wmt_power_on_dlm_table[] = { + INIT_CMD(WMT_POWER_CTRL_DLM_CMD1, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd1"), + INIT_CMD(WMT_POWER_CTRL_DLM_CMD2, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd2"), + INIT_CMD(WMT_POWER_CTRL_DLM_CMD3, WMT_POWER_CTRL_DLM_EVT, "power on dlm cmd3") +}; +#endif + +/* SOC Chip Version and Info Table */ +static const WMT_IC_INFO_S mtk_wcn_soc_info_table[] = { + { + .u4HwVer = 0x8A00, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E1, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + /* need to refine? */ + .eWmtHwVer = WMTHWVER_E1, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8A01, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E2, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .eWmtHwVer = WMTHWVER_E2, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + }, + { + .u4HwVer = 0x8B01, + .cChipName = WMT_IC_NAME_DEFAULT, + .cChipVersion = WMT_IC_VER_E3, + .cPatchNameExt = WMT_IC_PATCH_E1_EXT, + .eWmtHwVer = WMTHWVER_E3, + .bWorkWithoutPatch = MTK_WCN_BOOL_FALSE, + .bPsmSupport = MTK_WCN_BOOL_TRUE, + } +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf); + +static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag); + +static INT32 mtk_wcn_soc_ver_check(VOID); + +static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver); + +static INT32 wmt_stp_init_coex(VOID); + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID); +#endif + +#if CFG_WMT_MULTI_PATCH +static INT32 mtk_wcn_soc_patch_dwn(UINT32 index); +static INT32 mtk_wcn_soc_patch_info_prepare(VOID); +#else +static INT32 mtk_wcn_soc_patch_dwn(VOID); +#endif + +static INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on); +static WMT_CO_CLOCK mtk_wcn_soc_co_clock_get(VOID); + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mtk_wcn_soc_crystal_triming_set(VOID); +#endif + +static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID); + +static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID); + +#if CFG_WMT_SDIO_DRIVING_SET +static INT32 mtk_wcn_soc_set_sdio_driving(void); +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* SOC Operation Function Table */ +WMT_IC_OPS wmt_ic_ops_soc = { + .icId = 0x0000, /* soc may have mt6572/82/71/83,but they have the same sw init flow */ + .sw_init = mtk_wcn_soc_sw_init, + .sw_deinit = mtk_wcn_soc_sw_deinit, + .ic_pin_ctrl = mtk_wcn_soc_pin_ctrl, + .ic_ver_check = mtk_wcn_soc_ver_check, + .co_clock_ctrl = mtk_wcn_soc_co_clock_ctrl, + .is_quick_sleep = mtk_wcn_soc_quick_sleep_flag_get, + .is_aee_dump_support = mtk_wcn_soc_aee_dump_flag_get, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static INT32 mtk_wcn_soc_sw_init(P_WMT_HIF_CONF pWmtHifConf) +{ + INT32 iRet = -1; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + UINT32 hw_ver; + WMT_CTRL_DATA ctrlData; +#ifdef CFG_WMT_READ_EFUSE_VCN33 + UINT32 efuse_d3_vcn33 = 2; /*default voltage is 3.5V*/ +#endif +#if CFG_WMT_MULTI_PATCH + UINT32 patch_num = 0; + UINT32 patch_index = 0; +#endif +#if CFG_WMT_WIFI_5G_SUPPORT + UINT32 dDieChipid = 0; + UINT32 aDieChipid = 0; + UINT8 evtbuf[20]; + UINT32 u4Res; + UINT32 pmicChipid = 0; +#endif + WMT_DBG_FUNC(" start\n"); + + osal_assert(NULL != gp_soc_info); + if ((NULL == gp_soc_info) + || (NULL == pWmtHifConf) + ) { + WMT_ERR_FUNC("null pointers: gp_soc_info(0x%p), pWmtHifConf(0x%p)\n", gp_soc_info, pWmtHifConf); + return -1; + } + + hw_ver = gp_soc_info->u4HwVer; + + /* 4 <3.2> start init for BTIF */ + if (WMT_HIF_BTIF == pWmtHifConf->hifType) { + /* 1. Query chip STP default options (TEST-ONLY) */ + /* WMT_DBG_FUNC("WMT-CORE: init_table_1_2 set chip baud:%d", pWmtHifConf->au4HifConf[0]); */ + iRet = wmt_core_init_script(init_table_1_2, osal_array_size(init_table_1_2)); + if (iRet) { + WMT_ERR_FUNC("init_table_1_2 fail(%d)\n", iRet); + osal_assert(0); + return -2; + } + /* 2. Set chip STP options */ + iRet = wmt_core_init_script(init_table_4, osal_array_size(init_table_4)); + if (iRet) { + WMT_ERR_FUNC("init_table_4 fail(%d)\n", iRet); + return -3; + } + + /* 3. Enable host full mode */ + ctrlPa1 = WMT_STP_CONF_MODE; + ctrlPa2 = MTKSTP_BTIF_FULL_MODE; + iRet = wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WMT_STP_CONF_EN; + ctrlPa2 = 1; + iRet += wmt_core_ctrl(WMT_CTRL_STP_CONF, &ctrlPa1, &ctrlPa2); + if (iRet) { + WMT_ERR_FUNC("enable host STP-BTIF-FULL mode fail(%d)\n", iRet); + return -4; + } + WMT_DBG_FUNC("enable host STP-BTIF-FULL mode\n"); + /*4. wait for 10ms, enough for chip do mechanism switch.(at least 2ms is needed) */ + osal_sleep_ms(10); + /* 5. Query chip STP options (TEST-ONLY) */ + iRet = wmt_core_init_script(init_table_5, osal_array_size(init_table_5)); + if (iRet) { + WMT_ERR_FUNC("init_table_5 fail(%d)\n", iRet); + return -5; + } + } +#if CFG_WMT_POWER_ON_DLM + iRet = wmt_core_init_script(wmt_power_on_dlm_table, osal_array_size(wmt_power_on_dlm_table)); + if (iRet) + WMT_ERR_FUNC("wmt_power_on_dlm_table fail(%d)\n", iRet); + WMT_DBG_FUNC("wmt_power_on_dlm_table ok\n"); +#endif + /* 6. download patch */ +#if CFG_WMT_MULTI_PATCH + /* 6.1 Let launcher to search patch info */ + iRet = mtk_wcn_soc_patch_info_prepare(); + if (iRet) { + WMT_ERR_FUNC("patch info perpare fail(%d)\n", iRet); + return -6; + } + + /* 6.2 Read patch number */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_GET_PATCH_NUM, &ctrlPa1, &ctrlPa2); + patch_num = ctrlPa1; + WMT_DBG_FUNC("patch total num = [%d]\n", patch_num); + +#if CFG_WMT_PATCH_DL_OPTM + if (0x0279 == wmt_ic_ops_soc.icId) { + iRet = wmt_core_init_script(set_mcuclk_table_3, osal_array_size(set_mcuclk_table_3)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_3 fail(%d)\n", iRet); + } else { + iRet = wmt_core_init_script(set_mcuclk_table_1, osal_array_size(set_mcuclk_table_1)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_1 fail(%d)\n", iRet); + } +#endif + /* 6.3 Multi-patch Patch download */ + for (patch_index = 0; patch_index < patch_num; patch_index++) { + iRet = mtk_wcn_soc_patch_dwn(patch_index); + if (iRet) { + WMT_ERR_FUNC("patch dwn fail (%d),patch_index(%d)\n", iRet, patch_index); + return -7; + } + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -8; + } + } + +#if CFG_WMT_PATCH_DL_OPTM + if (0x0279 == wmt_ic_ops_soc.icId) { + iRet = wmt_core_init_script(set_mcuclk_table_4, osal_array_size(set_mcuclk_table_4)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_4 fail(%d)\n", iRet); + } else { + iRet = wmt_core_init_script(set_mcuclk_table_2, osal_array_size(set_mcuclk_table_2)); + if (iRet) + WMT_ERR_FUNC("set_mcuclk_table_2 fail(%d)\n", iRet); + } +#endif + +#else + /* 6.3 Patch download */ + iRet = mtk_wcn_soc_patch_dwn(); + /* If patch download fail, we just ignore this error and let chip init process goes on */ + if (iRet) + WMT_ERR_FUNC("patch dwn fail (%d), just omit\n", iRet); + + /* 6.4. WMT Reset command */ + iRet = wmt_core_init_script(init_table_3, osal_array_size(init_table_3)); + if (iRet) { + WMT_ERR_FUNC("init_table_3 fail(%d)\n", iRet); + return -8; + } +#endif + +#ifdef CFG_WMT_READ_EFUSE_VCN33 + /*get CrystalTiming value before set it */ + iRet = wmt_core_tx(get_efuse_vcn33_script[0].cmd, get_efuse_vcn33_script[0].cmdSz, &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != get_efuse_vcn33_script[0].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", + get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].cmdSz); + } + /* EVENT BUF */ + osal_memset(get_efuse_vcn33_script[0].evt, 0, get_efuse_vcn33_script[0].evtSz); + iRet = wmt_core_rx(get_efuse_vcn33_script[0].evt, get_efuse_vcn33_script[0].evtSz, &u4Res); + if (iRet || (u4Res != get_efuse_vcn33_script[0].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", + get_efuse_vcn33_script[0].str, iRet, u4Res, get_efuse_vcn33_script[0].evtSz); + mtk_wcn_stp_dbg_dump_package(); + } + efuse_d3_vcn33 = WMT_GET_EFUSE_VCN33_EVT[5] & 0x03; + WMT_INFO_FUNC("Read efuse to set PMIC voltage:(%d)\n", efuse_d3_vcn33); + wmt_set_pmic_voltage(efuse_d3_vcn33); +#endif + +#if CFG_WMT_FILTER_MODE_SETTING + if ((0x6580 == wmt_ic_ops_soc.icId) || + (0x8163 == wmt_ic_ops_soc.icId) || + (0x6752 == wmt_ic_ops_soc.icId) || + (0x6582 == wmt_ic_ops_soc.icId) || + (0x6592 == wmt_ic_ops_soc.icId) || + (0x0279 == wmt_ic_ops_soc.icId) || + (0x0326 == wmt_ic_ops_soc.icId) || + (0x0321 == wmt_ic_ops_soc.icId) || (0x0335 == wmt_ic_ops_soc.icId) || (0x0337 == wmt_ic_ops_soc.icId)) { + wmt_stp_wifi_lte_coex(); + WMT_DBG_FUNC("wmt_stp_wifi_lte_coex done!\n"); + } + if ((0x6582 == wmt_ic_ops_soc.icId) || (0x6592 == wmt_ic_ops_soc.icId)) { + /*get gpio tdm req antsel number */ + ctrlPa1 = 0; + ctrlPa2 = 0; + wmt_core_ctrl(WMT_CTRL_GET_TDM_REQ_ANTSEL, &ctrlPa1, &ctrlPa2); + WMT_INFO_FUNC("get GPIO TDM REQ ANTSEL number(%d)\n", ctrlPa1); + /*set gpio tdm req antsel number to firmware */ + WMT_COEX_TDM_REQ_ANTSEL_NUM_CMD[5] = ctrlPa1; + iRet = wmt_core_init_script(get_tdm_req_antsel_num_table, + osal_array_size(get_tdm_req_antsel_num_table)); + if (iRet) + WMT_ERR_FUNC("get_tdm_req_antsel_num_table fail(%d)\n", iRet); + } +#endif + /* 7. start RF calibration data */ + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WIFI_PALDO; + ctrlPa2 = PALDO_ON; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + iRet = wmt_core_init_script(calibration_table, osal_array_size(calibration_table)); + if (iRet) { + /* pwrap_read(0x0210,&ctrlPa1); */ + /* pwrap_read(0x0212,&ctrlPa2); */ + WMT_ERR_FUNC("power status: 210:(%d),212:(%d)!\n", ctrlPa1, ctrlPa2); + WMT_ERR_FUNC("calibration_table fail(%d)\n", iRet); + return -9; + } + + ctrlPa1 = BT_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + ctrlPa1 = WIFI_PALDO; + ctrlPa2 = PALDO_OFF; + iRet = wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + + iRet = wmt_stp_init_coex(); + if (iRet) { + WMT_ERR_FUNC("init_coex fail(%d)\n", iRet); + return -10; + } + WMT_DBG_FUNC("init_coex ok\n"); + +#if CFG_WMT_CRYSTAL_TIMING_SET + mtk_wcn_soc_crystal_triming_set(); +#endif + +#if CFG_WMT_SDIO_DRIVING_SET + mtk_wcn_soc_set_sdio_driving(); +#endif + + if (WMT_CO_CLOCK_EN == mtk_wcn_soc_co_clock_get()) { + WMT_INFO_FUNC("co-clock enabled.\n"); + + iRet = wmt_core_init_script(osc_type_table, osal_array_size(osc_type_table)); + if (iRet) { + WMT_ERR_FUNC("osc_type_table fail(%d), goes on\n", iRet); + return -11; + } + } else { + WMT_WARN_FUNC("co-clock disabled.\n"); + } +#if (MTK_WCN_CMB_MERGE_INTERFACE_SUPPORT) + iRet = wmt_core_init_script(merge_pcm_table, osal_array_size(merge_pcm_table)); + if (iRet) { + WMT_ERR_FUNC("merge_pcm_table fail(%d), goes on\n", iRet); + return -12; + } +#endif + + /* 15. Set FM strap */ + WMT_STRAP_CONF_CMD_FM_COMM[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + WMT_STRAP_CONF_EVT[5] = (UINT8) pWmtHifConf->au4StrapConf[0]; + iRet = wmt_core_init_script(init_table_5_1, osal_array_size(init_table_5_1)); + if (iRet) { + WMT_ERR_FUNC("init_table_5_1 fm mode(%d) fail(%d)\n", pWmtHifConf->au4StrapConf[0], iRet); + return -13; + } + WMT_DBG_FUNC("set fm mode (%d) ok\n", pWmtHifConf->au4StrapConf[0]); + +#if CFG_SET_OPT_REG /*set registers */ + iRet = wmt_core_init_script(set_registers, osal_array_size(set_registers)); + if (iRet) { + WMT_ERR_FUNC("set_registers fail(%d)", iRet); + return -14; + } +#endif + +#if CFG_WMT_COREDUMP_ENABLE + /*Open Core Dump Function @QC begin */ + mtk_wcn_stp_coredump_flag_ctrl(1); +#endif + if (0 != mtk_wcn_stp_coredump_flag_get()) { + iRet = wmt_core_init_script(init_table_6, osal_array_size(init_table_6)); + if (iRet) { + WMT_ERR_FUNC("init_table_6 core dump setting fail(%d)\n", iRet); + return -15; + } + WMT_DBG_FUNC("enable soc_consys firmware coredump\n"); + } else { + WMT_DBG_FUNC("disable soc_consys firmware coredump\n"); + } + +#if CFG_WMT_WIFI_5G_SUPPORT + dDieChipid = wmt_ic_ops_soc.icId; + WMT_DBG_FUNC("current SOC chipid is 0x%x\n", dDieChipid); + if (0x6592 == dDieChipid) { + /* read A die chipid by wmt cmd */ + iRet = + wmt_core_tx((PUINT8) &WMT_GET_SOC_ADIE_CHIPID_CMD[0], sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_CMD))) { + WMT_ERR_FUNC("wmt_core:read A die chipid CMD fail(%d),size(%d)\n", iRet, u4Res); + return -16; + } + osal_memset(evtbuf, 0, sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_ADIE_CHIPID_EVT))) { + WMT_ERR_FUNC("wmt_core:read A die chipid EVT fail(%d),size(%d)\n", iRet, u4Res); + return -17; + } + + osal_memcpy(&aDieChipid, &evtbuf[u4Res - 2], 2); + WMT_INFO_FUNC("get SOC A die chipid(0x%x)\n", aDieChipid); + + if (0x6625 == aDieChipid) { + iRet = + wmt_core_tx((PUINT8) &WMT_GET_SOC_6625_L_CMD[0], sizeof(WMT_GET_SOC_6625_L_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_CMD))) + WMT_ERR_FUNC("wmt_core:read A die efuse CMD fail(%d),size(%d)\n", iRet, u4Res); + osal_memset(evtbuf, 0, sizeof(evtbuf)); + iRet = wmt_core_rx(evtbuf, sizeof(WMT_GET_SOC_6625_L_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_GET_SOC_6625_L_EVT))) + WMT_ERR_FUNC("wmt_core:read A die efuse EVT fail(%d),size(%d)\n", iRet, u4Res); + + WMT_INFO_FUNC("read SOC Adie Efuse(0x120) value:0x%2x,0x%2x,0x%2x,0x%2x -> %s\n", + evtbuf[u4Res - 4], evtbuf[u4Res - 3], evtbuf[u4Res - 2], evtbuf[u4Res - 1], + evtbuf[u4Res - 2] == 0x31 ? "MT6625L" : "MT6625"); + } + /* get PMIC chipid */ + + ctrlData.ctrlId = WMT_CTRL_SOC_PALDO_CTRL; + ctrlData.au4CtrlData[0] = PMIC_CHIPID_PALDO; + ctrlData.au4CtrlData[1] = 0; + iRet = wmt_ctrl(&ctrlData); + if (iRet < 0) { + WMT_ERR_FUNC("wmt_core: read PMIC chipid fail(%d)\n", iRet); + return -18; + } + pmicChipid = ctrlData.au4CtrlData[2]; + WMT_INFO_FUNC("current PMIC chipid(0x%x)\n", pmicChipid); + + /* MT6625 & MT6322, write 1 to 0x0414[12] */ + /* MT6625 & MT6323, assert */ + /* MT6627 & (MT6322 or MT6323),write 0 to 0x0414[12] */ + + switch (aDieChipid) { + case 0x6625: + if (0x6322 == pmicChipid) { + WMT_INFO_FUNC("wmt-core:enable wifi 5G support\n"); + ctrlPa1 = WIFI_5G_PALDO; + ctrlPa2 = PALDO_ON; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else if (0x6323 == pmicChipid) { + osal_assert(0); + } else { + WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); + } + break; + case 0x6627: + if ((0x6322 == pmicChipid) || (0x6323 == pmicChipid)) { + WMT_INFO_FUNC("wmt-core: disable wifi 5G support\n"); + ctrlPa1 = WIFI_5G_PALDO; + ctrlPa2 = PALDO_OFF; + wmt_core_ctrl(WMT_CTRL_SOC_PALDO_CTRL, &ctrlPa1, &ctrlPa2); + } else { + WMT_WARN_FUNC("wmt-core: unknown PMIC chipid\n"); + } + break; + default: + WMT_WARN_FUNC("wmt-core: unknown A die chipid(0x%x)\n", aDieChipid); + break; + } + } +#endif + +#if 1 + ctrlData.ctrlId = WMT_CTRL_SET_STP_DBG_INFO; + ctrlData.au4CtrlData[0] = wmt_ic_ops_soc.icId; + ctrlData.au4CtrlData[1] = (SIZE_T) gp_soc_info->cChipVersion; + ctrlData.au4CtrlData[2] = (SIZE_T) &gp_soc_patch_info; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("set dump info fail(%d)\n", iRet); + return -19; + } +#endif + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_soc_info); + if (NULL != gp_soc_info) { + if (MTK_WCN_BOOL_FALSE != gp_soc_info->bPsmSupport) + wmt_lib_ps_enable(); + else + wmt_lib_ps_disable(); + } +#endif + + return 0; +} + +static INT32 mtk_wcn_soc_sw_deinit(P_WMT_HIF_CONF pWmtHifConf) +{ + WMT_DBG_FUNC(" start\n"); + +#if CFG_WMT_PS_SUPPORT + osal_assert(NULL != gp_soc_info); + if ((NULL != gp_soc_info) + && (MTK_WCN_BOOL_FALSE != gp_soc_info->bPsmSupport)) { + wmt_lib_ps_disable(); + } +#endif + + gp_soc_info = NULL; + + return 0; +} + +static INT32 mtk_wcn_soc_aif_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret = -1; + UINT32 val; + + if ((flag & WMT_LIB_AIF_FLAG_MASK) == WMT_LIB_AIF_FLAG_SHARE) { + WMT_INFO_FUNC("PCM & I2S PIN SHARE\n"); +#if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000710; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#else + WMT_WARN_FUNC("TBD!!"); + ret = 0; +#endif + } else { + /*PCM & I2S separate */ + WMT_INFO_FUNC("PCM & I2S PIN SEPARATE\n"); +#if 0 + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + val = 0x00000770; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + val = 0x00000700; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000000; + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x00000070; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + case WMT_IC_AIF_3: + val = 0x00000000; + ret = wmt_core_reg_rw_raw(1, 0x80050140, &val, 0x00000FF0); + val = 0x00000800; /* 800:3-wire, 000: 4-wire */ + ret += wmt_core_reg_rw_raw(1, 0x80050150, &val, 0x00000800); + + break; + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#else + switch (state) { + case WMT_IC_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + ret = 0; + break; + case WMT_IC_AIF_1: + /* BT_PCM_ON & FM line in/out */ + ret = 0; + break; + + case WMT_IC_AIF_2: + /* BT_PCM_OFF & FM I2S */ + val = 0x01110000; + ret = wmt_core_reg_rw_raw(1, 0x80050078, &val, 0x0FFF0000); + + break; + case WMT_IC_AIF_3: + ret = 0; + break; + + default: + WMT_ERR_FUNC("unsupported state (%d)\n", state); + ret = -1; + break; + } +#endif + } + + if (!ret) + WMT_WARN_FUNC("new state(%d) fail(%d)\n", state, ret); + WMT_INFO_FUNC("new state(%d) ok\n", state); + + return ret; +} + +static INT32 mtk_wcn_soc_gps_sync_ctrl(WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 iRet = -1; + UINT32 uVal = 0; + + /* mt6797 can not access reg:0x80050078 and no need to do GPS SYNC */ + if (0x0279 != wmt_ic_ops_soc.icId) { + if (WMT_IC_PIN_MUX == state) + uVal = 0x1 << 28; + else + uVal = 0x5 << 28; + iRet = wmt_core_reg_rw_raw(1, 0x80050078, &uVal, 0x7 << 28); + if (iRet) + WMT_ERR_FUNC("gps_sync pin ctrl failed, iRet(%d)\n", iRet); + } else + WMT_INFO_FUNC("This chip no need to sync GPS and MODEM!\n"); + + /* anyway, we return 0 */ + return 0; +} + +static INT32 mtk_wcn_soc_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE state, UINT32 flag) +{ + INT32 ret; + + WMT_DBG_FUNC("ic pin id:%d, state:%d, flag:0x%x\n", id, state, flag); + + ret = -1; + switch (id) { + case WMT_IC_PIN_AUDIO: + ret = mtk_wcn_soc_aif_ctrl(state, flag); + break; + + case WMT_IC_PIN_EEDI: + WMT_WARN_FUNC("TBD!!"); + /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ + ret = 0; + break; + + case WMT_IC_PIN_EEDO: + WMT_WARN_FUNC("TBD!!"); + /* We just return 0 here, prevent from WMT-FUNC do other register read/write */ + ret = 0; + break; + case WMT_IC_PIN_GSYNC: + ret = mtk_wcn_soc_gps_sync_ctrl(state, flag); + break; + default: + break; + } + WMT_INFO_FUNC("ret = (%d)\n", ret); + + return ret; +} + +INT32 mtk_wcn_soc_co_clock_ctrl(WMT_CO_CLOCK on) +{ + INT32 iRet = 0; + + if ((WMT_CO_CLOCK_DIS <= on) && (WMT_CO_CLOCK_MAX > on)) { + gCoClockEn = on; + } else { + WMT_DBG_FUNC("0x%x: error parameter:%d\n", wmt_ic_ops_soc.icId, on); + iRet = -1; + } + WMT_DBG_FUNC("0x%x: Co-clock %s\n", wmt_ic_ops_soc.icId, + (gCoClockEn == WMT_CO_CLOCK_DIS) ? "disabled" : "enabled"); + + return iRet; +} + +static MTK_WCN_BOOL mtk_wcn_soc_quick_sleep_flag_get(VOID) +{ + return MTK_WCN_BOOL_TRUE; +} + +static MTK_WCN_BOOL mtk_wcn_soc_aee_dump_flag_get(VOID) +{ + return MTK_WCN_BOOL_FALSE; +} + +WMT_CO_CLOCK mtk_wcn_soc_co_clock_get(VOID) +{ + return gCoClockEn; +} + +static INT32 mtk_wcn_soc_ver_check(VOID) +{ + UINT32 hw_ver; + UINT32 fw_ver; + INT32 iret; + const WMT_IC_INFO_S *p_info; + unsigned long ctrlPa1; + unsigned long ctrlPa2; + + /* 1. identify chip versions: HVR(HW_VER) and FVR(FW_VER) */ + WMT_LOUD_FUNC("0x%x: before read hw_ver (hw version)\n", wmt_ic_ops_soc.icId); + iret = wmt_core_reg_rw_raw(0, GEN_HVR, &hw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("0x%x: read hw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); + return -2; + } + WMT_WARN_FUNC("0x%x: read hw_ver (hw version) (0x%x)\n", wmt_ic_ops_soc.icId, hw_ver); + + WMT_LOUD_FUNC("0x%x: before fw_ver (rom version)\n", wmt_ic_ops_soc.icId); + wmt_core_reg_rw_raw(0, GEN_FVR, &fw_ver, GEN_VER_MASK); + if (iret) { + WMT_ERR_FUNC("0x%x: read fw_ver fail:%d\n", wmt_ic_ops_soc.icId, iret); + return -2; + } + WMT_WARN_FUNC("0x%x: read fw_ver (rom version) (0x%x)\n", wmt_ic_ops_soc.icId, fw_ver); + + p_info = mtk_wcn_soc_find_wmt_ic_info(hw_ver); + if (NULL == p_info) { + WMT_ERR_FUNC("0x%x: hw_ver(0x%x) find wmt ic info fail\n", wmt_ic_ops_soc.icId); + return -3; + } + WMT_WARN_FUNC("0x%x: ic info: %s.%s (0x%x/0x%x, WMTHWVER:%d, patch_ext:%s)\n", + wmt_ic_ops_soc.icId, p_info->cChipName, p_info->cChipVersion, + hw_ver, fw_ver, p_info->eWmtHwVer, p_info->cPatchNameExt); + + /* hw id & version */ + ctrlPa1 = (wmt_ic_ops_soc.icId << 16) | (hw_ver & 0x0000FFFF); + /* translated hw version & fw rom version */ + ctrlPa2 = ((UINT32) (p_info->eWmtHwVer) << 16) | (fw_ver & 0x0000FFFF); + + iret = wmt_core_ctrl(WMT_CTRL_HWIDVER_SET, &ctrlPa1, &ctrlPa2); + if (iret) + WMT_WARN_FUNC("0x%x: WMT_CTRL_HWIDVER_SET fail(%d)\n", wmt_ic_ops_soc.icId, iret); + + gp_soc_info = p_info; + return 0; +} + +static const WMT_IC_INFO_S *mtk_wcn_soc_find_wmt_ic_info(const UINT32 hw_ver) +{ + /* match chipversion with u4HwVer item in mtk_wcn_soc_info_table */ + const UINT32 size = osal_array_size(mtk_wcn_soc_info_table); + INT32 index = 0; + + /* George: reverse the search order to favor newer version products + * TODO:[FixMe][GeorgeKuo] Remove full match once API wmt_lib_get_hwver() + * is changed correctly in the future!! + * Leave full match here is a workaround for GPS to distinguish E3/E4 ICs. + */ + index = size - 1; + /* full match */ + while ((0 <= index) && (hw_ver != mtk_wcn_soc_info_table[index].u4HwVer)) + --index; + if (0 <= index) { + WMT_DBG_FUNC("found ic info(0x%x) by full match! index:%d\n", hw_ver, index); + return &mtk_wcn_soc_info_table[index]; + } + + WMT_WARN_FUNC("find no ic info for (0x%x) by full match!try major num match!\n", hw_ver); + + /* George: The ONLY CORRECT method to find supported hw table. Match MAJOR + * NUM only can help us support future minor hw ECO, or fab switch, etc. + * FULL matching eliminate such flexibility and software package have to be + * updated EACH TIME even when minor hw ECO or fab switch!!! + */ + /* George: reverse the search order to favor newer version products */ + index = size - 1; + /* major num match */ + while ((0 <= index) && + (MAJORNUM(hw_ver) != MAJORNUM(mtk_wcn_soc_info_table[index].u4HwVer))) { + --index; + } + if (0 <= index) { + WMT_DBG_FUNC("0x%x: found ic info for hw_ver(0x%x) by major num! index:%d\n", + wmt_ic_ops_soc.icId, hw_ver, index); + return &mtk_wcn_soc_info_table[index]; + } + + WMT_ERR_FUNC("0x%x: find no ic info for hw_ver(0x%x) by full match nor major num match!\n", + wmt_ic_ops_soc.icId, hw_ver); + WMT_ERR_FUNC("Set default chip version: E1!\n"); + return &mtk_wcn_soc_info_table[0]; +} + +#if CFG_WMT_FILTER_MODE_SETTING +static INT32 wmt_stp_wifi_lte_coex(VOID) +{ + INT32 iRet; + unsigned long addr; + WMT_GEN_CONF *pWmtGenConf; + + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_DBG_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + osal_sleep_ms(5); + + if (pWmtGenConf->coex_wmt_filter_mode == 0) { + if ((0x6752 == wmt_ic_ops_soc.icId) || + (0x6580 == wmt_ic_ops_soc.icId) || + (0x8163 == wmt_ic_ops_soc.icId) || + (0x0326 == wmt_ic_ops_soc.icId) || + (0x0321 == wmt_ic_ops_soc.icId) || + (0x0335 == wmt_ic_ops_soc.icId) || (0x0337 == wmt_ic_ops_soc.icId)) { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_1, osal_array_size(set_wifi_lte_coex_table_1)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_1 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } else if (0x0279 == wmt_ic_ops_soc.icId) { + /* add WMT_COXE_CONFIG_EXT_COMPONENT_OPCODE command for 2G4 eLNA demand*/ + if (pWmtGenConf->coex_wmt_ext_component) { + WMT_INFO_FUNC("coex_wmt_ext_component:0x%x\n", pWmtGenConf->coex_wmt_ext_component); + set_wifi_lte_coex_table_2[0].cmd[5] = pWmtGenConf->coex_wmt_ext_component; + } + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_2, osal_array_size(set_wifi_lte_coex_table_2)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_2 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } else { + iRet = + wmt_core_init_script(set_wifi_lte_coex_table_0, osal_array_size(set_wifi_lte_coex_table_0)); + WMT_DBG_FUNC("wmt_core:set_wifi_lte_coex_table_0 %s(%d)\n", iRet ? "fail" : "ok", iRet); + } + } + + return iRet; +} +#endif + +static INT32 wmt_stp_init_coex(VOID) +{ + INT32 iRet; + unsigned long addr; + WMT_GEN_CONF *pWmtGenConf; + +#define COEX_WMT 0 + +#if CFG_SUBSYS_COEX_NEED + /* no need for MT6628 */ +#define COEX_BT 1 +#define COEX_WIFI 2 +#define COEX_PTA 3 +#define COEX_MISC 4 +#endif + /*Get wmt config */ + iRet = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (iRet) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", iRet); + return -2; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + /*Dump the coex-related info */ + WMT_DBG_FUNC("coex_wmt:0x%x\n", pWmtGenConf->coex_wmt_ant_mode); +#if CFG_SUBSYS_COEX_NEED + WMT_DBG_FUNC("coex_bt:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_bt_rssi_upper_limit, + pWmtGenConf->coex_bt_rssi_mid_limit, + pWmtGenConf->coex_bt_rssi_lower_limit, + pWmtGenConf->coex_bt_pwr_high, pWmtGenConf->coex_bt_pwr_mid, pWmtGenConf->coex_bt_pwr_low); + WMT_DBG_FUNC("coex_wifi:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_wifi_rssi_upper_limit, + pWmtGenConf->coex_wifi_rssi_mid_limit, + pWmtGenConf->coex_wifi_rssi_lower_limit, + pWmtGenConf->coex_wifi_pwr_high, pWmtGenConf->coex_wifi_pwr_mid, pWmtGenConf->coex_wifi_pwr_low); + WMT_DBG_FUNC("coex_ext_pta:0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_ext_pta_hi_tx_tag, + pWmtGenConf->coex_ext_pta_hi_rx_tag, + pWmtGenConf->coex_ext_pta_lo_tx_tag, + pWmtGenConf->coex_ext_pta_lo_rx_tag, + pWmtGenConf->coex_ext_pta_sample_t1, + pWmtGenConf->coex_ext_pta_sample_t2, pWmtGenConf->coex_ext_pta_wifi_bt_con_trx); + WMT_DBG_FUNC("coex_misc:0x%x 0x%x 0x%x\n", + pWmtGenConf->coex_misc_ext_pta_on, pWmtGenConf->coex_misc_ext_feature_set); +#endif + + /*command adjustion due to WMT.cfg */ + coex_table[COEX_WMT].cmd[5] = pWmtGenConf->coex_wmt_ant_mode; + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&coex_table[COEX_WMT].cmd[0], coex_table[COEX_WMT].str, coex_table[COEX_WMT].cmdSz); + +#if CFG_SUBSYS_COEX_NEED + coex_table[COEX_BT].cmd[9] = pWmtGenConf->coex_bt_rssi_upper_limit; + coex_table[COEX_BT].cmd[10] = pWmtGenConf->coex_bt_rssi_mid_limit; + coex_table[COEX_BT].cmd[11] = pWmtGenConf->coex_bt_rssi_lower_limit; + coex_table[COEX_BT].cmd[12] = pWmtGenConf->coex_bt_pwr_high; + coex_table[COEX_BT].cmd[13] = pWmtGenConf->coex_bt_pwr_mid; + coex_table[COEX_BT].cmd[14] = pWmtGenConf->coex_bt_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&coex_table[COEX_BT].cmd[0], coex_table[COEX_BT].str, coex_table[COEX_BT].cmdSz); + + coex_table[COEX_WIFI].cmd[10] = pWmtGenConf->coex_wifi_rssi_upper_limit; + coex_table[COEX_WIFI].cmd[11] = pWmtGenConf->coex_wifi_rssi_mid_limit; + coex_table[COEX_WIFI].cmd[12] = pWmtGenConf->coex_wifi_rssi_lower_limit; + coex_table[COEX_WIFI].cmd[13] = pWmtGenConf->coex_wifi_pwr_high; + coex_table[COEX_WIFI].cmd[14] = pWmtGenConf->coex_wifi_pwr_mid; + coex_table[COEX_WIFI].cmd[15] = pWmtGenConf->coex_wifi_pwr_low; + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&coex_table[COEX_WIFI].cmd[0], + coex_table[COEX_WIFI].str, coex_table[COEX_WIFI].cmdSz); + + coex_table[COEX_PTA].cmd[5] = pWmtGenConf->coex_ext_pta_hi_tx_tag; + coex_table[COEX_PTA].cmd[6] = pWmtGenConf->coex_ext_pta_hi_rx_tag; + coex_table[COEX_PTA].cmd[7] = pWmtGenConf->coex_ext_pta_lo_tx_tag; + coex_table[COEX_PTA].cmd[8] = pWmtGenConf->coex_ext_pta_lo_rx_tag; + coex_table[COEX_PTA].cmd[9] = ((pWmtGenConf->coex_ext_pta_sample_t1 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[10] = ((pWmtGenConf->coex_ext_pta_sample_t1 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[11] = ((pWmtGenConf->coex_ext_pta_sample_t2 & 0xff00) >> 8); + coex_table[COEX_PTA].cmd[12] = ((pWmtGenConf->coex_ext_pta_sample_t2 & 0x00ff) >> 0); + coex_table[COEX_PTA].cmd[13] = pWmtGenConf->coex_ext_pta_wifi_bt_con_trx; + if (gWmtDbgLvl >= WMT_LOG_DBG) + wmt_core_dump_data(&coex_table[COEX_PTA].cmd[0], coex_table[COEX_PTA].str, coex_table[COEX_PTA].cmdSz); + + osal_memcpy(&coex_table[COEX_MISC].cmd[5], &pWmtGenConf->coex_misc_ext_pta_on, + sizeof(pWmtGenConf->coex_misc_ext_pta_on)); + osal_memcpy(&coex_table[COEX_MISC].cmd[9], &pWmtGenConf->coex_misc_ext_feature_set, + sizeof(pWmtGenConf->coex_misc_ext_feature_set)); + + wmt_core_dump_data(&coex_table[COEX_MISC].cmd[0], coex_table[COEX_MISC].str, coex_table[COEX_MISC].cmdSz); +#endif + + iRet = wmt_core_init_script(coex_table, sizeof(coex_table) / sizeof(coex_table[0])); + + return iRet; +} + +#if CFG_WMT_SDIO_DRIVING_SET +static INT32 mtk_wcn_soc_set_sdio_driving(void) +{ + INT32 ret = 0; + + unsigned long addr; + WMT_GEN_CONF *pWmtGenConf; + UINT32 drv_val = 0; + + /*Get wmt config */ + ret = wmt_core_ctrl(WMT_CTRL_GET_WMT_CONF, &addr, 0); + if (ret) { + WMT_ERR_FUNC("ctrl GET_WMT_CONF fail(%d)\n", ret); + return -1; + } + WMT_INFO_FUNC("ctrl GET_WMT_CONF ok(0x%08lx)\n", addr); + + pWmtGenConf = (P_WMT_GEN_CONF) addr; + + /*Check if WMT.cfg exists */ + if (pWmtGenConf->cfgExist == 0) { + WMT_INFO_FUNC("cfgExist == 0, skip config chip\n"); + /*if WMT.cfg not existed, still return success and adopt the default value */ + return 0; + } + + drv_val = pWmtGenConf->sdio_driving_cfg; + + /*Dump the sdio driving related info */ + WMT_INFO_FUNC("sdio driving:0x%x\n", drv_val); + + sdio_driving_table[0].cmd[12] = (UINT8) ((drv_val & 0x00000077UL) >> 0); /* DAT0 and DAT1 */ + sdio_driving_table[0].cmd[13] = (UINT8) ((drv_val & 0x00007700UL) >> 8); /* DAT2 and DAT3 */ + sdio_driving_table[0].cmd[14] = (UINT8) ((drv_val & 0x00070000UL) >> 16); /* CMD */ + + ret = wmt_core_init_script(sdio_driving_table, sizeof(sdio_driving_table) / sizeof(sdio_driving_table[0])); + + return ret; +} +#endif + +#if CFG_WMT_CRYSTAL_TIMING_SET +static INT32 mtk_wcn_soc_crystal_triming_set(VOID) +{ + INT32 iRet = 0; + PUINT8 pbuf = NULL; + UINT32 bufLen = 0; + WMT_CTRL_DATA ctrlData; + UINT32 uCryTimOffset = 0x6D; + MTK_WCN_BOOL bIsNvramExist = MTK_WCN_BOOL_FALSE; + INT8 cCrystalTimingOffset = 0x0; + UINT8 cCrystalTiming = 0x0; + INT32 iCrystalTiming = 0x0; + MTK_WCN_BOOL bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + UINT32 u4Res; + + bIsNvramExist = MTK_WCN_BOOL_FALSE; + /**/ ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_GET; + ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; + ctrlData.au4CtrlData[1] = (UINT32) &pbuf; + ctrlData.au4CtrlData[2] = (UINT32) &bufLen; + + iRet = wmt_ctrl(&ctrlData); + if (0 != iRet) { + WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_GET fail:%d\n", wmt_ic_ops_soc.icId, iRet); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + iRet = -1; + } else { + WMT_DBG_FUNC("0x%x: nvram pBuf(0x%08x), bufLen(%d)\n", wmt_ic_ops_soc.icId, pbuf, bufLen); + if (bufLen < (uCryTimOffset + 1)) { + WMT_ERR_FUNC("0x%x: nvram len(%d) too short, crystalTimging value offset(%d)\n", + wmt_ic_ops_soc.icId, bufLen, uCryTimOffset); + bIsNvramExist = MTK_WCN_BOOL_FALSE; + bIsCrysTrimEnabled = MTK_WCN_BOOL_FALSE; + cCrystalTimingOffset = 0x0; + cCrystalTiming = 0x0; + } else { + bIsNvramExist = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = *(pbuf + uCryTimOffset); + if (cCrystalTimingOffset & 0x80) { + bIsCrysTrimEnabled = MTK_WCN_BOOL_TRUE; + cCrystalTimingOffset = (UINT8) cCrystalTimingOffset & 0x7f; + } + WMT_DBG_FUNC("cCrystalTimingOffset (%d), bIsCrysTrimEnabled(%d)\n", cCrystalTimingOffset, + bIsCrysTrimEnabled); + } + ctrlData.ctrlId = WMT_CTRL_CRYSTAL_TRIMING_PUT; + ctrlData.au4CtrlData[0] = (UINT32) "/data/nvram/APCFG/APRDEB/WIFI"; + iRet = wmt_ctrl(&ctrlData); + if (0 != iRet) { + WMT_ERR_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT fail:%d\n", wmt_ic_ops_soc.icId, iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("0x%x: WMT_CTRL_CRYSTAL_TRIMING_PUT succeed\n", wmt_ic_ops_soc.icId); + } + } + if ((MTK_WCN_BOOL_TRUE == bIsNvramExist) && (MTK_WCN_BOOL_TRUE == bIsCrysTrimEnabled)) { + /*get CrystalTiming value before set it */ + iRet = + wmt_core_tx(get_crystal_timing_script[0].cmd, get_crystal_timing_script[0].cmdSz, &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != get_crystal_timing_script[0].cmdSz)) { + WMT_ERR_FUNC("WMT-CORE: write (%s) iRet(%d) cmd len err(%d, %d)\n", + get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].cmdSz); + iRet = -3; + goto done; + } + /* EVENT BUF */ + osal_memset(get_crystal_timing_script[0].evt, 0, get_crystal_timing_script[0].evtSz); + iRet = wmt_core_rx(get_crystal_timing_script[0].evt, get_crystal_timing_script[0].evtSz, &u4Res); + if (iRet || (u4Res != get_crystal_timing_script[0].evtSz)) { + WMT_ERR_FUNC("WMT-CORE: read (%s) iRet(%d) evt len err(rx:%d, exp:%d)\n", + get_crystal_timing_script[0].str, iRet, u4Res, get_crystal_timing_script[0].evtSz); + mtk_wcn_stp_dbg_dump_package(); + iRet = -4; + goto done; + } + + iCrystalTiming = WMT_GET_CRYSTAL_TRIMING_EVT[5] & 0x7f; + if (cCrystalTimingOffset & 0x40) { + /*nagative offset value */ + iCrystalTiming = iCrystalTiming + cCrystalTimingOffset - 128; + } else { + iCrystalTiming += cCrystalTimingOffset; + } + WMT_DBG_FUNC("iCrystalTiming (0x%x)\n", iCrystalTiming); + cCrystalTiming = iCrystalTiming > 0x7f ? 0x7f : iCrystalTiming; + cCrystalTiming = iCrystalTiming < 0 ? 0 : iCrystalTiming; + WMT_DBG_FUNC("cCrystalTiming (0x%x)\n", cCrystalTiming); + /* set_crystal_timing_script */ + WMT_SET_CRYSTAL_TRIMING_CMD[5] = cCrystalTiming; + WMT_GET_CRYSTAL_TRIMING_EVT[5] = cCrystalTiming; + + iRet = wmt_core_init_script(set_crystal_timing_script, osal_array_size(set_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("set_crystal_timing_script fail(%d)\n", iRet); + iRet = -5; + } else { + WMT_DBG_FUNC("set crystal timing value (0x%x) succeed\n", WMT_SET_CRYSTAL_TRIMING_CMD[5]); + iRet = + wmt_core_init_script(get_crystal_timing_script, osal_array_size(get_crystal_timing_script)); + if (iRet) { + WMT_ERR_FUNC("get_crystal_timing_script fail(%d)\n", iRet); + iRet = -6; + } else { + WMT_INFO_FUNC("succeed, updated crystal timing value (0x%x)\n", + WMT_GET_CRYSTAL_TRIMING_EVT[5]); + iRet = 0x0; + } + } + } +done: + return iRet; +} +#endif + +#if CFG_WMT_MULTI_PATCH +static INT32 mtk_wcn_soc_patch_info_prepare(VOID) +{ + INT32 iRet = -1; + WMT_CTRL_DATA ctrlData; + + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + + return iRet; +} + +static INT32 mtk_wcn_soc_patch_dwn(UINT32 index) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + UINT8 addressevtBuf[12]; + UINT8 addressByte[4]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_soc_info) { + WMT_ERR_FUNC("null gp_soc_info!\n"); + return -1; + } + + osal_memset(gFullPatchName, 0, osal_sizeof(gFullPatchName)); + + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_INFO; + ctrlData.au4CtrlData[0] = index + 1; + ctrlData.au4CtrlData[1] = (SIZE_T) &gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T) &addressByte; + iRet = wmt_ctrl(&ctrlData); + WMT_DBG_FUNC("the %d time valid patch found: (%s)\n", index + 1, gFullPatchName); + + /* <2.2> read patch content */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (SIZE_T) NULL; + ctrlData.au4CtrlData[1] = (SIZE_T) &gFullPatchName; + ctrlData.au4CtrlData[2] = (SIZE_T) &pbuf; + ctrlData.au4CtrlData[3] = (SIZE_T) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + if (index == 0) { + WMT_DBG_FUNC("===========================================\n"); + WMT_INFO_FUNC("[Patch]BuiltTime = %s, HVer = 0x%x, SVer = 0x%x, PhVer = 0x%04x,Platform = %c%c%c%c\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("[Consys Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Ph Ver = 0x%04x\n", + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_DBG_FUNC("[Consys Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], patchHdr->ucPLat[1], + patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("===========================================\n"); + } + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + /* gp_soc_patch_info = patchHdr; */ + osal_memcpy(&gp_soc_patch_info, patchHdr, osal_sizeof(WMT_PATCH)); + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + /*send wmt part patch address command */ + if (0x6752 == wmt_ic_ops_soc.icId || + 0x8127 == wmt_ic_ops_soc.icId || + 0x7623 == wmt_ic_ops_soc.icId || + 0x6571 == wmt_ic_ops_soc.icId || + 0x0326 == wmt_ic_ops_soc.icId || + 0x0321 == wmt_ic_ops_soc.icId || + 0x0335 == wmt_ic_ops_soc.icId || + 0x0337 == wmt_ic_ops_soc.icId || 0x8163 == wmt_ic_ops_soc.icId || 0x6580 == wmt_ic_ops_soc.icId) { + /* MT6571 patch RAM base */ + WMT_PATCH_ADDRESS_CMD[8] = 0x40; + WMT_PATCH_P_ADDRESS_CMD[8] = 0xc8; + } + /*send wmt part patch address command */ + if (0x0279 == wmt_ic_ops_soc.icId) { + /* MT6797 patch RAM base */ + WMT_PATCH_ADDRESS_CMD[8] = 0x08; + WMT_PATCH_ADDRESS_CMD[9] = 0x05; + WMT_PATCH_P_ADDRESS_CMD[8] = 0x2c; + WMT_PATCH_P_ADDRESS_CMD[9] = 0x0b; + } + + /*send wmt part patch address command */ + iRet = + wmt_core_tx((PUINT8) &WMT_PATCH_ADDRESS_CMD[0], sizeof(WMT_PATCH_ADDRESS_CMD), &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt patch address CMD fail(%d),size(%d)\n", iRet, u4Res); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf, sizeof(WMT_PATCH_ADDRESS_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_ADDRESS_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d)\n", iRet, u4Res); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail\n"); + iRet -= 1; + goto done; + } +#endif + + /*send part patch address command */ + osal_memcpy(&WMT_PATCH_P_ADDRESS_CMD[12], addressByte, osal_sizeof(addressByte)); + WMT_DBG_FUNC("4 bytes address command:0x%02x,0x%02x,0x%02x,0x%02x", + WMT_PATCH_P_ADDRESS_CMD[12], + WMT_PATCH_P_ADDRESS_CMD[13], WMT_PATCH_P_ADDRESS_CMD[14], WMT_PATCH_P_ADDRESS_CMD[15]); + iRet = + wmt_core_tx((PUINT8) &WMT_PATCH_P_ADDRESS_CMD[0], sizeof(WMT_PATCH_P_ADDRESS_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_CMD))) { + WMT_ERR_FUNC("wmt_core:wmt part patch address CMD fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); + iRet -= 1; + goto done; + } + osal_memset(addressevtBuf, 0, sizeof(addressevtBuf)); + iRet = wmt_core_rx(addressevtBuf, sizeof(WMT_PATCH_P_ADDRESS_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_P_ADDRESS_EVT))) { + WMT_ERR_FUNC("wmt_core:wmt patch address EVT fail(%d),size(%d),index(%d)\n", iRet, u4Res, index); + iRet -= 1; + goto done; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(addressevtBuf, WMT_PATCH_P_ADDRESS_EVT, osal_sizeof(WMT_PATCH_ADDRESS_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: write WMT_PATCH_ADDRESS_CMD status fail,index(%d)\n", index); + iRet -= 1; + goto done; + } +#endif + + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum - 1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST : WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag */ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + /* iRet = + *(*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), + *&u4Res); + */ + iRet = + wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), + &u4Res, MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet -= 1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + /* iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); */ + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), + u4Res, iRet); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, + evtBuf[0], + evtBuf[1], + evtBuf[2], + evtBuf[3], + evtBuf[4]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_PATCH_EVT), + WMT_PATCH_EVT[0], + WMT_PATCH_EVT[1], + WMT_PATCH_EVT[2], + WMT_PATCH_EVT[3], + WMT_PATCH_EVT[4]); + iRet -= 1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); + + if (fragSeq != fragNum) + iRet -= 1; +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + /* wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); */ + ctrlData.ctrlId = WMT_CTRL_FREE_PATCH; + ctrlData.au4CtrlData[0] = index + 1; + wmt_ctrl(&ctrlData); + + return iRet; +} + +#else +static INT32 mtk_wcn_soc_patch_dwn(VOID) +{ + INT32 iRet = -1; + P_WMT_PATCH patchHdr; + PUINT8 pbuf; + UINT32 patchSize; + UINT32 fragSeq; + UINT32 fragNum; + UINT16 fragSize = 0; + UINT16 cmdLen; + UINT32 offset; + UINT32 u4Res; + UINT8 evtBuf[8]; + PINT8 cDataTime = NULL; + /*PINT8 cPlat = NULL; */ + UINT16 u2HwVer = 0; + UINT16 u2SwVer = 0; + UINT32 u4PatchVer = 0; + UINT32 patchSizePerFrag = 0; + WMT_CTRL_DATA ctrlData; + + /*1.check hardware information */ + if (NULL == gp_soc_info) { + WMT_ERR_FUNC("null gp_soc_info!\n"); + return -1; + } + /* <2> search patch and read patch content */ + /* <2.1> search patch */ + ctrlData.ctrlId = WMT_CTRL_PATCH_SEARCH; + iRet = wmt_ctrl(&ctrlData); + if (0 == iRet) { + /* patch with correct Hw Ver Major Num found */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH_NAME; + ctrlData.au4CtrlData[0] = (UINT32) &gFullPatchName; + iRet = wmt_ctrl(&ctrlData); + + WMT_INFO_FUNC("valid patch found: (%s)\n", gFullPatchName); + /* <2.2> read patch content */ + ctrlData.ctrlId = WMT_CTRL_GET_PATCH; + ctrlData.au4CtrlData[0] = (UINT32) NULL; + ctrlData.au4CtrlData[1] = (UINT32) &gFullPatchName; + + } else { + iRet -= 1; + return iRet; + } + ctrlData.au4CtrlData[2] = (UINT32) &pbuf; + ctrlData.au4CtrlData[3] = (UINT32) &patchSize; + iRet = wmt_ctrl(&ctrlData); + if (iRet) { + WMT_ERR_FUNC("wmt_core: WMT_CTRL_GET_PATCH fail:%d\n", iRet); + iRet -= 1; + goto done; + } + + /* |<-BCNT_PATCH_BUF_HEADROOM(8) bytes dummy allocated->|<-patch file->| */ + pbuf += BCNT_PATCH_BUF_HEADROOM; + /* patch file with header: + * |<-patch header: 28 Bytes->|<-patch body: X Bytes ----->| + */ + patchHdr = (P_WMT_PATCH) pbuf; + /* check patch file information */ + + cDataTime = patchHdr->ucDateTime; + u2HwVer = patchHdr->u2HwVer; + u2SwVer = patchHdr->u2SwVer; + u4PatchVer = patchHdr->u4PatchVer; + /*cPlat = &patchHdr->ucPLat[0]; */ + + cDataTime[15] = '\0'; + WMT_DBG_FUNC("===========================================\n"); + WMT_INFO_FUNC("[ConsysPatch]BuiltTime = %s, HVer = 0x%x, SVer = 0x%x, PhVer = 0x%04x,Platform = %c%c%c%c\n", + cDataTime, ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8), + ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8), + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16), + patchHdr->ucPLat[0], patchHdr->ucPLat[1], patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("[Consys Patch] Hw Ver = 0x%x\n", ((u2HwVer & 0x00ff) << 8) | ((u2HwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Sw Ver = 0x%x\n", ((u2SwVer & 0x00ff) << 8) | ((u2SwVer & 0xff00) >> 8)); + WMT_DBG_FUNC("[Consys Patch] Ph Ver = 0x%04x\n", + ((u4PatchVer & 0xff000000) >> 24) | ((u4PatchVer & 0x00ff0000) >> 16)); + WMT_DBG_FUNC("[Consys Patch] Platform = %c%c%c%c\n", patchHdr->ucPLat[0], patchHdr->ucPLat[1], + patchHdr->ucPLat[2], patchHdr->ucPLat[3]); + WMT_DBG_FUNC("===========================================\n"); + + /* remove patch header: + * |<-patch body: X Bytes (X=patchSize)--->| + */ + patchSize -= sizeof(WMT_PATCH); + pbuf += sizeof(WMT_PATCH); + patchSizePerFrag = DEFAULT_PATCH_FRAG_SIZE; + /* reserve 1st patch cmd space before patch body + * |<-WMT_CMD: 5Bytes->|<-patch body: X Bytes (X=patchSize)----->| + */ + pbuf -= sizeof(WMT_PATCH_CMD); + + fragNum = patchSize / patchSizePerFrag; + fragNum += ((fragNum * patchSizePerFrag) == patchSize) ? 0 : 1; + + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + + /* send all fragments */ + offset = sizeof(WMT_PATCH_CMD); + fragSeq = 0; + while (fragSeq < fragNum) { + WMT_DBG_FUNC("patch size(%d) fragNum(%d)\n", patchSize, fragNum); + if (fragSeq == (fragNum - 1)) { + /* last fragment */ + fragSize = patchSize - fragSeq * patchSizePerFrag; + WMT_PATCH_CMD[4] = WMT_PATCH_FRAG_LAST; + } else { + fragSize = patchSizePerFrag; + WMT_PATCH_CMD[4] = (fragSeq == 0) ? WMT_PATCH_FRAG_1ST : WMT_PATCH_FRAG_MID; + } + /* update length field in CMD:flag+frag */ + cmdLen = 1 + fragSize; + osal_memcpy(&WMT_PATCH_CMD[2], &cmdLen, 2); + /* copy patch CMD to buf (overwrite last 5-byte in prev frag) */ + osal_memcpy(pbuf + offset - sizeof(WMT_PATCH_CMD), WMT_PATCH_CMD, sizeof(WMT_PATCH_CMD)); + + /* iRet = + * (*kal_stp_tx)(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), + * &u4Res); + */ + iRet = + wmt_core_tx(pbuf + offset - sizeof(WMT_PATCH_CMD), fragSize + sizeof(WMT_PATCH_CMD), &u4Res, + MTK_WCN_BOOL_FALSE); + if (iRet || (u4Res != fragSize + sizeof(WMT_PATCH_CMD))) { + WMT_ERR_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) fail(%d)\n", fragSeq, + fragSize + sizeof(WMT_PATCH_CMD), u4Res, iRet); + iRet -= 1; + break; + } + WMT_DBG_FUNC("wmt_core: write fragSeq(%d) size(%d, %d) ok\n", + fragSeq, fragSize + sizeof(WMT_PATCH_CMD), u4Res); + + osal_memset(evtBuf, 0, sizeof(evtBuf)); + /* iRet = (*kal_stp_rx)(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); */ + iRet = wmt_core_rx(evtBuf, sizeof(WMT_PATCH_EVT), &u4Res); + if (iRet || (u4Res != sizeof(WMT_PATCH_EVT))) { + WMT_ERR_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) fail(%d)\n", sizeof(WMT_PATCH_EVT), + u4Res, iRet); + iRet -= 1; + break; + } +#if CFG_CHECK_WMT_RESULT + if (osal_memcmp(evtBuf, WMT_PATCH_EVT, sizeof(WMT_PATCH_EVT)) != 0) { + WMT_ERR_FUNC("wmt_core: compare WMT_PATCH_EVT error rx(%d):[%02X,%02X,%02X,%02X,%02X]\n", + u4Res, + evtBuf[0], + evtBuf[1], + evtBuf[2], + evtBuf[3], + evtBuf[4]); + WMT_ERR_FUNC("wmt_core: exp(%d):[%02X,%02X,%02X,%02X,%02X]\n", + sizeof(WMT_PATCH_EVT), + WMT_PATCH_EVT[0], + WMT_PATCH_EVT[1], + WMT_PATCH_EVT[2], + WMT_PATCH_EVT[3], + WMT_PATCH_EVT[4]); + iRet -= 1; + break; + } +#endif + WMT_DBG_FUNC("wmt_core: read WMT_PATCH_EVT length(%d, %d) ok\n", sizeof(WMT_PATCH_EVT), u4Res); + offset += patchSizePerFrag; + ++fragSeq; + } + + WMT_WARN_FUNC("wmt_core: patch dwn:%d frag(%d, %d) %s\n", + iRet, fragSeq, fragSize, (!iRet && (fragSeq == fragNum)) ? "ok" : "fail"); + + if (fragSeq != fragNum) + iRet -= 1; +done: + /* WMT_CTRL_FREE_PATCH always return 0 */ + wmt_core_ctrl(WMT_CTRL_FREE_PATCH, NULL, NULL); + + return iRet; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c new file mode 100644 index 0000000000000..747ed64af2d2d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_lib.c @@ -0,0 +1,1938 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-LIB]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include "wmt_dev.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "wmt_core.h" +#include "wmt_plat.h" + +#include "stp_core.h" +#include "btm_core.h" +#include "psm_core.h" +#include "stp_dbg.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* A table for translation: CMB_STUB_AIF_X=>WMT_IC_PIN_STATE */ +static const WMT_IC_PIN_STATE cmb_aif2pin_stat[] = { + [CMB_STUB_AIF_0] = WMT_IC_AIF_0, + [CMB_STUB_AIF_1] = WMT_IC_AIF_1, + [CMB_STUB_AIF_2] = WMT_IC_AIF_2, + [CMB_STUB_AIF_3] = WMT_IC_AIF_3, +}; + +#if CFG_WMT_PS_SUPPORT +static UINT32 gPsIdleTime = STP_PSM_IDLE_TIME_SLEEP; +static UINT32 gPsEnable = 1; +static PF_WMT_SDIO_PSOP sdio_own_ctrl; +#endif + +#define WMT_STP_CPUPCR_BUF_SIZE 6144 +static UINT8 g_cpupcr_buf[WMT_STP_CPUPCR_BUF_SIZE] = { 0 }; + +static UINT32 g_quick_sleep_ctrl = 1; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +DEV_WMT gDevWmt; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_WMT_PS_SUPPORT +static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action); +static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID); +static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID); +static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID); +static INT32 wmt_lib_ps_handler(MTKSTP_PSM_ACTION_T action); +#endif + +static MTK_WCN_BOOL wmt_lib_put_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pLxOp); + +static P_OSAL_OP wmt_lib_get_op(P_OSAL_OP_Q pOpQ); + +static INT32 wmtd_thread(PVOID pvData); + +static INT32 wmt_lib_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag); +static MTK_WCN_BOOL wmt_lib_hw_state_show(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +INT32 wmt_lib_idc_lock_aquire(VOID) +{ + return osal_lock_sleepable_lock(&gDevWmt.idc_lock); +} + +VOID wmt_lib_idc_lock_release(VOID) +{ + osal_unlock_sleepable_lock(&gDevWmt.idc_lock); +} +INT32 wmt_lib_psm_lock_aquire(void) +{ + return osal_lock_sleepable_lock(&gDevWmt.psm_lock); +} + +void wmt_lib_psm_lock_release(void) +{ + osal_unlock_sleepable_lock(&gDevWmt.psm_lock); +} + +INT32 DISABLE_PSM_MONITOR(void) +{ + INT32 ret = 0; + + /* osal_lock_sleepable_lock(&gDevWmt.psm_lock); */ + ret = wmt_lib_psm_lock_aquire(); + if (ret) { + WMT_ERR_FUNC("--->lock psm_lock failed, ret=%d\n", ret); + return ret; + } +#if CFG_WMT_PS_SUPPORT + ret = wmt_lib_ps_disable(); + if (ret) { + WMT_ERR_FUNC("wmt_lib_ps_disable fail, ret=%d\n", ret); + wmt_lib_psm_lock_release(); + } +#endif + + return ret; +} + +void ENABLE_PSM_MONITOR(void) +{ +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_enable(); +#endif + /* osal_unlock_sleepable_lock(&gDevWmt.psm_lock); */ + wmt_lib_psm_lock_release(); +} + +INT32 wmt_lib_init(VOID) +{ + INT32 iRet; + UINT32 i; + P_DEV_WMT pDevWmt; + P_OSAL_THREAD pThraed; + + /* create->init->start */ + /* 1. create: static allocation with zero initialization */ + pDevWmt = &gDevWmt; + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); + + iRet = wmt_conf_read_file(); + if (iRet) { + WMT_ERR_FUNC("read wmt config file fail(%d)\n", iRet); + return -1; + } + + pThraed = &gDevWmt.thread; + + /* Create mtk_wmtd thread */ + osal_strncpy(pThraed->threadName, "mtk_wmtd", sizeof(pThraed->threadName)); + pThraed->pThreadData = (VOID *) pDevWmt; + pThraed->pThreadFunc = (VOID *) wmtd_thread; + iRet = osal_thread_create(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_create(0x%p) fail(%d)\n", pThraed, iRet); + return -2; + } + + /* 2. initialize */ + /* Initialize wmt_core */ + + iRet = wmt_core_init(); + if (iRet) { + WMT_ERR_FUNC("wmt_core_init() fail(%d)\n", iRet); + return -1; + } + + /* Initialize WMTd Thread Information: Thread */ + osal_event_init(&pDevWmt->rWmtdWq); + osal_sleepable_lock_init(&pDevWmt->psm_lock); + osal_sleepable_lock_init(&pDevWmt->idc_lock); + osal_sleepable_lock_init(&pDevWmt->rActiveOpQ.sLock); + osal_sleepable_lock_init(&pDevWmt->rFreeOpQ.sLock); + pDevWmt->state.data = 0; + + /* Initialize op queue */ + RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); + RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); + /* Put all to free Q */ + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_init(&(pDevWmt->arQue[i].signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); + } + + /* initialize stp resources */ + osal_event_init(&pDevWmt->rWmtRxWq); + + /*function driver callback */ + for (i = 0; i < WMTDRV_TYPE_WIFI; i++) + pDevWmt->rFdrvCb.fDrvRst[i] = NULL; + + pDevWmt->hw_ver = WMTHWVER_MAX; + WMT_INFO_FUNC("***********Init, hw->ver = %x\n", pDevWmt->hw_ver); + + /* TODO:[FixMe][GeorgeKuo]: wmt_lib_conf_init */ + /* initialize default configurations */ + /* i4Result = wmt_lib_conf_init(VOID); */ + /* WMT_WARN_FUNC("wmt_drv_conf_init(%d)\n", i4Result); */ + + osal_signal_init(&pDevWmt->cmdResp); + osal_event_init(&pDevWmt->cmdReq); + + /* initialize platform resources */ + if (0 != gDevWmt.rWmtGenConf.cfgExist) + iRet = wmt_plat_init(gDevWmt.rWmtGenConf.co_clock_flag & 0x0f); + else + iRet = wmt_plat_init(0); + + if (iRet) { + WMT_ERR_FUNC("wmt_plat_init() fail(%d)\n", iRet); + return -3; + } +#if CFG_WMT_PS_SUPPORT + iRet = wmt_lib_ps_init(); + if (iRet) { + WMT_ERR_FUNC("wmt_lib_ps_init() fail(%d)\n", iRet); + return -4; + } +#endif + + /* 3. start: start running mtk_wmtd */ + iRet = osal_thread_run(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_run(0x%p) fail(%d)\n", pThraed, iRet); + return -5; + } + + /*4. register irq callback to WMT-PLAT */ + wmt_plat_irq_cb_reg(wmt_lib_ps_irq_cb); + + /*5. register audio if control callback to WMT-PLAT */ + wmt_plat_aif_cb_reg(wmt_lib_set_aif); + + /*6. register function control callback to WMT-PLAT */ + wmt_plat_func_ctrl_cb_reg(mtk_wcn_wmt_func_ctrl_for_plat); + + wmt_plat_deep_idle_ctrl_cb_reg(mtk_wcn_consys_stp_btif_dpidle_ctrl); + /*7 reset gps/bt state */ + + mtk_wcn_wmt_system_state_reset(); + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_wmt_exp_init(); +#endif + +#if CFG_WMT_LTE_COEX_HANDLING + wmt_idc_init(); +#endif + WMT_DBG_FUNC("init success\n"); + return 0; +} + +INT32 wmt_lib_deinit(VOID) +{ + INT32 iRet; + P_DEV_WMT pDevWmt; + P_OSAL_THREAD pThraed; + INT32 i; + INT32 iResult; + + pDevWmt = &gDevWmt; + pThraed = &gDevWmt.thread; + iResult = 0; + + /* stop->deinit->destroy */ + + /* 1. stop: stop running mtk_wmtd */ + iRet = osal_thread_stop(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); + iResult += 1; + } + + /* 2. deinit: */ + +#if CFG_WMT_PS_SUPPORT + iRet = wmt_lib_ps_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_lib_ps_deinit fail(%d)\n", iRet); + iResult += 2; + } +#endif + + iRet = wmt_plat_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_plat_deinit fail(%d)\n", iRet); + iResult += 4; + } + + osal_event_deinit(&pDevWmt->cmdReq); + osal_signal_deinit(&pDevWmt->cmdResp); + + /* de-initialize stp resources */ + osal_event_deinit(&pDevWmt->rWmtRxWq); + + for (i = 0; i < WMT_OP_BUF_SIZE; i++) + osal_signal_deinit(&(pDevWmt->arQue[i].signal)); + + + osal_sleepable_lock_deinit(&pDevWmt->rFreeOpQ.sLock); + osal_sleepable_lock_deinit(&pDevWmt->rActiveOpQ.sLock); + osal_sleepable_lock_deinit(&pDevWmt->idc_lock); + osal_sleepable_lock_deinit(&pDevWmt->psm_lock); + osal_event_deinit(&pDevWmt->rWmtdWq); + + iRet = wmt_core_deinit(); + if (iRet) { + WMT_ERR_FUNC("wmt_core_deinit fail(%d)\n", iRet); + iResult += 8; + } + + /* 3. destroy */ + iRet = osal_thread_destroy(pThraed); + if (iRet) { + WMT_ERR_FUNC("osal_thread_stop(0x%p) fail(%d)\n", pThraed, iRet); + iResult += 16; + } + osal_memset(&gDevWmt, 0, sizeof(gDevWmt)); + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_wmt_exp_deinit(); +#endif + +#if CFG_WMT_LTE_COEX_HANDLING + wmt_idc_deinit(); +#endif + + return iResult; +} + +VOID wmt_lib_flush_rx(VOID) +{ + mtk_wcn_stp_flush_rx_queue(WMT_TASK_INDX); +} + +INT32 wmt_lib_trigger_cmd_signal(INT32 result) +{ + P_OSAL_SIGNAL pSignal = &gDevWmt.cmdResp; + + gDevWmt.cmdResult = result; + osal_raise_signal(pSignal); + WMT_DBG_FUNC("wakeup cmdResp\n"); + return 0; +} + +P_OSAL_EVENT wmt_lib_get_cmd_event(VOID) +{ + return &gDevWmt.cmdReq; +} + +INT32 wmt_lib_set_patch_name(PUINT8 cPatchName) +{ + osal_strncpy(gDevWmt.cPatchName, cPatchName, NAME_MAX); + return 0; +} + +INT32 wmt_lib_set_hif(unsigned long hifconf) +{ + UINT32 val; + P_WMT_HIF_CONF pHif = &gDevWmt.rWmtHifConf; + + val = hifconf & 0xF; + if (STP_UART_FULL == val) { + pHif->hifType = WMT_HIF_UART; + val = (hifconf >> 8); + pHif->au4HifConf[0] = val; + pHif->au4HifConf[1] = val; + mtk_wcn_stp_set_if_tx_type(STP_UART_IF_TX); + } else if (STP_SDIO == val) { + pHif->hifType = WMT_HIF_SDIO; + mtk_wcn_stp_set_if_tx_type(STP_SDIO_IF_TX); + } else if (STP_BTIF_FULL == val) { + pHif->hifType = WMT_HIF_BTIF; + mtk_wcn_stp_set_if_tx_type(STP_BTIF_IF_TX); + } else { + WMT_WARN_FUNC("invalid stp mode: %u\n", val); + mtk_wcn_stp_set_if_tx_type(STP_MAX_IF_TX); + return -1; + } + + val = (hifconf & 0xF0) >> 4; + if (WMT_FM_COMM == val) { + pHif->au4StrapConf[0] = WMT_FM_COMM; + } else if (WMT_FM_I2C == val) { + pHif->au4StrapConf[0] = WMT_FM_I2C; + } else { + WMT_WARN_FUNC("invalid fm mode: %u\n", val); + return -2; + } + + WMT_WARN_FUNC("new hifType: %d, fm:%d\n", pHif->hifType, pHif->au4StrapConf[0]); + return 0; +} + +P_WMT_HIF_CONF wmt_lib_get_hif(VOID) +{ + return &gDevWmt.rWmtHifConf; +} + +PUINT8 wmt_lib_get_cmd(VOID) +{ + if (osal_test_and_clear_bit(WMT_STAT_CMD, &gDevWmt.state)) + return gDevWmt.cCmd; + + return NULL; +} + +MTK_WCN_BOOL wmt_lib_get_cmd_status(VOID) +{ + return osal_test_bit(WMT_STAT_CMD, &gDevWmt.state) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} + +#if CFG_WMT_PS_SUPPORT +INT32 wmt_lib_ps_set_idle_time(UINT32 psIdleTime) +{ + gPsIdleTime = psIdleTime; + return gPsIdleTime; +} + +INT32 wmt_lib_ps_ctrl(UINT32 state) +{ + if (0 == state) { + wmt_lib_ps_disable(); + gPsEnable = 0; + } else { + gPsEnable = 1; + wmt_lib_ps_enable(); + } + return 0; +} + +INT32 wmt_lib_ps_enable(VOID) +{ + if (gPsEnable) + mtk_wcn_stp_psm_enable(gPsIdleTime); + + return 0; +} + +INT32 wmt_lib_ps_disable(VOID) +{ + if (gPsEnable) + return mtk_wcn_stp_psm_disable(); + + return 0; +} + +INT32 wmt_lib_ps_init(VOID) +{ + /* mtk_wcn_stp_psm_register_wmt_cb(wmt_lib_ps_stp_cb); */ + return 0; +} + +INT32 wmt_lib_ps_deinit(VOID) +{ + /* mtk_wcn_stp_psm_unregister_wmt_cb(); */ + return 0; +} + +static MTK_WCN_BOOL wmt_lib_ps_action(MTKSTP_PSM_ACTION_T action) +{ + P_OSAL_OP lxop; + MTK_WCN_BOOL bRet; + UINT32 u4Wait; + P_OSAL_SIGNAL pSignal; + + lxop = wmt_lib_get_free_op(); + if (!lxop) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + pSignal = &lxop->signal; + pSignal->timeoutValue = 0; + lxop->op.opId = WMT_OPID_PWR_SV; + lxop->op.au4OpData[0] = action; + lxop->op.au4OpData[1] = (SIZE_T) mtk_wcn_stp_psm_notify_stp; + u4Wait = 0; + bRet = wmt_lib_put_act_op(lxop); + return bRet; +} + +#if CFG_WMT_LTE_COEX_HANDLING +MTK_WCN_BOOL wmt_lib_handle_idc_msg(ipc_ilm_t *idc_infor) +{ + P_OSAL_OP lxop; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + INT32 ret = 0; + UINT16 msg_len = 0; + static UINT8 msg_local_buffer[1300]; +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; +#endif + WMT_DBG_FUNC("idc_infor from conn_md is 0x%p\n", idc_infor); + ret = wmt_lib_idc_lock_aquire(); + if (ret) { + WMT_ERR_FUNC("--->lock idc_lock failed, ret=%d\n", ret); + return MTK_WCN_BOOL_FALSE; + } + msg_len = idc_infor->local_para_ptr->msg_len - osal_sizeof(local_para_struct); + osal_memcpy(&msg_local_buffer[0], &msg_len, osal_sizeof(msg_len)); + osal_memcpy(&msg_local_buffer[osal_sizeof(msg_len)], + &(idc_infor->local_para_ptr->data[0]), msg_len - 1); + wmt_lib_idc_lock_release(); + lxop = wmt_lib_get_free_op(); + if (!lxop) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + pSignal = &lxop->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + lxop->op.opId = WMT_OPID_IDC_MSG_HANDLING; + lxop->op.au4OpData[0] = (size_t) msg_local_buffer; + /*msg opcode fill rule is still not clrear,need scott comment */ + /***********************************************************/ + WMT_DBG_FUNC("ilm msg id is (0x%08x)\n", idc_infor->msg_id); + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + switch (idc_infor->msg_id) { + case IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_PARA; + break; + case IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_FREQ; + break; + case IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_WIFI_MAX_POWER; + break; + case IPC_MSG_ID_EL1_LTE_TX_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_INDICATION; + break; + case IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND: + lxop->op.au4OpData[1] = WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS; + break; + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + break; + } + + if (MTK_WCN_BOOL_FALSE == unknown_msgid) { + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(lxop); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(lxop); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) + WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); + else + WMT_DBG_FUNC("OPID(%d) type(%d) ok\n", lxop->op.opId, lxop->op.au4OpData[1]); + } else { + bRet = MTK_WCN_BOOL_FALSE; + wmt_lib_put_op_to_free_queue(lxop); + WMT_ERR_FUNC("unknown msgid from LTE(%d)\n", idc_infor->msg_id); + } +#else + if ((idc_infor->msg_id >= IPC_EL1_MSG_ID_BEGIN) + && (idc_infor->msg_id <= IPC_EL1_MSG_ID_BEGIN + IPC_EL1_MSG_ID_RANGE)) { + lxop->op.au4OpData[1] = idc_infor->msg_id - IPC_EL1_MSG_ID_BEGIN + LTE_MSG_ID_OFFSET - 1; + + WMT_DBG_FUNC("LTE->CONN:(0x%x->0x%zx)\n", idc_infor->msg_id, lxop->op.au4OpData[1]); + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(lxop); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(lxop); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_IDC_MSG_HANDLING fail(%d)\n", bRet); + } else { + WMT_DBG_FUNC("wmt_lib_handle_idc_msg OPID(%d) type(%d) ok\n", + lxop->op.opId, lxop->op.au4OpData[1]); + } + } else { + wmt_lib_put_op_to_free_queue(lxop); + WMT_ERR_FUNC("msgid(%d) out of range,wmt drop it!\n", idc_infor->msg_id); + } +#endif + + return bRet; +} +#endif + +static MTK_WCN_BOOL wmt_lib_ps_do_sleep(VOID) +{ + return wmt_lib_ps_action(SLEEP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_wakeup(VOID) +{ + return wmt_lib_ps_action(WAKEUP); +} + +static MTK_WCN_BOOL wmt_lib_ps_do_host_awake(VOID) +{ +#if 1 + return wmt_lib_ps_action(WAKEUP); +#else + return wmt_lib_ps_action(HOST_AWAKE); +#endif +} + +/* extern int g_block_tx; */ +static INT32 wmt_lib_ps_handler(MTKSTP_PSM_ACTION_T action) +{ + INT32 ret; + + ret = 0; /* TODO:[FixMe][George] initial value or compile warning? */ + /* if(g_block_tx && (action == SLEEP)) */ + if ((0 != mtk_wcn_stp_coredump_start_get()) && (action == SLEEP)) { + mtk_wcn_stp_psm_notify_stp(SLEEP); + return ret; + } + + /*MT662x Not Ready */ + if (!mtk_wcn_stp_is_ready()) { + WMT_DBG_FUNC("MT662x Not Ready, Dont Send Sleep/Wakeup Command\n"); + mtk_wcn_stp_psm_notify_stp(ROLL_BACK); + return 0; + } + + if (SLEEP == action) { + WMT_DBG_FUNC("send op-----------> sleep job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + ret = wmt_lib_ps_do_sleep(); + WMT_DBG_FUNC("enable host eirq\n"); + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_EN); +#if CFG_WMT_DUMP_INT_STATUS + if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) + wmt_plat_BGF_irq_dump_status(); +#endif + } else { + /* ret = mtk_wcn_stp_sdio_do_own_set(); */ + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl) (OWN_SET); + } else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + if (!ret) { + mtk_wcn_stp_psm_notify_stp(SLEEP); + } else if (ret == -2) { + mtk_wcn_stp_psm_notify_stp(ROLL_BACK); + WMT_WARN_FUNC("===[SDIO-PS] rollback due to tx busy===%%\n"); + } else { + mtk_wcn_stp_psm_notify_stp(SLEEP); + WMT_ERR_FUNC("===[SDIO-PS] set own fails!===%%\n"); + } + } + + WMT_DBG_FUNC("send op<---------- sleep job\n"); + } else if (WAKEUP == action) { + WMT_DBG_FUNC("send op --------> wake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq\n"); +#if CFG_WMT_DUMP_INT_STATUS + if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) + wmt_plat_BGF_irq_dump_status(); +#endif + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + ret = wmt_lib_ps_do_wakeup(); + } else { + /* ret = mtk_wcn_stp_sdio_do_own_clr(); */ + + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl) (OWN_CLR); + } else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + if (!ret) { + mtk_wcn_stp_psm_notify_stp(WAKEUP); + } else { + mtk_wcn_stp_psm_notify_stp(WAKEUP); + WMT_ERR_FUNC("===[SDIO-PS] set own back fails!===%%\n"); + } + } + + WMT_DBG_FUNC("send op<---------- wake job\n"); + } else if (HOST_AWAKE == action) { + WMT_DBG_FUNC("send op-----------> host awake job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq\n"); + /* IRQ already disabled */ + /* wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); */ +#if 0 + if (MTK_WCN_BOOL_TRUE == wmt_plat_dump_BGF_irq_status()) + wmt_plat_BGF_irq_dump_status(); +#endif + ret = wmt_lib_ps_do_host_awake(); + } else { + WMT_DBG_FUNC("[SDIO-PS] SDIO host awake! ####\n"); + + /* ret = mtk_wcn_stp_sdio_do_own_clr(); */ + + if (sdio_own_ctrl) { + ret = (*sdio_own_ctrl) (OWN_CLR); + } else { + WMT_ERR_FUNC("sdio_own_ctrl is not registered\n"); + ret = -1; + } + + /* Here we set ret to 0 directly */ + ret = 0; + if (!ret) { + mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); + } else { + mtk_wcn_stp_psm_notify_stp(HOST_AWAKE); + WMT_ERR_FUNC("===[SDIO-PS]set own back fails!===%%\n"); + } + } + + WMT_DBG_FUNC("send op<----------- host awake job\n"); + } else if (EIRQ == action) { + WMT_DBG_FUNC("send op -------------> eirq job\n"); + + if (!mtk_wcn_stp_is_sdio_mode()) { + WMT_DBG_FUNC("disable host eirq\n"); + /* Disable interrupt */ + /* wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); */ + ret = mtk_wcn_stp_psm_notify_stp(EIRQ); + } else { + WMT_ERR_FUNC("[SDIO-PS]sdio own-back eirq!######\n"); + ret = mtk_wcn_stp_psm_notify_stp(EIRQ); + } + + WMT_DBG_FUNC("send op<----------- eirq job\n"); + } + + return ret; +} +#endif /* end of CFG_WMT_PS_SUPPORT */ + +INT32 wmt_lib_ps_stp_cb(MTKSTP_PSM_ACTION_T action) +{ +#if CFG_WMT_PS_SUPPORT + return wmt_lib_ps_handler(action); +#else + WMT_WARN_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); + return 0; +#endif +} + +MTK_WCN_BOOL wmt_lib_is_quick_ps_support(VOID) +{ + if ((g_quick_sleep_ctrl) && (wmt_dev_get_early_suspend_state() == MTK_WCN_BOOL_TRUE)) + return wmt_core_is_quick_ps_support(); + else + return MTK_WCN_BOOL_FALSE; +} + +VOID wmt_lib_ps_irq_cb(VOID) +{ +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_handler(EIRQ); +#else + WMT_DBG_FUNC("CFG_WMT_PS_SUPPORT is not set\n"); + return; +#endif +} + +VOID wmt_lib_ps_set_sdio_psop(PF_WMT_SDIO_PSOP own_cb) +{ +#if CFG_WMT_PS_SUPPORT + sdio_own_ctrl = own_cb; +#endif +} + +UINT32 wmt_lib_wait_event_checker(P_OSAL_THREAD pThread) +{ + P_DEV_WMT pDevWmt; + + if (pThread) { + pDevWmt = (P_DEV_WMT) (pThread->pThreadData); + return !RB_EMPTY(&pDevWmt->rActiveOpQ); + } + WMT_ERR_FUNC("pThread(NULL)\n"); + return 0; +} + +static INT32 wmtd_thread(void *pvData) +{ + P_DEV_WMT pWmtDev = (P_DEV_WMT) pvData; + P_OSAL_EVENT pEvent = NULL; + P_OSAL_OP pOp; + INT32 iResult; + + if (NULL == pWmtDev) { + WMT_ERR_FUNC("pWmtDev(NULL)\n"); + return -1; + } + WMT_INFO_FUNC("wmtd thread starts\n"); + + pEvent = &(pWmtDev->rWmtdWq); + + for (;;) { + pOp = NULL; + pEvent->timeoutValue = 0; +/* osal_thread_wait_for_event(&pWmtDev->thread, pEvent);*/ + osal_thread_wait_for_event(&pWmtDev->thread, pEvent, wmt_lib_wait_event_checker); + + if (osal_thread_should_stop(&pWmtDev->thread)) { + WMT_INFO_FUNC("wmtd thread should stop now...\n"); + /* TODO: clean up active opQ */ + break; + } + + /* get Op from activeQ */ + pOp = wmt_lib_get_op(&pWmtDev->rActiveOpQ); + if (!pOp) { + WMT_WARN_FUNC("get_lxop activeQ fail\n"); + continue; + } +#if 0 /* wmt_core_opid_handler will do sanity check on opId, so no usage here */ + id = lxop_get_opid(pLxOp); + if (id >= WMT_OPID_MAX) { + WMT_WARN_FUNC("abnormal opid id: 0x%x\n", id); + iResult = -1; + goto handlerDone; + } +#endif + + if (osal_test_bit(WMT_STAT_RST_ON, &pWmtDev->state)) { + /* when whole chip reset, only HW RST and SW RST cmd can execute */ + if ((pOp->op.opId == WMT_OPID_HW_RST) || (pOp->op.opId == WMT_OPID_SW_RST) + || (pOp->op.opId == WMT_OPID_GPIO_STATE)) { + iResult = wmt_core_opid(&pOp->op); + } else { + iResult = -2; + WMT_WARN_FUNC("Whole chip resetting, opid (%d) failed, iRet(%d)\n", pOp->op.opId, + iResult); + } + } else { + wmt_lib_set_current_op(pWmtDev, pOp); + iResult = wmt_core_opid(&pOp->op); + wmt_lib_set_current_op(pWmtDev, NULL); + } + + if (iResult) + WMT_WARN_FUNC("opid (%d) failed, iRet(%d)\n", pOp->op.opId, iResult); + + if (osal_op_is_wait_for_signal(pOp)) { + osal_op_raise_signal(pOp, iResult); + } else { + /* put Op back to freeQ */ + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } + + if (WMT_OPID_EXIT == pOp->op.opId) { + WMT_INFO_FUNC("wmtd thread received exit signal\n"); + break; + } + } + + WMT_INFO_FUNC("wmtd thread exits succeed\n"); + + return 0; +}; + +static MTK_WCN_BOOL wmt_lib_put_op(P_OSAL_OP_Q pOpQ, P_OSAL_OP pOp) +{ + INT32 iRet; + + if (!pOpQ || !pOp) { + WMT_WARN_FUNC("invalid input param: pOpQ(0x%p), pLxOp(0x%p)\n", pOpQ, pOp); + osal_assert(pOpQ); + osal_assert(pOp); + return MTK_WCN_BOOL_FALSE; + } + + iRet = osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + WMT_WARN_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); + return MTK_WCN_BOOL_FALSE; + } +#if 0 + if (pOpQ == &gDevWmt.rFreeOpQ) + WMT_INFO_FUNC("current wmt free queue count is(%d),opid(%d)\n", RB_COUNT(pOpQ), pOp->op.opId); +#endif + /* acquire lock success */ + if (!RB_FULL(pOpQ)) + RB_PUT(pOpQ, pOp); + else + iRet = -1; + + osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (iRet) { + WMT_WARN_FUNC("RB_FULL(0x%p)\n", pOpQ); + return MTK_WCN_BOOL_FALSE; + } else { + return MTK_WCN_BOOL_TRUE; + } +} + +static P_OSAL_OP wmt_lib_get_op(P_OSAL_OP_Q pOpQ) +{ + P_OSAL_OP pOp; + INT32 iRet; + + if (NULL == pOpQ) { + WMT_ERR_FUNC("pOpQ = NULL\n"); + osal_assert(pOpQ); + return NULL; + } + + iRet = osal_lock_sleepable_lock(&pOpQ->sLock); + if (iRet) { + WMT_ERR_FUNC("osal_lock_sleepable_lock iRet(%d)\n", iRet); + return NULL; + } + + /* acquire lock success */ + RB_GET(pOpQ, pOp); + osal_unlock_sleepable_lock(&pOpQ->sLock); + + if (NULL == pOp) { + WMT_WARN_FUNC("RB_GET return NULL\n"); + osal_assert(pOp); + } + + return pOp; +} + +INT32 wmt_lib_put_op_to_free_queue(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + if (MTK_WCN_BOOL_FALSE == wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp)) + return -1; + else + return 0; +} + +P_OSAL_OP wmt_lib_get_free_op(VOID) +{ + P_OSAL_OP pOp = NULL; + P_DEV_WMT pDevWmt = &gDevWmt; + + osal_assert(pDevWmt); + + pOp = wmt_lib_get_op(&pDevWmt->rFreeOpQ); + if (pOp) + osal_memset(&pOp->op, 0, osal_sizeof(pOp->op)); + return pOp; +} + +MTK_WCN_BOOL wmt_lib_put_act_op(P_OSAL_OP pOp) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + MTK_WCN_BOOL bCleanup = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal = NULL; + long waitRet = -1; + P_OSAL_THREAD pThread; + + osal_assert(pWmtDev); + osal_assert(pOp); + + do { + if (!pWmtDev || !pOp) { + WMT_ERR_FUNC("pWmtDev(0x%p), pOp(0x%p)\n", pWmtDev, pOp); + break; + } + if ((0 != mtk_wcn_stp_coredump_start_get()) && + (WMT_OPID_HW_RST != pOp->op.opId) && + (WMT_OPID_SW_RST != pOp->op.opId) && (WMT_OPID_GPIO_STATE != pOp->op.opId)) { + bCleanup = MTK_WCN_BOOL_TRUE; + WMT_WARN_FUNC("block tx flag is set\n"); + break; + } + pSignal = &pOp->signal; +/* pOp->u4WaitMs = u4WaitMs; */ + if (pSignal->timeoutValue) { + pOp->result = -9; + osal_signal_init(pSignal); + } + + /* put to active Q */ + bRet = wmt_lib_put_op(&pWmtDev->rActiveOpQ, pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("put to active queue fail\n"); + bCleanup = MTK_WCN_BOOL_TRUE; + break; + } + + /* wake up wmtd */ + /* wake_up_interruptible(&pWmtDev->rWmtdWq); */ + osal_trigger_event(&pWmtDev->rWmtdWq); + + if (0 == pSignal->timeoutValue) { + bRet = MTK_WCN_BOOL_TRUE; + /* clean it in wmtd */ + break; + } + /* wait result, clean it here */ + bCleanup = MTK_WCN_BOOL_TRUE; + + /* check result */ + /* wait_ret = wait_for_completion_interruptible_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); */ + /* wait_ret = wait_for_completion_timeout(&pOp->comp, msecs_to_jiffies(u4WaitMs)); */ + waitRet = osal_wait_for_signal_timeout(pSignal); + WMT_DBG_FUNC("osal_wait_for_signal_timeout:%ld\n", waitRet); + + /* if (unlikely(!wait_ret)) { */ + if (0 == waitRet) { + pThread = &gDevWmt.thread; + WMT_ERR_FUNC + ("wait completion timeout, opId(%d), show wmtd_thread stack!\n", pOp->op.opId); + /* TODO: how to handle it? retry? */ + wcn_wmtd_timeout_collect_ftrace(); /* trigger collect SYS_FTRACE */ + osal_thread_show_stack(pThread); + } else { + if (pOp->result) + WMT_WARN_FUNC("opId(%d) result:%d\n", pOp->op.opId, pOp->result); + } + /* op completes, check result */ + bRet = (pOp->result) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; + } while (0); + + if (bCleanup) { + /* put Op back to freeQ */ + wmt_lib_put_op(&pWmtDev->rFreeOpQ, pOp); + } + + return bRet; +} + +/* TODO:[ChangeFeature][George] is this function obsoleted? */ +#if 0 +INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) +{ + P_WMT_LXOP lxop; + MTK_WCN_BOOL bRet; + PUINT32 plv = NULL; + UINT32 pbuf[2]; + P_OSAL_EVENT pSignal = NULL; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue\n"); + return -1; + } + lxop = wmt_lib_get_free_lxop(); + if (!lxop) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + + return -1; + } + + plv = (PUINT32) (((UINT32) pbuf + 0x3) & ~0x3UL); + *plv = *pvalue; + pSignal = &lxop->signal; + WMT_DBG_FUNC("OPID_REG_RW isWrite(%d) offset(0x%x) value(0x%x) mask(0x%x)\n", isWrite, offset, *pvalue, mask); + + lxop->op.opId = WMT_OPID_REG_RW; + lxop->op.au4OpData[0] = isWrite; + lxop->op.au4OpData[1] = offset; + lxop->op.au4OpData[2] = (UINT32) plv; + lxop->op.au4OpData[3] = mask; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + DISABLE_PSM_MONITOR(); + bRet = wmt_lib_put_act_lxop(lxop); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, *plv, mask); + if (!isWrite) + *pvalue = *plv; + } else { + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, *plv, mask, bRet); + } + + return bRet; +} +#endif + +/* TODO:[ChangeFeature][George] is this function obsoleted? */ +#if 0 +static VOID wmt_lib_clear_chip_id(VOID) +{ +/* + gDevWmt.pChipInfo = NULL; +*/ + gDevWmt.hw_ver = WMTHWVER_INVALID; +} +#endif + +/* TODO: [FixMe][GeorgeKuo]: change this API to report real chip id, hw_ver, and */ +/* fw_ver instead of WMT-translated WMTHWVER */ +ENUM_WMTHWVER_TYPE_T wmt_lib_get_hwver(VOID) +{ +/* + P_WMT_CMB_CHIP_INFO_S pChipInfo = NULL; + P_DEV_WMT pWmtDev = gpDevWmt; + pChipInfo = wmt_lib_get_chip_info(pWmtDev); + return pChipInfo != NULL ? pChipInfo->eHwVersion : WMTHWVER_INVALID; + */ + return gDevWmt.eWmtHwVer; +} + +UINT32 wmt_lib_get_icinfo(ENUM_WMT_CHIPINFO_TYPE_T index) +{ + if (WMTCHIN_CHIPID == index) + return gDevWmt.chip_id; + else if (WMTCHIN_HWVER == index) + return gDevWmt.hw_ver; + else if (WMTCHIN_MAPPINGHWVER == index) + return gDevWmt.eWmtHwVer; + else if (WMTCHIN_FWVER == index) + return gDevWmt.fw_ver; + + return 0; + +} + +PUINT8 wmt_lib_def_patch_name(VOID) +{ + WMT_INFO_FUNC("wmt-lib: use default patch name (%s)\n", gDevWmt.cPatchName); + return gDevWmt.cPatchName; +} + +MTK_WCN_BOOL wmt_lib_is_therm_ctrl_support(VOID) +{ + MTK_WCN_BOOL bIsSupportTherm = MTK_WCN_BOOL_TRUE; + /* TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file */ + if (((0x6620 == gDevWmt.chip_id) && (WMTHWVER_E3 > gDevWmt.eWmtHwVer)) + || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer)) { + WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); + bIsSupportTherm = MTK_WCN_BOOL_FALSE; + } + if (!mtk_wcn_stp_is_ready()) { + WMT_ERR_FUNC("thermal command can not be send: STP is not ready\n"); + bIsSupportTherm = MTK_WCN_BOOL_FALSE; + } + + return bIsSupportTherm; +} + +MTK_WCN_BOOL wmt_lib_is_dsns_ctrl_support(VOID) +{ + /* TODO:[FixMe][GeorgeKuo]: move IC-dependent checking to ic-implementation file */ + if (((0x6620 == gDevWmt.chip_id) && (WMTHWVER_E3 > gDevWmt.eWmtHwVer)) + || (WMTHWVER_INVALID == gDevWmt.eWmtHwVer)) { + WMT_ERR_FUNC("thermal command fail: chip version(WMTHWVER_TYPE:%d) is not valid\n", gDevWmt.eWmtHwVer); + return MTK_WCN_BOOL_FALSE; + } + + return MTK_WCN_BOOL_TRUE; +} + +/*! + * \brief Update combo chip pin settings (GPIO) + * + * An internal library function to support various settings for chip GPIO. It is + * updated in a grouping way: configure all required pins in a single call. + * + * \param id desired pin ID to be controlled + * \param stat desired pin states to be set + * \param flag supplementary options for this operation + * + * \retval 0 operation success + * \retval -1 invalid id + * \retval -2 invalid stat + * \retval < 0 error for operation fail + */ +static INT32 wmt_lib_pin_ctrl(WMT_IC_PIN_ID id, WMT_IC_PIN_STATE stat, UINT32 flag) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /* input sanity check */ + if (WMT_IC_PIN_MAX <= id) { + WMT_ERR_FUNC("invalid ic pin id(%d)\n", id); + return -1; + } + if (WMT_IC_PIN_STATE_MAX <= stat) { + WMT_ERR_FUNC("invalid ic pin state (%d)\n", stat); + return -2; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_GPIO_CTRL (ic pin id:%d, stat:%d, flag:0x%x)\n", id, stat, flag); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_GPIO_CTRL; + pOp->op.au4OpData[0] = id; + pOp->op.au4OpData[1] = stat; + pOp->op.au4OpData[2] = flag; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) + WMT_WARN_FUNC("PIN_ID(%d) PIN_STATE(%d) flag(%d) fail\n", id, stat, flag); + else + WMT_DBG_FUNC("OPID(%d) type(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return 0; +} + +INT32 wmt_lib_reg_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 value; + P_OSAL_SIGNAL pSignal; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue\n"); + return -1; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + value = *pvalue; + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_REG_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (SIZE_T)&value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) + *pvalue = value; + + return 0; + } + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + return -1; +} + +INT32 wmt_lib_efuse_rw(UINT32 isWrite, UINT32 offset, PUINT32 pvalue, UINT32 mask) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 value; + P_OSAL_SIGNAL pSignal; + + if (!pvalue) { + WMT_WARN_FUNC("!pvalue\n"); + return -1; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return -1; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + value = *pvalue; + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x)\n\n", + isWrite, offset, *pvalue, mask); + pOp->op.opId = WMT_OPID_EFUSE_RW; + pOp->op.au4OpData[0] = isWrite; + pOp->op.au4OpData[1] = offset; + pOp->op.au4OpData[2] = (SIZE_T)&value; + pOp->op.au4OpData[3] = mask; + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE != bRet) { + WMT_DBG_FUNC("OPID_EFUSE_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) ok\n", + isWrite, offset, value, mask); + if (!isWrite) + *pvalue = value; + + return 0; + } + WMT_WARN_FUNC("OPID_REG_RW isWrite(%u) offset(0x%x) value(0x%x) mask(0x%x) bRet(%d)\n", + isWrite, offset, value, mask, bRet); + return -1; + +} + +/*! + * \brief update combo chip AUDIO Interface (AIF) settings + * + * A library function to support updating chip AUDIO pin settings. A group of + * pins is updated as a whole. + * + * \param aif desired audio interface state to use + * \param flag whether audio pin is shared or not + * + * \retval 0 operation success + * \retval -1 invalid aif + * \retval < 0 error for invalid parameters or operation fail + */ +INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share) +{ + if (CMB_STUB_AIF_MAX <= aif) { + WMT_ERR_FUNC("invalid aif (%d)\n", aif); + return -1; + } + WMT_DBG_FUNC("call pin_ctrl for aif:%d, share:%d\n", aif, (MTK_WCN_BOOL_TRUE == share) ? 1 : 0); + /* Translate CMB_STUB_AIF_X into WMT_IC_PIN_STATE by array */ + return wmt_lib_pin_ctrl(WMT_IC_PIN_AUDIO, + cmb_aif2pin_stat[aif], + (MTK_WCN_BOOL_TRUE == share) ? WMT_LIB_AIF_FLAG_SHARE : WMT_LIB_AIF_FLAG_SEPARATE); +} + +INT32 wmt_lib_host_awake_get(VOID) +{ + return wmt_plat_wake_lock_ctrl(WL_OP_GET); +} + +INT32 wmt_lib_host_awake_put(VOID) +{ + return wmt_plat_wake_lock_ctrl(WL_OP_PUT); +} + +MTK_WCN_BOOL wmt_lib_btm_cb(MTKSTP_BTM_WMT_OP_T op) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + if (op == BTM_RST_OP) { + /* high priority, not to enqueue into the queue of wmtd */ + WMT_INFO_FUNC("Invoke whole chip reset from stp_btm!!!\n"); + wmt_lib_cmb_rst(WMTRSTSRC_RESET_STP); + bRet = MTK_WCN_BOOL_TRUE; + } else if (op == BTM_DMP_OP) { + + WMT_WARN_FUNC("TBD!!!\n"); + } else if (op == BTM_GET_AEE_SUPPORT_FLAG) { + bRet = wmt_core_get_aee_dump_flag(); + } + return bRet; +} + +MTK_WCN_BOOL wmt_cdev_rstmsg_snd(ENUM_WMTRSTMSG_TYPE_T msg) +{ + + INT32 i = 0; + P_DEV_WMT pDevWmt = &gDevWmt; + PUINT8 drv_name[] = { + "DRV_TYPE_BT", + "DRV_TYPE_FM", + "DRV_TYPE_GPS", + "DRV_TYPE_WIFI" + }; + + for (i = 0; i <= WMTDRV_TYPE_WIFI; i++) { + /* <1> check if reset callback is registered */ + if (pDevWmt->rFdrvCb.fDrvRst[i]) { + /* <2> send the msg to this subfucntion */ + /*src, dst, msg_type, msg_data, msg_size */ + pDevWmt->rFdrvCb.fDrvRst[i] (WMTDRV_TYPE_WMT, i, WMTMSG_TYPE_RESET, &msg, + sizeof(ENUM_WMTRSTMSG_TYPE_T)); + WMT_INFO_FUNC("type = %s, msg sent\n", drv_name[i]); + } else { + WMT_DBG_FUNC("type = %s, unregistered\n", drv_name[i]); + } + } + + return MTK_WCN_BOOL_TRUE; +} + +VOID wmt_lib_state_init(VOID) +{ + /* UINT32 i = 0; */ + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + + /* Initialize op queue */ + /* RB_INIT(&pDevWmt->rFreeOpQ, WMT_OP_BUF_SIZE); */ + /* RB_INIT(&pDevWmt->rActiveOpQ, WMT_OP_BUF_SIZE); */ + + while (!RB_EMPTY(&pDevWmt->rActiveOpQ)) { +#if 0 + osal_signal_init(&(pOp->signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); +#endif + pOp = wmt_lib_get_op(&pDevWmt->rActiveOpQ); + if (pOp) { + if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, -1); + else + wmt_lib_put_op(&pDevWmt->rFreeOpQ, pOp); + } + } + + /* Put all to free Q */ + /* + for (i = 0; i < WMT_OP_BUF_SIZE; i++) { + osal_signal_init(&(pDevWmt->arQue[i].signal)); + wmt_lib_put_op(&pDevWmt->rFreeOpQ, &(pDevWmt->arQue[i])); + } */ +} + +#if 0 +INT32 wmt_lib_sdio_ctrl(UINT32 on) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_SDIO_CTRL\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_SDIO_CTRL; + pOp->op.au4OpData[0] = on; + pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_SDIO_CTRL failed\n"); + return -1; + } + WMT_DBG_FUNC("OPID(WMT_OPID_SDIO_CTRL)ok\n"); + + return 0; +} +#endif + +MTK_WCN_BOOL wmt_lib_hw_state_show(VOID) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_HW_STATE_SHOW\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_GPIO_STATE; + pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_HW_STATE_SHOW failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_HW_STATE_SHOW)ok\n"); + return MTK_WCN_BOOL_TRUE; +} + +MTK_WCN_BOOL wmt_lib_hw_rst(VOID) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + P_DEV_WMT pDevWmt = &gDevWmt; + + wmt_lib_state_init(); + + osal_clear_bit(WMT_STAT_STP_REG, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_OPEN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_EN, &pDevWmt->state); + osal_clear_bit(WMT_STAT_STP_RDY, &pDevWmt->state); + osal_clear_bit(WMT_STAT_RX, &pDevWmt->state); + osal_clear_bit(WMT_STAT_CMD, &pDevWmt->state); + + /*Before do hardware reset, we show GPIO state to check if others modified our pin state accidentially */ + wmt_lib_hw_state_show(); + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_HW_RST\n"); + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_HW_RST; + pSignal->timeoutValue = MAX_GPIO_CTRL_TIME; + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_HW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_HW_RST)ok\n"); + return MTK_WCN_BOOL_TRUE; +} + +MTK_WCN_BOOL wmt_lib_sw_rst(INT32 baudRst) +{ + + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /* <1> wmt state reset */ + wmt_lib_state_init(); + + /* <2> Reset STP data structure */ + WMT_DBG_FUNC("Cleanup STP context\n"); + mtk_wcn_stp_flush_context(); + /* <3> Reset STP-PSM data structure */ + WMT_DBG_FUNC("Cleanup STP-PSM context\n"); + mtk_wcn_stp_psm_reset(); + + /* <4> do sw reset in wmt-core */ + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + WMT_DBG_FUNC("call WMT_OPID_SW_RST\n"); + + pSignal = &pOp->signal; + pSignal->timeoutValue = MAX_FUNC_ON_TIME; + + pOp->op.opId = WMT_OPID_SW_RST; + pOp->op.au4OpData[0] = baudRst; + + bRet = wmt_lib_put_act_op(pOp); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("WMT_OPID_SW_RST failed\n"); + return MTK_WCN_BOOL_FALSE; + } + WMT_DBG_FUNC("OPID(WMT_OPID_SW_RST)ok\n"); + return MTK_WCN_BOOL_TRUE; +} + +ENUM_WMTRSTRET_TYPE_T wmt_lib_cmb_rst(ENUM_WMTRSTSRC_TYPE_T src) +{ +#define RETRYTIMES 10 + MTK_WCN_BOOL bRet; + ENUM_WMTRSTRET_TYPE_T retval = WMTRSTRET_MAX; + ENUM_WMTRSTMSG_TYPE_T rstMsg = WMTRSTMSG_RESET_MAX; + INT32 retries = RETRYTIMES; + P_DEV_WMT pDevWmt = &gDevWmt; + P_OSAL_OP pOp; + PUINT8 srcName[] = { "WMTRSTSRC_RESET_BT", + "WMTRSTSRC_RESET_FM", + "WMTRSTSRC_RESET_GPS", + "WMTRSTSRC_RESET_WIFI", + "WMTRSTSRC_RESET_STP", + "WMTRSTSRC_RESET_TEST" + }; + + if (src < WMTRSTSRC_RESET_MAX) + WMT_INFO_FUNC("reset source = %s\n", srcName[src]); + + if (WMTRSTSRC_RESET_TEST == src) { + pOp = wmt_lib_get_current_op(pDevWmt); + if (pOp && ((WMT_OPID_FUNC_ON == pOp->op.opId) + || (WMT_OPID_FUNC_OFF == pOp->op.opId))) { + WMT_INFO_FUNC("can't do reset by test src when func on/off\n"); + return -1; + } + } + /* <1> Consider the multi-context combo_rst case. */ + if (osal_test_and_set_bit(WMT_STAT_RST_ON, &pDevWmt->state)) { + retval = WMTRSTRET_ONGOING; + goto rstDone; + } + /* <2> Block all STP request */ + mtk_wcn_stp_enable(0); + + /* <3> RESET_START notification */ + bRet = wmt_cdev_rstmsg_snd(WMTRSTMSG_RESET_START); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); + retval = WMTRSTRET_FAIL; + goto rstDone; + } + /* wakeup blocked opid */ + pOp = wmt_lib_get_current_op(pDevWmt); + if (osal_op_is_wait_for_signal(pOp)) + osal_op_raise_signal(pOp, -1); + + /* wakeup blocked cmd */ + wmt_dev_rx_event_cb(); + + /* <4> retry until reset flow successful */ + while (retries > 0) { + /* <4.1> reset combo hw */ + bRet = wmt_lib_hw_rst(); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_hw_rst!\n"); + retries--; + continue; + } + /* <4.2> reset driver/combo sw */ + bRet = wmt_lib_sw_rst(1); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_sw_rst!\n"); + retries--; + continue; + } + break; + } + + osal_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state); + + if (bRet == MTK_WCN_BOOL_FALSE) { + rstMsg = WMTRSTMSG_RESET_END_FAIL; + WMT_WARN_FUNC("[whole chip reset] fail! retries = %d\n", RETRYTIMES - retries); + } else { + rstMsg = WMTRSTMSG_RESET_END; + WMT_INFO_FUNC("[whole chip reset] ok! retries = %d\n", RETRYTIMES - retries); + } + + /* <5> RESET_END notification */ + bRet = wmt_cdev_rstmsg_snd(rstMsg); + if (bRet == MTK_WCN_BOOL_FALSE) { + WMT_ERR_FUNC("[whole chip reset] fail at wmt_lib_rstmsg_snd!\n"); + retval = WMTRSTRET_FAIL; + } else { + retval = WMTRSTMSG_RESET_END == rstMsg ? WMTRSTRET_SUCCESS : WMTRSTRET_FAIL; + } + mtk_wcn_stp_coredump_start_ctrl(0); + mtk_wcn_stp_set_wmt_evt_err_trg_assert(0); +rstDone: + if (osal_test_and_clear_bit(WMT_STAT_RST_ON, &pDevWmt->state)) + WMT_WARN_FUNC("[whole chip reset] retval = %d\n", retval); + + return retval; +} + +MTK_WCN_BOOL wmt_lib_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) +{ + + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_DEV_WMT pWmtDev = &gDevWmt; + + if (eType >= 0 && eType <= WMTDRV_TYPE_WIFI) { + WMT_DBG_FUNC("reg ok!\n"); + pWmtDev->rFdrvCb.fDrvRst[eType] = pCb; + bRet = MTK_WCN_BOOL_TRUE; + } else { + WMT_WARN_FUNC("reg fail!\n"); + } + + return bRet; +} + +MTK_WCN_BOOL wmt_lib_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) +{ + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_DEV_WMT pWmtDev = &gDevWmt; + + if (eType >= 0 && eType <= WMTDRV_TYPE_WIFI) { + WMT_DBG_FUNC("unreg ok!\n"); + pWmtDev->rFdrvCb.fDrvRst[eType] = NULL; + bRet = MTK_WCN_BOOL_TRUE; + } else { + WMT_WARN_FUNC("unreg fail!\n"); + } + + return bRet; +} + +UINT32 wmt_lib_dbg_level_set(UINT32 level) +{ + gWmtDbgLvl = level > WMT_LOG_LOUD ? WMT_LOG_LOUD : level; + return 0; +} + +INT32 wmt_lib_set_stp_wmt_last_close(UINT32 value) +{ + return mtk_wcn_stp_set_wmt_last_close(value); +} + +INT32 wmt_lib_notify_stp_sleep(void) +{ + INT32 iRet = 0x0; + + iRet = wmt_lib_psm_lock_aquire(); + if (iRet) { + WMT_ERR_FUNC("--->lock psm_lock failed, iRet=%d\n", iRet); + return iRet; + } + + iRet = mtk_wcn_stp_notify_sleep_for_thermal(); + wmt_lib_psm_lock_release(); + + return iRet; +} + +VOID wmt_lib_set_patch_num(UINT32 num) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + pWmtDev->patchNum = num; +} + +VOID wmt_lib_set_patch_info(P_WMT_PATCH_INFO pPatchinfo) +{ + P_DEV_WMT pWmtDev = &gDevWmt; + + if (pPatchinfo) + pWmtDev->pWmtPatchInfo = pPatchinfo; + +} + +INT32 wmt_lib_set_current_op(P_DEV_WMT pWmtDev, P_OSAL_OP pOp) +{ + if (pWmtDev) { + pWmtDev->pCurOP = pOp; + WMT_DBG_FUNC("pOp=0x%p\n", pOp); + return 0; + } + WMT_ERR_FUNC("Invalid pointer\n"); + return -1; +} + +P_OSAL_OP wmt_lib_get_current_op(P_DEV_WMT pWmtDev) +{ + if (pWmtDev) + return pWmtDev->pCurOP; + + WMT_ERR_FUNC("Invalid pointer\n"); + return NULL; +} + +UINT8 *wmt_lib_get_fwinfor_from_emi(UINT8 section, UINT32 offset, UINT8 *buf, UINT32 len) +{ + UINT8 *pAddr = NULL; + UINT32 sublen1 = 0; + UINT32 sublen2 = 0; + P_CONSYS_EMI_ADDR_INFO p_consys_info; + + p_consys_info = wmt_plat_get_emi_phy_add(); + osal_assert(p_consys_info); + + if (section == 0) { + pAddr = wmt_plat_get_emi_virt_add(0x0); + if (len > 1024) + len = 1024; + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); + osal_memcpy(&buf[0], pAddr, len); + } + } else { + if (offset >= 0x7fff) + offset = 0x0; + + if (offset + len > 32768) { + pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get part1 EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("part1 vir addr(0x%p)\n", pAddr); + sublen1 = 0x7fff - offset; + osal_memcpy(&buf[0], pAddr, sublen1); + } + pAddr = wmt_plat_get_emi_virt_add(p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get part2 EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("part2 vir addr(0x%p)\n", pAddr); + sublen2 = len - sublen1; + osal_memcpy(&buf[sublen1], pAddr, sublen2); + } + } else { + pAddr = wmt_plat_get_emi_virt_add(offset + p_consys_info->paged_trace_off); + if (!pAddr) { + WMT_ERR_FUNC("wmt-lib: get EMI virtual base address fail\n"); + } else { + WMT_INFO_FUNC("vir addr(0x%p)\n", pAddr); + osal_memcpy(&buf[0], pAddr, len); + } + } + } + + return 0; +} + +INT32 wmt_lib_poll_cpupcr(UINT32 count, UINT16 sleep, UINT16 toAee) +{ + ENUM_STP_FW_ISSUE_TYPE issue_type; + + issue_type = STP_DBG_PROC_TEST; + + stp_dbg_poll_cpupcr(count, sleep, 1); + + if (toAee) { + stp_dbg_set_fw_info("STP ProcTest", osal_strlen("STP ProcTest"), issue_type); + osal_dbg_assert_aee("[SOC_CONSYS]ProcTest", + "**[WCN_ISSUE_INFO]STP Tx Timeout**\n Polling CPUPCR for FW debug usage\n"); + } else { + WMT_INFO_FUNC("wmt_lib:do not pass cpupcr to AEE\n"); + } + return 0; +} + +UINT8 *wmt_lib_get_cpupcr_xml_format(UINT32 *len) +{ + PUINT8 temp; + UINT32 i = 0; + + osal_memset(&g_cpupcr_buf[0], 0, WMT_STP_CPUPCR_BUF_SIZE); + temp = g_cpupcr_buf; + stp_dbg_cpupcr_infor_format(&temp, len); + + pr_debug("print xml buffer,len(%d):\n\n", *len); + for (i = 0; i < *len; i++) + pr_cont("%c", g_cpupcr_buf[i]); + + return &g_cpupcr_buf[0]; +} + +UINT32 wmt_lib_set_host_assert_info(UINT32 type, UINT32 reason, UINT32 en) +{ + return stp_dbg_set_host_assert_info(type, reason, en); +} + +INT32 wmt_lib_register_thermal_ctrl_cb(thermal_query_ctrl_cb thermal_ctrl) +{ + wmt_plat_thermal_ctrl_cb_reg(thermal_ctrl); + return 0; +} + +INT8 wmt_lib_co_clock_get(void) +{ + if (gDevWmt.rWmtGenConf.cfgExist) + return gDevWmt.rWmtGenConf.co_clock_flag; + else + return -1; +} + +#if CFG_WMT_PS_SUPPORT +UINT32 wmt_lib_quick_sleep_ctrl(UINT32 en) +{ + WMT_WARN_FUNC("%s quick sleep mode\n", en ? "enable" : "disable"); + g_quick_sleep_ctrl = en; + return 0; +} +#endif + +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_lib_jtag_flag_set(UINT32 en) +{ + return wmt_plat_jtag_flag_ctrl(en); +} +#endif + +UINT32 wmt_lib_soc_set_wifiver(UINT32 wifiver) +{ + return stp_dbg_set_wifiver(wifiver); +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h new file mode 100644 index 0000000000000..b1b5285638f96 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/stp_exp.h @@ -0,0 +1,252 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _STP_EXP_H_ +#define _STP_EXP_H_ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_stp_exp.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +#define BT_TASK_INDX (0) +#define FM_TASK_INDX (1) +#define GPS_TASK_INDX (2) +#define WIFI_TASK_INDX (3) +#define WMT_TASK_INDX (4) +#define STP_TASK_INDX (5) +#define INFO_TASK_INDX (6) +#define ANT_TASK_INDX (7) +#if CFG_WMT_LTE_COEX_HANDLING +#define COEX_TASK_INDX (8) +#define MTKSTP_MAX_TASK_NUM (9) +#else +#define MTKSTP_MAX_TASK_NUM (8) +#endif + +#define MTKSTP_BUFFER_SIZE (16384) /* Size of RX Queue */ + +#define STP_EXP_HID_API_EXPORT 0 + +#else + +#define STP_EXP_HID_API_EXPORT 1 + +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +typedef void (*MTK_WCN_STP_EVENT_CB) (void); +typedef INT32 (*MTK_WCN_STP_IF_TX) (const UINT8 *data, const UINT32 size, UINT32 *written_size); +/* export for HIF driver */ +typedef void (*MTK_WCN_STP_IF_RX) (const UINT8 *data, INT32 size); + +typedef enum { + STP_UART_IF_TX = 0, + STP_SDIO_IF_TX = 1, + STP_BTIF_IF_TX = 2, + STP_MAX_IF_TX +} ENUM_STP_TX_IF_TYPE; +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_receive_data +* DESCRIPTION +* receive data from serial protocol engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* INT32 >= 0: size of data received; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_receive_data(UINT8 *buffer, UINT32 length, UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_send_data +* DESCRIPTION +* subfunction send data through STP +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* type [IN] subfunction type +* RETURNS +* INT32 >= 0: length transmitted; < 0: error +*****************************************************************************/ +extern INT32 mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_rxqueue_empty +* DESCRIPTION +* Is certain rx queue empty? +* PARAMETERS +* type [IN] subfunction type +* RETURNS +* INT32 0: queue is NOT empyt; !0: queue is empty +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_rxqueue_empty(UINT8 type); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_is_enable +* DESCRIPTION +* Is STP ready? +* PARAMETERS +* none. +* RETURNS +* MTK_WCN_BOOL TRUE:ready, FALSE:not ready +*****************************************************************************/ +extern MTK_WCN_BOOL mtk_wcn_stp_is_ready(void); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_parser_data +* DESCRIPTION +* push data to serial transport protocol parser engine +* PARAMETERS +* buffer [IN] data buffer +* length [IN] data buffer length +* RETURNS +* void +*****************************************************************************/ +extern int mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length); + +/***************************************************************************** +* FUNCTION +* set_bluetooth_rx_interface +* DESCRIPTION +* Set bluetooth rx interface +* PARAMETERS +* rx interface type +* RETURNS +* void +*****************************************************************************/ +extern void mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_tx_event_cb +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* func +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern int mtk_wcn_stp_register_tx_event_cb(int type, MTK_WCN_STP_EVENT_CB func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_event_cb +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* func +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern int mtk_wcn_stp_register_event_cb(int type, MTK_WCN_STP_EVENT_CB func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_tx +* DESCRIPTION +* regiter Tx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern int mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); + +/***************************************************************************** +* FUNCTION +* mtk_wcn_stp_register_if_rx +* DESCRIPTION +* regiter Rx event callback function +* PARAMETERS +* stp_if: SDIO or UART, fnnc: Call back function +* RETURNS +* int: 0:successful , -1: fail +*****************************************************************************/ +extern int mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#else +extern INT32 _mtk_wcn_stp_receive_data(PUINT8 buffer, UINT32 length, UINT8 type); +extern INT32 _mtk_wcn_stp_send_data_raw(const PUINT8 buffer, const UINT32 length, const UINT8 type); +extern INT32 _mtk_wcn_stp_send_data(const PUINT8 buffer, const UINT32 length, const UINT8 type); +extern MTK_WCN_BOOL _mtk_wcn_stp_is_rxqueue_empty(UINT8 type); +extern MTK_WCN_BOOL _mtk_wcn_stp_is_ready(void); +extern INT32 _mtk_wcn_stp_parser_data(UINT8 *buffer, UINT32 length); +extern void _mtk_wcn_stp_set_bluez(MTK_WCN_BOOL sdio_flag); +extern INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); +extern INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func); +extern INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func); +extern INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func); +extern INT32 _mtk_wcn_stp_coredump_start_get(VOID); + +#endif + +#endif /* _WMT_EXP_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h new file mode 100644 index 0000000000000..6d10c3ff26590 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt.h @@ -0,0 +1,19 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _MTKWMT_H_ +#define _MTKWMT_H_ +#include "wmt_core.h" + +#endif /*_MTKWMT_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h new file mode 100644 index 0000000000000..06238e07879fe --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_exp.h @@ -0,0 +1,329 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_EXP_H_ +#define _WMT_EXP_H_ + +#include +#include "osal.h" +#include "wmt_plat.h" +#include "wmt_stp_exp.h" +/* not to reference to internal wmt */ +/* #include "wmt_core.h" */ +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_LOUD) \ + osal_dbg_print(DFT_TAG "[L]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_INFO_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_INFO) \ + osal_dbg_print(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_WARN_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_WARN) \ + osal_warn_print(DFT_TAG "[W]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_ERR_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_ERR) \ + osal_err_print(DFT_TAG "[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ +} while (0) +#define WMT_DBG_FUNC(fmt, arg...) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_DBG) \ + osal_dbg_print(DFT_TAG "[D]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_TRC_FUNC(f) \ +do { \ + if (gWmtDbgLvl >= WMT_LOG_DBG) \ + osal_dbg_print(DFT_TAG "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +extern UINT32 gWmtDbgLvl; +#endif +extern OSAL_BIT_OP_VAR gBtWifiGpsState; +extern OSAL_BIT_OP_VAR gGpsFmState; +extern UINT32 gWifiProbed; +extern MTK_WCN_BOOL g_pwr_off_flag; +extern UINT32 g_IsNeedDoChipReset; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if 1 /* moved from wmt_lib.h */ +#define WMT_LOG_LOUD 4 +#define WMT_LOG_DBG 3 +#define WMT_LOG_INFO 2 +#define WMT_LOG_WARN 1 +#define WMT_LOG_ERR 0 +#endif +#define CFG_CORE_INTERNAL_TXRX 0 /*just do TX/RX in host side */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_STP = 5, + WMTDRV_TYPE_LPBK = 6, + WMTDRV_TYPE_COREDUMP = 7, + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +/* TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type */ +/* TODO: how do we extend for new chip and newer revision? */ +/* TODO: This way is hard to extend */ +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_E1 = 0x0, + WMTHWVER_E2 = 0x1, + WMTHWVER_E3 = 0x2, + WMTHWVER_E4 = 0x3, + WMTHWVER_E5 = 0x4, + WMTHWVER_E6 = 0x5, + WMTHWVER_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; + +typedef enum _ENUM_WMTDSNS_TYPE_T { + WMTDSNS_FM_DISABLE = 0, + WMTDSNS_FM_ENABLE = 1, + WMTDSNS_FM_GPS_DISABLE = 2, + WMTDSNS_FM_GPS_ENABLE = 3, + WMTDSNS_MAX +} ENUM_WMTDSNS_TYPE_T, *P_ENUM_WMTDSNS_TYPE_T; + +typedef enum _ENUM_WMTTHERM_TYPE_T { + WMTTHERM_ZERO = 0, + WMTTHERM_ENABLE = WMTTHERM_ZERO + 1, + WMTTHERM_READ = WMTTHERM_ENABLE + 1, + WMTTHERM_DISABLE = WMTTHERM_READ + 1, + WMTTHERM_MAX +} ENUM_WMTTHERM_TYPE_T, *P_ENUM_WMTTHERM_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY = 3, + WMTMSG_TYPE_HW_FUNC_ON = 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + +typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + VOID *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client + can't touch this buffer after this function return. */ + UINT32 /* Buffer size in unit of byte */ +); + +typedef enum _SDIO_PS_OP { + OWN_SET = 0, + OWN_CLR = 1, + OWN_STATE = 2, +} SDIO_PS_OP; + +typedef INT32(*PF_WMT_SDIO_PSOP) (SDIO_PS_OP); + +typedef enum _ENUM_WMTCHIN_TYPE_T { + WMTCHIN_CHIPID = 0x0, + WMTCHIN_HWVER = WMTCHIN_CHIPID + 1, + WMTCHIN_MAPPINGHWVER = WMTCHIN_HWVER + 1, + WMTCHIN_FWVER = WMTCHIN_MAPPINGHWVER + 1, + WMTCHIN_MAX, + +} ENUM_WMT_CHIPINFO_TYPE_T, *P_ENUM_WMT_CHIPINFO_TYPE_T; + +#endif + +typedef enum _ENUM_WMTRSTMSG_TYPE_T { + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; + +typedef enum _ENUM_BT_GPS_ONOFF_STATE_T { + WMT_BT_ON = 0, + WMT_GPS_ON = 1, + WMT_WIFI_ON = 2, + WMT_FM_ON = 3, + WMT_BT_GPS_STATE_MAX, + WMT_BT_GPS_STATE_INVALID = 0xff +} ENUM_BT_GPS_ONOFF_STATE_T, *P_ENUM_BT_GPS_ONOFF_STATE_T; + +#if 1 /* moved from wmt_core.h */ +typedef enum { + WMT_SDIO_SLOT_INVALID = 0, + WMT_SDIO_SLOT_SDIO1 = 1, /* Wi-Fi dedicated SDIO1 */ + WMT_SDIO_SLOT_SDIO2 = 2, + WMT_SDIO_SLOT_MAX +} WMT_SDIO_SLOT_NUM; + +typedef enum { + WMT_SDIO_FUNC_STP = 0, + WMT_SDIO_FUNC_WIFI = 1, + WMT_SDIO_FUNC_MAX +} WMT_SDIO_FUNC_TYPE; +#endif + +typedef INT32(*wmt_wlan_probe_cb) (VOID); +typedef INT32(*wmt_wlan_remove_cb) (VOID); +typedef INT32(*wmt_wlan_bus_cnt_get_cb) (VOID); +typedef INT32(*wmt_wlan_bus_cnt_clr_cb) (VOID); + +typedef struct _MTK_WCN_WMT_WLAN_CB_INFO { + wmt_wlan_probe_cb wlan_probe_cb; + wmt_wlan_remove_cb wlan_remove_cb; + wmt_wlan_bus_cnt_get_cb wlan_bus_cnt_get_cb; + wmt_wlan_bus_cnt_clr_cb wlan_bus_cnt_clr_cb; +} MTK_WCN_WMT_WLAN_CB_INFO, *P_MTK_WCN_WMT_WLAN_CB_INFO; + +#ifdef CONFIG_MTK_COMBO_ANT +typedef enum _ENUM_WMT_ANT_RAM_CTRL_T { + WMT_ANT_RAM_GET_STATUS = 0, + WMT_ANT_RAM_DOWNLOAD = WMT_ANT_RAM_GET_STATUS + 1, + WMT_ANT_RAM_CTRL_MAX +} ENUM_WMT_ANT_RAM_CTRL, *P_ENUM_WMT_ANT_RAM_CTRL; + +typedef enum _ENUM_WMT_ANT_RAM_SEQ_T { + WMT_ANT_RAM_START_PKT = 1, + WMT_ANT_RAM_CONTINUE_PKT = WMT_ANT_RAM_START_PKT + 1, + WMT_ANT_RAM_END_PKT = WMT_ANT_RAM_CONTINUE_PKT + 1, + WMT_ANT_RAM_SEQ_MAX +} ENUM_WMT_ANT_RAM_SEQ, *P_ENUM_WMT_ANT_RAM_SEQ; + +typedef enum _ENUM_WMT_ANT_RAM_STATUS_T { + WMT_ANT_RAM_NOT_EXIST = 0, + WMT_ANT_RAM_EXIST = WMT_ANT_RAM_NOT_EXIST + 1, + WMT_ANT_RAM_DOWN_OK = WMT_ANT_RAM_EXIST + 1, + WMT_ANT_RAM_DOWN_FAIL = WMT_ANT_RAM_DOWN_OK + 1, + WMT_ANT_RAM_PARA_ERR = WMT_ANT_RAM_DOWN_FAIL + 1, + WMT_ANT_RAM_OP_ERR = WMT_ANT_RAM_PARA_ERR + 1, + WMT_ANT_RAM_MAX +} ENUM_WMT_ANT_RAM_STATUS, *P_ENUM_WMT_ANT_RAM_STATUS; +#endif + +extern INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo); +extern INT32 mtk_wcn_wmt_wlan_unreg(VOID); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern wmt_wlan_probe_cb mtk_wcn_wlan_probe; +extern wmt_wlan_remove_cb mtk_wcn_wlan_remove; +extern wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt; +extern wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*subsystem function ctrl APIs*/ +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); + +#ifndef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +#define WMT_EXP_HID_API_EXPORT 0 + +extern MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type); + +extern MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type); + +extern MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType); + +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); + +extern INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); + +extern INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); + +extern INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb); + +extern INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID); +/* +return value: +enable/disable thermal sensor function: true(1)/false(0) +read thermal sensor function: thermal value + +*/ +extern INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType); + +extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); + +#else +#define WMT_EXP_HID_API_EXPORT 1 +#endif + +#ifdef CONFIG_MTK_COMBO_ANT +extern ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, + UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq); +#endif +extern INT32 wmt_lib_set_aif(CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); /* set AUDIO interface options */ +extern VOID wmt_lib_ps_irq_cb(VOID); + +extern VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type); + +extern INT32 mtk_wcn_wmt_system_state_reset(VOID); +extern MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value); +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +extern VOID mtk_wcn_wmt_exp_init(VOID); +extern VOID mtk_wcn_wmt_exp_deinit(VOID); +#endif +extern INT8 mtk_wcn_wmt_co_clock_flag_get(VOID); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_EXP_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h new file mode 100644 index 0000000000000..075496cac54f9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/include/wmt_plat.h @@ -0,0 +1,295 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _WMT_PLAT_H_ +#define _WMT_PLAT_H_ +#include "osal_typedef.h" +#include "stp_exp.h" +#include + +/* #include "mtk_wcn_consys_hw.h" */ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if 1 /* moved from wmt_exp.h */ +#ifndef DFT_TAG +#define DFT_TAG "[WMT-DFT]" +#endif + +#define WMT_PLAT_LOG_LOUD 4 +#define WMT_PLAT_LOG_DBG 3 +#define WMT_PLAT_LOG_INFO 2 +#define WMT_PLAT_LOG_WARN 1 +#define WMT_PLAT_LOG_ERR 0 + +extern UINT32 wmtPlatLogLvl; + +#define WMT_PLAT_LOUD_FUNC(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_LOUD) \ + pr_debug(DFT_TAG "[L]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_PLAT_INFO_FUNC(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_INFO) \ + pr_debug(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_PLAT_WARN_FUNC(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_WARN) \ + pr_warn(DFT_TAG "[W]%s:" fmt, __func__ , ##arg); \ +} while (0) +#define WMT_PLAT_ERR_FUNC(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_ERR) \ + pr_err(DFT_TAG "[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \ +} while (0) +#define WMT_PLAT_DBG_FUNC(fmt, arg...) \ +do { \ + if (wmtPlatLogLvl >= WMT_PLAT_LOG_DBG) \ + pr_debug(DFT_TAG "[D]%s:" fmt, __func__ , ##arg); \ +} while (0) + +#endif + +#define CFG_WMT_PS_SUPPORT 1 /* moved from wmt_exp.h */ + +#define CFG_WMT_DUMP_INT_STATUS 0 +#define CONSYS_ENALBE_SET_JTAG 1 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_FUNC_STATE_ { + FUNC_ON = 0, + FUNC_OFF = 1, + FUNC_RST = 2, + FUNC_STAT = 3, + FUNC_CTRL_MAX, +} ENUM_FUNC_STATE, *P_ENUM_FUNC_STATE; + +typedef enum _ENUM_PIN_ID_ { + PIN_BGF_EINT = 0, + PIN_I2S_GRP = 1, + PIN_GPS_SYNC = 2, + PIN_GPS_LNA = 3, +#if CFG_WMT_LTE_COEX_HANDLING + PIN_TDM_REQ = 4, +#endif + PIN_ID_MAX +} ENUM_PIN_ID, *P_ENUM_PIN_ID; + +typedef enum _ENUM_PIN_STATE_ { + PIN_STA_INIT = 0, + PIN_STA_OUT_L = 1, + PIN_STA_OUT_H = 2, + PIN_STA_IN_L = 3, + PIN_STA_MUX = 4, + PIN_STA_EINT_EN = 5, + PIN_STA_EINT_DIS = 6, + PIN_STA_DEINIT = 7, + PIN_STA_SHOW = 8, + PIN_STA_MAX +} ENUM_PIN_STATE, *P_ENUM_PIN_STATE; + +typedef enum _CMB_IF_TYPE_ { + CMB_IF_UART = 0, + CMB_IF_WIFI_SDIO = 1, + CMB_IF_BGF_SDIO = 2, + CMB_IF_BGWF_SDIO = 3, + CMB_IF_TYPE_MAX +} CMB_IF_TYPE, *P_CMB_IF_TYPE; + +typedef INT32(*fp_set_pin) (ENUM_PIN_STATE); + +typedef enum _ENUM_WL_OP_ { + WL_OP_GET = 0, + WL_OP_PUT = 1, + WL_OP_MAX +} ENUM_WL_OP, *P_ENUM_WL_OP; + +typedef enum _ENUM_PALDO_TYPE_ { + BT_PALDO = 0, + WIFI_PALDO = 1, + FM_PALDO = 2, + GPS_PALDO = 3, + PMIC_CHIPID_PALDO = 4, + WIFI_5G_PALDO = 5, + PALDO_TYPE_MAX +} ENUM_PALDO_TYPE, *P_ENUM_PALDO_TYPE; + +typedef enum _ENUM_PALDO_OP_ { + PALDO_OFF = 0, + PALDO_ON = 1, + PALDO_OP_MAX +} ENUM_PALDO_OP, *P_ENUM_PALDO_OP; + +typedef enum _ENUM_HOST_DUMP_STATE_T { + STP_HOST_DUMP_NOT_START = 0, + STP_HOST_DUMP_GET = 1, + STP_HOST_DUMP_GET_DONE = 2, + STP_HOST_DUMP_END = 3, + STP_HOST_DUMP_MAX +} ENUM_HOST_DUMP_STATE, *P_ENUM_HOST_DUMP_STATE_T; + +typedef enum _ENUM_FORCE_TRG_ASSERT_T { + STP_FORCE_TRG_ASSERT_EMI = 0, + STP_FORCE_TRG_ASSERT_DEBUG_PIN = 1, + STP_FORCE_TRG_ASSERT_MAX = 2 +} ENUM_FORCE_TRG_ASSERT_T, *P_ENUM_FORCE_TRG_ASSERT_T; + +typedef enum _ENUM_CHIP_DUMP_STATE_T { + STP_CHIP_DUMP_NOT_START = 0, + STP_CHIP_DUMP_PUT = 1, + STP_CHIP_DUMP_PUT_DONE = 2, + STP_CHIP_DUMP_END = 3, + STP_CHIP_DUMP_MAX +} ENUM_CHIP_DUMP_STATE, *P_ENUM_CHIP_DUMP_STATE_T; + +typedef struct _EMI_CTRL_STATE_OFFSET_ { + UINT32 emi_apmem_ctrl_state; + UINT32 emi_apmem_ctrl_host_sync_state; + UINT32 emi_apmem_ctrl_host_sync_num; + UINT32 emi_apmem_ctrl_chip_sync_state; + UINT32 emi_apmem_ctrl_chip_sync_num; + UINT32 emi_apmem_ctrl_chip_sync_addr; + UINT32 emi_apmem_ctrl_chip_sync_len; + UINT32 emi_apmem_ctrl_chip_print_buff_start; + UINT32 emi_apmem_ctrl_chip_print_buff_len; + UINT32 emi_apmem_ctrl_chip_print_buff_idx; + UINT32 emi_apmem_ctrl_chip_int_status; + UINT32 emi_apmem_ctrl_chip_paded_dump_end; + UINT32 emi_apmem_ctrl_host_outband_assert_w1; + UINT32 emi_apmem_ctrl_chip_page_dump_num; +} EMI_CTRL_STATE_OFFSET, *P_EMI_CTRL_STATE_OFFSET; + +typedef struct _BGF_IRQ_BALANCE_ { + UINT32 counter; + unsigned long flags; + spinlock_t lock; +} BGF_IRQ_BALANCE, *P_BGF_IRQ_BALANCE; + +typedef struct _CONSYS_EMI_ADDR_INFO_ { + UINT32 emi_phy_addr; + UINT32 paged_trace_off; + UINT32 paged_dump_off; + UINT32 full_dump_off; + P_EMI_CTRL_STATE_OFFSET p_ecso; +} CONSYS_EMI_ADDR_INFO, *P_CONSYS_EMI_ADDR_INFO; + +typedef struct _GPIO_TDM_REQ_INFO_ { + UINT32 ant_sel_index; + UINT32 gpio_number; + UINT32 cr_address; +} GPIO_TDM_REQ_INFO, *P_GPIO_TDM_REQ_INFO; + +typedef VOID(*irq_cb) (VOID); +typedef INT32(*device_audio_if_cb) (CMB_STUB_AIF_X aif, MTK_WCN_BOOL share); +typedef VOID(*func_ctrl_cb) (UINT32 on, UINT32 type); +typedef long (*thermal_query_ctrl_cb) (VOID); +typedef INT32(*deep_idle_ctrl_cb) (UINT32); + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern UINT32 gWmtDbgLvl; +extern struct device *wmt_dev; +#ifdef CFG_WMT_READ_EFUSE_VCN33 +extern INT32 wmt_set_pmic_voltage(UINT32 level); +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +INT32 wmt_plat_init(UINT32 co_clock_type); + +INT32 wmt_plat_deinit(VOID); + +INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state); + +INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); + +INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state); + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId); + +INT32 wmt_plat_audio_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); + +VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb); +VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb); +VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl); +VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl); +VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl); + +INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo); +UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset); +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en); +#endif +#if CFG_WMT_DUMP_INT_STATUS +VOID wmt_plat_BGF_irq_dump_status(VOID); +MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID); +#endif +P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID); +UINT32 wmt_plat_read_cpupcr(VOID); +UINT32 wmt_plat_read_dmaregs(UINT32); +INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state); +UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type); +INT32 wmt_plat_update_host_sync_num(VOID); +INT32 wmt_plat_get_dump_info(UINT32 offset); +UINT32 wmt_plat_get_soc_chipid(VOID); +INT32 wmt_plat_set_dbg_mode(UINT32 flag); +VOID wmt_plat_set_dynamic_dumpmem(UINT32 *buf); +#if CFG_WMT_LTE_COEX_HANDLING +INT32 wmt_plat_get_tdm_antsel_index(VOID); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WMT_PLAT_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile new file mode 100644 index 0000000000000..9052071189386 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/Makefile @@ -0,0 +1,6 @@ +ifeq ($(CONFIG_MTK_COMBO), y) + +obj-y += pub/ +obj-y += pri/ + +endif \ No newline at end of file diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h new file mode 100644 index 0000000000000..95d1ab02a9fa4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/bgw_desense.h @@ -0,0 +1,74 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef __BGW_DESENSE_H_ +#define __BGW_DESENSE_H_ + +#ifdef MSG +#undef MSG +#endif + +#ifdef ERR +#undef ERR +#endif + +#define PFX1 "[BWG] " +#define MSG(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__ , ##arg) +#define ERR(fmt, arg ...) pr_debug(PFX1 "[D]%s: " fmt, __func__ , ##arg) + +#ifdef NETLINK_TEST +#undef NETLINK_TEST +#endif + +#define NETLINK_TEST 17 + +#ifdef MAX_NL_MSG_LEN +#undef MAX_NL_MSG_LEN +#endif + +#define MAX_NL_MSG_LEN 1024 + + +#ifdef ON +#undef ON +#endif +#ifdef OFF +#undef OFF +#endif +#ifdef ACK +#undef ACK +#endif + +#define ON 1 +#define OFF 0 +#define ACK 2 + +/* +used send command to native process + +parameter: command could be macro ON: enable co-exist; OFF: disable co-exist; +ACK: after get native process init message send ACK + +*/ +extern void send_command_to_daemon(const int command); + +/* +before use kernel socket, please call init socket first +return value: 0: ok; -1: fail +*/ +extern int bgw_init_socket(void); + +extern void bgw_destroy_netlink_kernel(void); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h new file mode 100644 index 0000000000000..cf3e830003ac8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal.h @@ -0,0 +1,349 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _OSAL_H_ +#define _OSAL_H_ + +#include +#include +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define OS_BIT_OPS_SUPPORT 1 + +#define _osal_inline_ inline + +#define MAX_THREAD_NAME_LEN 16 +#define MAX_WAKE_LOCK_NAME_LEN 16 +#define OSAL_OP_BUF_SIZE 64 + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MT_ENG_BUILD)) +#define OSAL_OP_DATA_SIZE 8 +#else +#define OSAL_OP_DATA_SIZE 32 +#endif + +#define DBG_LOG_STR_SIZE 256 + +#define osal_sizeof(x) sizeof(x) + +#define osal_array_size(x) (sizeof(x)/sizeof(x[0])) + +#ifndef NAME_MAX +#define NAME_MAX 256 +#endif + +#define WMT_OP_BIT(x) (0x1UL << x) +#define WMT_OP_HIF_BIT WMT_OP_BIT(0) + +#define RB_SIZE(prb) ((prb)->size) +#define RB_MASK(prb) (RB_SIZE(prb) - 1) +#define RB_COUNT(prb) ((prb)->write - (prb)->read) +#define RB_FULL(prb) (RB_COUNT(prb) >= RB_SIZE(prb)) +#define RB_EMPTY(prb) ((prb)->write == (prb)->read) + +#define RB_INIT(prb, qsize) \ +do { \ + (prb)->read = (prb)->write = 0; \ + (prb)->size = (qsize); \ +} while (0) + +#define RB_PUT(prb, value) \ +do { \ + if (!RB_FULL(prb)) { \ + (prb)->queue[(prb)->write & RB_MASK(prb)] = value; \ + ++((prb)->write); \ + } \ + else { \ + osal_assert(!RB_FULL(prb)); \ + } \ +} while (0) + +#define RB_GET(prb, value) \ +do { \ + if (!RB_EMPTY(prb)) { \ + value = (prb)->queue[(prb)->read & RB_MASK(prb)]; \ + ++((prb)->read); \ + if (RB_EMPTY(prb)) { \ + (prb)->read = (prb)->write = 0; \ + } \ + } \ + else { \ + value = NULL; \ + osal_assert(!RB_EMPTY(prb)); \ + } \ +} while (0) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +//typedef VOID(*P_TIMEOUT_HANDLER) (unsigned long); +typedef VOID(*P_TIMEOUT_HANDLER) (struct timer_list *t); +typedef INT32(*P_COND) (VOID *); + +typedef struct _OSAL_TIMER_ { + struct timer_list timer; + P_TIMEOUT_HANDLER timeoutHandler; + unsigned long timeroutHandlerData; +} OSAL_TIMER, *P_OSAL_TIMER; + +typedef struct _OSAL_UNSLEEPABLE_LOCK_ { + spinlock_t lock; + unsigned long flag; +} OSAL_UNSLEEPABLE_LOCK, *P_OSAL_UNSLEEPABLE_LOCK; + +typedef struct _OSAL_SLEEPABLE_LOCK_ { + struct mutex lock; +} OSAL_SLEEPABLE_LOCK, *P_OSAL_SLEEPABLE_LOCK; + +typedef struct _OSAL_SIGNAL_ { + struct completion comp; + UINT32 timeoutValue; +} OSAL_SIGNAL, *P_OSAL_SIGNAL; + +typedef struct _OSAL_EVENT_ { + wait_queue_head_t waitQueue; +/* VOID *pWaitQueueData; */ + UINT32 timeoutValue; + INT32 waitFlag; + +} OSAL_EVENT, *P_OSAL_EVENT; + +typedef struct _OSAL_THREAD_ { + struct task_struct *pThread; + VOID *pThreadFunc; + VOID *pThreadData; + char threadName[MAX_THREAD_NAME_LEN]; +} OSAL_THREAD, *P_OSAL_THREAD; + +typedef struct _OSAL_FIFO_ { + /*fifo definition */ + VOID *pFifoBody; + spinlock_t fifoSpinlock; + /*fifo operations */ + INT32 (*FifoInit)(struct _OSAL_FIFO_ *pFifo, UINT8 *buf, UINT32); + INT32 (*FifoDeInit)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoReset)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoSz)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoAvailSz)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoLen)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoIsEmpty)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoIsFull)(struct _OSAL_FIFO_ *pFifo); + INT32 (*FifoDataIn)(struct _OSAL_FIFO_ *pFifo, const VOID *buf, UINT32 len); + INT32 (*FifoDataOut)(struct _OSAL_FIFO_ *pFifo, void *buf, UINT32 len); +} OSAL_FIFO, *P_OSAL_FIFO; + +typedef struct firmware osal_firmware; + +typedef struct _OSAL_OP_DAT { + UINT32 opId; /* Event ID */ + UINT32 u4InfoBit; /* Reserved */ + SIZE_T au4OpData[OSAL_OP_DATA_SIZE]; /* OP Data */ +} OSAL_OP_DAT, *P_OSAL_OP_DAT; + +typedef struct _OSAL_LXOP_ { + OSAL_OP_DAT op; + OSAL_SIGNAL signal; + INT32 result; +} OSAL_OP, *P_OSAL_OP; + +typedef struct _OSAL_LXOP_Q { + OSAL_SLEEPABLE_LOCK sLock; + UINT32 write; + UINT32 read; + UINT32 size; + P_OSAL_OP queue[OSAL_OP_BUF_SIZE]; +} OSAL_OP_Q, *P_OSAL_OP_Q; + +typedef struct _OSAL_WAKE_LOCK_ { + #ifdef CONFIG_PM_WAKELOCKS + struct wakeup_source wake_lock; + #else + struct wake_lock wake_lock; + #endif + UINT8 name[MAX_WAKE_LOCK_NAME_LEN]; +} OSAL_WAKE_LOCK, *P_OSAL_WAKE_LOCK; +#if 1 +typedef struct _OSAL_BIT_OP_VAR_ { + unsigned long data; + OSAL_UNSLEEPABLE_LOCK opLock; +} OSAL_BIT_OP_VAR, *P_OSAL_BIT_OP_VAR; +#else +#define OSAL_BIT_OP_VAR unsigned long +#define P_OSAL_BIT_OP_VAR unsigned long * + +#endif +typedef UINT32(*P_OSAL_EVENT_CHECKER) (P_OSAL_THREAD pThread); +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern UINT32 osal_strlen(const char *str); +extern INT32 osal_strcmp(const char *dst, const char *src); +extern INT32 osal_strncmp(const char *dst, const char *src, UINT32 len); +extern char *osal_strcpy(char *dst, const char *src); +extern char *osal_strncpy(char *dst, const char *src, UINT32 len); +extern char *osal_strcat(char *dst, const char *src); +extern char *osal_strncat(char *dst, const char *src, UINT32 len); +extern char *osal_strchr(const char *str, UINT8 c); +extern char *osal_strsep(char **str, const char *c); +extern int osal_strtol(const char *str, UINT32 adecimal, long *res); +extern INT32 osal_snprintf(char *buf, UINT32 len, const char *fmt, ...); +extern char *osal_strstr(char *str1, const char *str2); + +extern INT32 osal_err_print(const char *str, ...); +extern INT32 osal_dbg_print(const char *str, ...); +extern INT32 osal_warn_print(const char *str, ...); + +extern INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line); +extern INT32 osal_sprintf(char *str, const char *format, ...); +extern VOID *osal_malloc(UINT32 size); +extern VOID osal_free(const VOID *dst); +extern VOID *osal_memset(VOID *buf, INT32 i, UINT32 len); +extern VOID *osal_memcpy(VOID *dst, const VOID *src, UINT32 len); +extern INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len); + +extern INT32 osal_sleep_ms(UINT32 ms); +extern INT32 osal_udelay(UINT32 us); +extern INT32 osal_timer_create(P_OSAL_TIMER); +extern INT32 osal_timer_start(P_OSAL_TIMER, UINT32); +extern INT32 osal_timer_stop(P_OSAL_TIMER); +extern INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer); +extern INT32 osal_timer_modify(P_OSAL_TIMER, UINT32); +extern INT32 osal_timer_delete(P_OSAL_TIMER); + +extern INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size); +extern VOID osal_fifo_deinit(P_OSAL_FIFO pFifo); +extern INT32 osal_fifo_reset(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +extern UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size); +extern UINT32 osal_fifo_len(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo); +extern UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo); + +extern INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_lock(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK plock); +extern INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK plock); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_unsleepable_lock_init(l) { spin_lock_init(&((l)->lock)); } +#else +extern INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK); +#endif +extern INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +extern INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK); +extern INT32 osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK); + +#if defined(CONFIG_PROVE_LOCKING) +#define osal_sleepable_lock_init(l) { mutex_init(&((l)->lock)); } +#else +extern INT32 osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK); +#endif +extern INT32 osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +extern INT32 osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK); +extern INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK); + +extern INT32 osal_signal_init(P_OSAL_SIGNAL); +extern INT32 osal_wait_for_signal(P_OSAL_SIGNAL); +extern INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL); +extern INT32 osal_raise_signal(P_OSAL_SIGNAL); +extern INT32 osal_signal_deinit(P_OSAL_SIGNAL); + +extern INT32 osal_event_init(P_OSAL_EVENT); +extern INT32 osal_wait_for_event(P_OSAL_EVENT, P_COND, void *); +extern INT32 osal_wait_for_event_timeout(P_OSAL_EVENT, P_COND, void *); +extern INT32 osal_trigger_event(P_OSAL_EVENT); + +extern INT32 osal_event_deinit(P_OSAL_EVENT); + +extern INT32 osal_thread_create(P_OSAL_THREAD); +extern INT32 osal_thread_run(P_OSAL_THREAD); +extern INT32 osal_thread_should_stop(P_OSAL_THREAD); +extern INT32 osal_thread_stop(P_OSAL_THREAD); +/*extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT);*/ +extern INT32 osal_thread_wait_for_event(P_OSAL_THREAD, P_OSAL_EVENT, P_OSAL_EVENT_CHECKER); +/*check pOsalLxOp and OSAL_THREAD_SHOULD_STOP*/ +extern INT32 osal_thread_destroy(P_OSAL_THREAD); + +extern INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); +extern INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData); + +extern INT32 osal_dbg_assert_aee(const char *module, const char *detail_description); +extern INT32 osal_gettimeofday(PINT32 sec, PINT32 usec); +extern INT32 osal_printtimeofday(const PUINT8 prefix); + +extern VOID osal_buffer_dump(const UINT8 *buf, const UINT8 *title, UINT32 len, UINT32 limit); + +extern UINT32 osal_op_get_id(P_OSAL_OP pOp); +extern MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp); +extern VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result); +extern VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result); +extern UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length); +extern VOID osal_thread_show_stack(P_OSAL_THREAD pThread); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#define osal_assert(condition) \ +do { \ + if (!(condition)) \ + osal_err_print("%s, %d, (%s)\n", __FILE__, __LINE__, #condition); \ +} while (0) + +#endif /* _OSAL_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h new file mode 100644 index 0000000000000..b3a9c57e062dd --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/osal_typedef.h @@ -0,0 +1,90 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _OSAL_TYPEDEF_H_ +#define _OSAL_TYPEDEF_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_EARLYSUSPEND +#include +#else +#include +#endif +#include +#include +#ifdef WMT_PLAT_ALPS +#include +#endif +#include +#ifdef CONFIG_PM_WAKELOCKS +#include +#else +#include +#endif +#include + +#ifndef _TYPEDEFS_H /*fix redifine */ +typedef char INT8; +#endif + +typedef void VOID, *PVOID, **PPVOID; +typedef char *PINT8, **PPINT8; +typedef short INT16, *PINT16, **PPINT16; +typedef int INT32, *PINT32, **PPINT32; +typedef long long INT64, *PINT64, **PPINT64; + +typedef unsigned char UINT8, *PUINT8, **PPUINT8; +typedef unsigned short UINT16, *PUINT16, **PPUINT16; +typedef unsigned int UINT32, *PUINT32, **PPUINT32; +typedef unsigned long long UINT64, *PUINT64, **PPUINT64; + +typedef size_t SIZE_T; + +typedef int MTK_WCN_BOOL; +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +#endif /*_OSAL_TYPEDEF_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h new file mode 100644 index 0000000000000..17be778484c17 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/include/wmt_idc.h @@ -0,0 +1,97 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_IDC_H_ +#define _WMT_IDC_H_ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_stp_exp.h" + +#if CFG_WMT_LTE_COEX_HANDLING + +#include "wmt_stp_exp.h" +#include "conn_md_exp.h" + +#define LTE_IDC_BUFFER_MAX_SIZE 1024 +/*comment from firmware owner,max pckage num is 5,but should not happened*/ +#define WMT_IDC_RX_MAX_LEN 384 +#define LTE_MSG_ID_OFFSET 0x30 + +typedef enum { + WMT_IDC_TX_OPCODE_MIN = 0, + WMT_IDC_TX_OPCODE_LTE_PARA = 0x0a, + WMT_IDC_TX_OPCODE_LTE_FREQ = 0x0b, + WMT_IDC_TX_OPCODE_WIFI_MAX_POWER = 0x0c, + WMT_IDC_TX_OPCODE_DEBUG_MONITOR = 0x0e, + WMT_IDC_TX_OPCODE_SPLIT_FILTER = 0x0f, + WMT_IDC_TX_OPCODE_LTE_CONNECTION_STAS = 0x16, + WMT_IDC_TX_OPCODE_LTE_HW_IF_INDICATION = 0x17, + WMT_IDC_TX_OPCODE_LTE_INDICATION = 0x20, + WMT_IDC_TX_OPCODE_MAX +} WMT_IDC_TX_OPCODE; + +typedef enum { + WMT_IDC_RX_OPCODE_BTWF_DEF_PARA = 0x0, + WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN = 0x1, + /* WMT_IDC_RX_OPCODE_TDM_REQ = 0x10, */ + WMT_IDC_RX_OPCODE_DEBUG_MONITOR = 0x02, + WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE = 0x03, + WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND = 0x04, + WMT_IDC_RX_OPCODE_UART_PIN_SEL = 0x05, + WMT_IDC_RX_OPCODE_MAX +} WMT_IDC_RX_OPCODE; + +#if (CFG_WMT_LTE_ENABLE_MSGID_MAPPING == 0) +typedef enum { + IPC_L4C_MSG_ID_INVALID = IPC_L4C_MSG_ID_BEGIN, + IPC_L4C_MSG_ID_END, + IPC_EL1_MSG_ID_INVALID = IPC_EL1_MSG_ID_BEGIN, + /* below are EL1 IPC messages sent from AP */ + IPC_MSG_ID_EL1_LTE_TX_ALLOW_IND, + IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND, + IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND, + IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND, + IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND, + + /* below are EL1 messages sent to AP */ + IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, + IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, + IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, + IPC_MSG_ID_EL1_LTE_TX_IND, + IPC_MSG_ID_EL1_LTE_CONNECTION_STATUS_IND, + IPC_MSG_ID_EL1_PIN_TYPE_IND, + IPC_MSG_ID_EL1_LTE_HW_INTERFACE_IND, + IPC_MSG_ID_EL1_DUMMY13_IND, + IPC_MSG_ID_EL1_DUMMY14_IND, + IPC_MSG_ID_EL1_DUMMY15_IND, + IPC_EL1_MSG_ID_END, +} IPC_MSG_ID_CODE; +#endif + +typedef struct _MTK_WCN_WMT_IDC_INFO_ { + ipc_ilm_t iit; + CONN_MD_BRIDGE_OPS ops; + UINT8 buffer[LTE_IDC_BUFFER_MAX_SIZE]; +} MTK_WCN_WMT_IDC_INFO, *P_MTK_WCN_WMT_IDC_INFO; + +extern INT32 wmt_idc_init(VOID); +extern INT32 wmt_idc_deinit(VOID); +extern INT32 wmt_idc_msg_from_lte_handing(ipc_ilm_t *ilm); +extern INT32 wmt_idc_msg_to_lte_handing(VOID); +extern UINT32 wmt_idc_msg_to_lte_handing_for_test(UINT8 *p_buf, UINT32 len); + +#endif /* endif CFG_WMT_LTE_COEX_HANDLING */ + +#endif /* _WMT_IDC_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile new file mode 100644 index 0000000000000..ff0f0b0aefda7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/Makefile @@ -0,0 +1,21 @@ +ifeq ($(CONFIG_MTK_COMBO), y) + +ccflags-y += \ + -I$(src)/../../linux/include \ + -I$(src)/../../linux/pri/include \ + -I$(src)/../../core/include \ + -I$(src)/../../include \ + -I$(src)/../include \ + -I$(src)/../../../common_detect \ + -I$(srctree)/drivers/misc/mediatek/btif/common/inc \ + -I$(srctree)/drivers/misc/mediatek/mach/$(MTK_PLATFORM)/include/mach + +ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1 + +obj-y += stp_btif.o \ + stp_dbg.o \ + stp_exp.o \ + wmt_dev.o \ + wmt_exp.o + +endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h new file mode 100644 index 0000000000000..3730fbba69289 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_btif.h @@ -0,0 +1,31 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _STP_BTIF_H_ +#define _STP_BTIF_H_ + +#include "osal_typedef.h" +#include "mtk_btif_exp.h" + +extern INT32 mtk_wcn_consys_stp_btif_open(VOID); +extern INT32 mtk_wcn_consys_stp_btif_close(VOID); +extern INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb); +extern INT32 mtk_wcn_consys_stp_btif_tx(const UINT8 *pBuf, const UINT32 len, UINT32 *written_len); +extern INT32 mtk_wcn_consys_stp_btif_wakeup(VOID); +extern INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag); +extern INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode); +extern INT32 mtk_wcn_consys_stp_btif_logger_ctrl(ENUM_BTIF_DBG_ID flag); +extern MTK_WCN_BOOL mtk_wcn_consys_stp_btif_parser_wmt_evt(const UINT8 *str, UINT32 len); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h new file mode 100644 index 0000000000000..de5684a168537 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/stp_dbg.h @@ -0,0 +1,316 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _STP_DEBUG_H_ +#define _STP_DEBUG_H_ + +#include +#include "osal.h" + +#define CONFIG_LOG_STP_INTERNAL + +#if 1 /* #ifndef CONFIG_LOG_STP_INTERNAL */ +#define STP_PKT_SZ 16 +#define STP_DMP_SZ 2048 +#define STP_PKT_NO 2048 + +#define STP_DBG_LOG_ENTRY_NUM 60 +#define STP_DBG_LOG_ENTRY_SZ 64 + +#else + +#define STP_PKT_SZ 16 +#define STP_DMP_SZ 16 +#define STP_PKT_NO 16 + +#define STP_DBG_LOG_ENTRY_NUM 28 +#define STP_DBG_LOG_ENTRY_SZ 64 + +#endif + +typedef enum { + STP_DBG_EN = 0, + STP_DBG_PKT = 1, + STP_DBG_DR = 2, + STP_DBG_FW_ASSERT = 3, + STP_DBG_FW_LOG = 4, + STP_DBG_FW_DMP = 5, + STP_DBG_MAX +} STP_DBG_OP_T; + +typedef enum { + STP_DBG_PKT_FIL_ALL = 0, + STP_DBG_PKT_FIL_BT = 1, + STP_DBG_PKT_FIL_GPS = 2, + STP_DBG_PKT_FIL_FM = 3, + STP_DBG_PKT_FIL_WMT = 4, + STP_DBG_PKT_FIL_MAX +} STP_DBG_PKT_FIL_T; + +static char *const gStpDbgType[] = { + "< BT>", + "< FM>", + "", + "", + "", + "", + "", + "", + "" +}; + +typedef enum { + STP_DBG_DR_MAX = 0, +} STP_DBG_DR_FIL_T; + +typedef enum { + STP_DBG_FW_MAX = 0, +} STP_DBG_FW_FIL_T; + +typedef enum { + PKT_DIR_RX = 0, + PKT_DIR_TX +} STP_DBG_PKT_DIR_T; + +/*simple log system ++*/ + +typedef struct { + /*type: 0. pkt trace 1. fw info + * 2. assert info 3. trace32 dump . + * -1. linked to the the previous + */ + int id; + int len; + char buffer[STP_DBG_LOG_ENTRY_SZ]; +} MTKSTP_LOG_ENTRY_T; + +typedef struct log_sys { + MTKSTP_LOG_ENTRY_T queue[STP_DBG_LOG_ENTRY_NUM]; + unsigned int size; + unsigned int in; + unsigned int out; + spinlock_t lock; +} MTKSTP_LOG_SYS_T; +/*--*/ + +typedef struct stp_dbg_pkt_hdr { + /* packet information */ + unsigned int sec; + unsigned int usec; + unsigned int dbg_type; + unsigned int dmy; + unsigned int no; + unsigned int dir; + + /* packet content */ + unsigned int type; + unsigned int len; + unsigned int ack; + unsigned int seq; + unsigned int chs; + unsigned int crc; +} STP_DBG_HDR_T; + +typedef struct stp_dbg_pkt { + struct stp_dbg_pkt_hdr hdr; + unsigned char raw[STP_DMP_SZ]; +} STP_PACKET_T; + +typedef struct mtkstp_dbg_t { + /*log_sys */ + int pkt_trace_no; + void *btm; + int is_enable; + MTKSTP_LOG_SYS_T *logsys; +} MTKSTP_DBG_T; + +/* extern void aed_combo_exception(const int *, int, const int *, int, const char *); */ + +#define STP_CORE_DUMP_TIMEOUT (5*60*1000) /* default 5minutes */ +#define STP_OJB_NAME_SZ 20 +#define STP_CORE_DUMP_INFO_SZ 500 +#define STP_CORE_DUMP_INIT_SIZE 1 +typedef enum wcn_compress_algorithm_t { + GZIP = 0, + BZIP2 = 1, + RAR = 2, + LMA = 3, + MAX +} WCN_COMPRESS_ALG_T; + +typedef INT32 (*COMPRESS_HANDLER) (void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, + INT32 finish); +typedef struct wcn_compressor_t { + /* current object name */ + UINT8 name[STP_OJB_NAME_SZ + 1]; + + /* buffer for raw data, named L1 */ + PUINT8 L1_buf; + INT32 L1_buf_sz; + INT32 L1_pos; + + /* target buffer, named L2 */ + PUINT8 L2_buf; + INT32 L2_buf_sz; + INT32 L2_pos; + + /* compress state */ + UINT8 f_done; + UINT16 reserved; + UINT32 uncomp_size; + UINT32 crc32; + + /* compress algorithm */ + UINT8 f_compress_en; + WCN_COMPRESS_ALG_T compress_type; + void *worker; + COMPRESS_HANDLER handler; +} WCN_COMPRESSOR_T, *P_WCN_COMPRESSOR_T; + +P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz); +INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T compressor); +INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T compressor, PUINT8 buf, INT32 len, INT32 finish); +INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T compressor, PUINT8 *pbuf, PINT32 len); +INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T compressor, UINT8 enable, WCN_COMPRESS_ALG_T type); + +typedef enum core_dump_state_t { + CORE_DUMP_INIT = 0, + CORE_DUMP_DOING, + CORE_DUMP_TIMEOUT, + CORE_DUMP_DONE, + CORE_DUMP_MAX +} CORE_DUMP_STA; + +typedef struct core_dump_t { + /* compress dump data and buffered */ + P_WCN_COMPRESSOR_T compressor; + + /* timer for monitor timeout */ + OSAL_TIMER dmp_timer; + UINT32 timeout; + + OSAL_SLEEPABLE_LOCK dmp_lock; + + /* state machine for core dump flow */ + CORE_DUMP_STA sm; + + /* dump info */ + INT8 info[STP_CORE_DUMP_INFO_SZ + 1]; +} WCN_CORE_DUMP_T, *P_WCN_CORE_DUMP_T; + +typedef enum _ENUM_STP_FW_ISSUE_TYPE_ { + STP_FW_ISSUE_TYPE_INVALID = 0x0, + STP_FW_ASSERT_ISSUE = 0x1, + STP_FW_NOACK_ISSUE = 0x2, + STP_FW_WARM_RST_ISSUE = 0x3, + STP_DBG_PROC_TEST = 0x4, + STP_HOST_TRIGGER_FW_ASSERT = 0x5, + STP_HOST_TRIGGER_ASSERT_TIMEOUT = 0x6, + STP_FW_ISSUE_TYPE_MAX +} ENUM_STP_FW_ISSUE_TYPE, *P_ENUM_STP_FW_ISSUE_TYPE; + +/* this was added for support dmareg's issue */ +typedef enum _ENUM_DMA_ISSUE_TYPE_ { + CONNSYS_CLK_GATE_STATUS = 0x00, + CONSYS_EMI_STATUS, + SYSRAM1, + SYSRAM2, + SYSRAM3, + DMA_REGS_MAX +} ENUM_DMA_ISSUE_TYPE; +#define STP_PATCH_TIME_SIZE 12 +#define STP_DBG_CPUPCR_NUM 512 +#define STP_DBG_DMAREGS_NUM 16 +#define STP_PATCH_BRANCH_SZIE 8 +#define STP_ASSERT_INFO_SIZE 64 +#define STP_DBG_ROM_VER_SIZE 4 +#define STP_ASSERT_TYPE_SIZE 32 + +typedef struct stp_dbg_host_assert_t { + UINT32 drv_type; + UINT32 reason; + UINT32 assert_from_host; +} STP_DBG_HOST_ASSERT_T, *P_STP_DBG_HOST_ASSERT_T; + +typedef struct stp_dbg_cpupcr_t { + UINT32 chipId; + UINT8 romVer[STP_DBG_ROM_VER_SIZE]; + UINT8 patchVer[STP_PATCH_TIME_SIZE]; + UINT8 branchVer[STP_PATCH_BRANCH_SZIE]; + UINT32 wifiVer; + UINT32 count; + UINT32 stop_flag; + UINT32 buffer[STP_DBG_CPUPCR_NUM]; + UINT8 assert_info[STP_ASSERT_INFO_SIZE]; + UINT32 fwTaskId; + UINT32 fwRrq; + UINT32 fwIsr; + STP_DBG_HOST_ASSERT_T host_assert_info; + UINT8 assert_type[STP_ASSERT_TYPE_SIZE]; + ENUM_STP_FW_ISSUE_TYPE issue_type; + OSAL_SLEEPABLE_LOCK lock; +} STP_DBG_CPUPCR_T, *P_STP_DBG_CPUPCR_T; + +typedef struct stp_dbg_dmaregs_t { + UINT32 count; + UINT32 dmaIssue[DMA_REGS_MAX][STP_DBG_DMAREGS_NUM]; + OSAL_SLEEPABLE_LOCK lock; +} STP_DBG_DMAREGS_T, *P_STP_DBG_DMAREGS_T; + +typedef enum _ENUM_ASSERT_INFO_PARSER_TYPE_ { + STP_DBG_ASSERT_INFO = 0x0, + STP_DBG_FW_TASK_ID = 0x1, + STP_DBG_FW_ISR = 0x2, + STP_DBG_FW_IRQ = 0x3, + STP_DBG_ASSERT_TYPE = 0x4, + STP_DBG_PARSER_TYPE_MAX +} ENUM_ASSERT_INFO_PARSER_TYPE, *P_ENUM_ASSERT_INFO_PARSER_TYPE; + +P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 packet_num, UINT32 timeout); +INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp); +INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len); +INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 len); +INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout); +INT32 wcn_core_dump_timeout(void); +INT32 wcn_wmtd_timeout_collect_ftrace(void); + +extern INT32 wcn_core_dump_init_gcoredump(UINT32 packet_num, UINT32 timeout); +extern INT32 wcn_core_dump_deinit_gcoredump(VOID); +extern INT32 wcn_core_dump_flush(INT32 rst, MTK_WCN_BOOL is_coredump_timeout); +extern int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg); +extern int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg); +extern MTKSTP_DBG_T *stp_dbg_init(void *); +extern int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg); +extern int stp_dbg_dmp_out_ex(char *buf, int *len); +extern int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len); +extern int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg); +extern char stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len); + +extern INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd); +extern INT32 _stp_btm_put_emi_dump_to_nl(PUINT8 data_buf, INT32 dump_len); +extern int +stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, + int dbg_type, int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body); +extern int stp_dbg_log_ctrl(unsigned int on); +extern INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd); +extern INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep); +extern INT32 stp_dbg_poll_cuppcr_ctrl(UINT32 en); +extern INT32 stp_dbg_set_version_info(UINT32 chipid, PUINT8 pRomVer, PUINT8 pPatchVer, + PUINT8 pPatchBrh); +extern INT32 stp_dbg_set_wifiver(UINT32 wifiver); +extern INT32 stp_dbg_cpupcr_infor_format(PPUINT8 buf, PUINT32 len); +extern INT32 stp_dbg_set_fw_info(PUINT8 assert_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type); +extern INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en); +extern UINT32 stp_dbg_get_host_trigger_assert(VOID); +#endif /* end of _STP_DEBUG_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h new file mode 100644 index 0000000000000..5788eb355549a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/include/wmt_dev.h @@ -0,0 +1,71 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#ifndef _WMT_DEV_H_ +#define _WMT_DEV_H_ + +#include "osal.h" + +#define STP_UART_FULL 0x01 +#define STP_UART_MAND 0x02 +#define STP_BTIF_FULL 0x03 +#define STP_SDIO 0x04 + +#define CFG_WMT_DBG_SUPPORT 1 /* support wmt_dbg or not */ +#define CFG_WMT_PROC_FOR_AEE 1 + +extern VOID wmt_dev_rx_event_cb(VOID); +extern INT32 wmt_dev_rx_timeout(P_OSAL_EVENT pEvent); +extern INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch, INT32 padSzBuf); +extern INT32 wmt_dev_patch_put(osal_firmware **ppPatch); +extern VOID wmt_dev_patch_info_free(VOID); +extern VOID wmt_dev_send_cmd_to_daemon(UINT32 cmd); +extern MTK_WCN_BOOL wmt_dev_get_early_suspend_state(VOID); + +#if CFG_WMT_DBG_SUPPORT +typedef struct _COEX_BUF { + UINT8 buffer[128]; + INT32 availSize; +} COEX_BUF, *P_COEX_BUF; + +typedef enum _ENUM_CMD_TYPE_T { + WMTDRV_CMD_ASSERT = 0, + WMTDRV_CMD_EXCEPTION = 1, + WMTDRV_CMD_COEXDBG_00 = 2, + WMTDRV_CMD_COEXDBG_01 = 3, + WMTDRV_CMD_COEXDBG_02 = 4, + WMTDRV_CMD_COEXDBG_03 = 5, + WMTDRV_CMD_COEXDBG_04 = 6, + WMTDRV_CMD_COEXDBG_05 = 7, + WMTDRV_CMD_COEXDBG_06 = 8, + WMTDRV_CMD_COEXDBG_07 = 9, + WMTDRV_CMD_COEXDBG_08 = 10, + WMTDRV_CMD_COEXDBG_09 = 11, + WMTDRV_CMD_COEXDBG_10 = 12, + WMTDRV_CMD_COEXDBG_11 = 13, + WMTDRV_CMD_COEXDBG_12 = 14, + WMTDRV_CMD_COEXDBG_13 = 15, + WMTDRV_CMD_COEXDBG_14 = 16, + WMTDRV_CMD_COEXDBG_15 = 17, + WMTDRV_CMD_NOACK_TEST = 18, + WMTDRV_CMD_WARNRST_TEST = 19, + WMTDRV_CMD_FWTRACE_TEST = 20, + WMTDRV_CMD_MAX +} ENUM_WMTDRV_CMD_T, *P_ENUM_WMTDRV_CMD_T; + +#endif + +typedef INT32(*WMT_DEV_DBG_FUNC) (INT32 par1, INT32 par2, INT32 par3); + +#endif /*_WMT_DEV_H_*/ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c new file mode 100644 index 0000000000000..76debb4674f9c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_btif.c @@ -0,0 +1,279 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*file: stp_btif, mainly control stp & btif interaction*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[STP-BTIF]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "wmt_exp.h" +#include "stp_exp.h" +#include "stp_btif.h" + +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BTIF_OWNER_NAME "CONSYS_STP" + +#define STP_MAX_PACKAGE_ALLOWED (2000) + +#define STP_BTIF_TX_RTY_LMT (10) +#define STP_BTIF_TX_RTY_DLY (5) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +unsigned long stpBtifId = 0; +unsigned long *pBtifRef = &stpBtifId; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 mtk_wcn_consys_stp_btif_open(VOID) +{ + INT32 iRet = -1; + + iRet = mtk_wcn_btif_open(BTIF_OWNER_NAME, pBtifRef); + if (iRet) { + WMT_WARN_FUNC("STP open btif fail(%d)\n", iRet); + return -1; + } + WMT_DBG_FUNC("STP open bitf OK\n"); + + mtk_wcn_stp_register_if_tx(STP_BTIF_IF_TX, (MTK_WCN_STP_IF_TX) mtk_wcn_consys_stp_btif_tx); + + return 0; +} + +INT32 mtk_wcn_consys_stp_btif_close(VOID) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_close(stpBtifId); + if (iRet) { + WMT_WARN_FUNC("STP close btif fail(%d)\n", iRet); + iRet = -2; + } else { + stpBtifId = 0; + WMT_DBG_FUNC("STP close btif OK\n"); + } + } + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_rx_cb_register(MTK_WCN_BTIF_RX_CB rx_cb) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference\n!"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_rx_cb_register(stpBtifId, rx_cb); + if (iRet) { + WMT_WARN_FUNC("STP register rxcb to btif fail(%d)\n", iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("STP register rxcb to btif OK\n"); + } + } + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_tx(const UINT8 *pBuf, const UINT32 len, UINT32 *written_len) +{ + INT32 retry_left = STP_BTIF_TX_RTY_LMT; + INT32 wr_count = 0; + INT32 written = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + return -1; + } + + if (len == 0) { + *written_len = 0; + WMT_INFO_FUNC("special case for STP-CORE,pbuf(%p)\n", pBuf); + return 0; + } + + *written_len = 0; + + if (len > STP_MAX_PACKAGE_ALLOWED) { + WMT_WARN_FUNC("abnormal pacage length,len(%d),pid[%d/%s]\n", len, current->pid, current->comm); + return -2; + } + wr_count = mtk_wcn_btif_write(stpBtifId, pBuf, len); + + if (wr_count < 0) { + WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)\n", wr_count); + *written_len = 0; + return -3; + } + if (wr_count == len) { + /*perfect case */ + *written_len = wr_count; + return wr_count; + } + + while ((retry_left--) && (wr_count < len)) { + osal_sleep_ms(STP_BTIF_TX_RTY_DLY); + written = mtk_wcn_btif_write(stpBtifId, pBuf + wr_count, len - wr_count); + if (written < 0) { + WMT_ERR_FUNC("mtk_wcn_btif_write err(%d)when do recovered\n", written); + break; + } + wr_count += written; + } + + if (wr_count == len) { + WMT_INFO_FUNC("recovered,len(%d),retry_left(%d)\n", len, retry_left); + /*recovered case */ + *written_len = wr_count; + return wr_count; + } + + WMT_ERR_FUNC("stp btif write fail,len(%d),written(%d),retry_left(%d),pid[%d/%s]\n", + len, wr_count, retry_left, current->pid, current->comm); + *written_len = 0; + return -wr_count; +} + +INT32 mtk_wcn_consys_stp_btif_rx(UINT8 *pBuf, UINT32 len) +{ + return 0; +} + +INT32 mtk_wcn_consys_stp_btif_wakeup(VOID) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_wakeup_consys(stpBtifId); + if (iRet) { + WMT_WARN_FUNC("STP btif wakeup consys fail(%d)\n", iRet); + iRet = -2; + } else { + WMT_DBG_FUNC("STP btif wakeup consys ok\n"); + } + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_dpidle_ctrl(ENUM_BTIF_DPIDLE_CTRL en_flag) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + mtk_wcn_btif_dpidle_ctrl(stpBtifId, en_flag); + WMT_DBG_FUNC("stp btif dpidle ctrl done,en_flag(%d)\n", en_flag); + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_lpbk_ctrl(ENUM_BTIF_LPBK_MODE mode) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_loopback_ctrl(stpBtifId, mode); + if (iRet) { + WMT_WARN_FUNC("STP btif lpbk ctrl fail(%d)\n", iRet); + iRet = -2; + } else { + WMT_INFO_FUNC("stp btif lpbk ctrl ok,mode(%d)\n", mode); + } + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_logger_ctrl(ENUM_BTIF_DBG_ID flag) +{ + INT32 iRet = 0; + + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + iRet = -1; + } else { + iRet = mtk_wcn_btif_dbg_ctrl(stpBtifId, flag); + if (iRet) { + WMT_WARN_FUNC("STP btif log dbg ctrl fail(%d)\n", iRet); + iRet = -2; + } else { + WMT_INFO_FUNC("stp btif log dbg ctrl ok,flag(%d)\n", flag); + } + } + + return iRet; +} + +INT32 mtk_wcn_consys_stp_btif_parser_wmt_evt(const UINT8 *str, UINT32 len) +{ + if (!stpBtifId) { + WMT_WARN_FUNC("NULL BTIF ID reference!\n"); + return -1; + } else { + return (INT32) mtk_wcn_btif_parser_wmt_evt(stpBtifId, str, len); + } +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c new file mode 100644 index 0000000000000..fdb610cc3897d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_dbg.c @@ -0,0 +1,2061 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ +#include /* GFP_KERNEL */ +#include /* init_timer, add_time, del_timer_sync */ +#include /* gettimeofday */ +#include +#include /* kzalloc */ +#include /* task's status */ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "osal_typedef.h" +#include "stp_dbg.h" +/* #include "stp_btm.h" */ +#include "btm_core.h" +#include "wmt_plat.h" + +#define PFX_STP_DBG "[STPDbg]" +#define STP_DBG_LOG_LOUD 4 +#define STP_DBG_LOG_DBG 3 +#define STP_DBG_LOG_INFO 2 +#define STP_DBG_LOG_WARN 1 +#define STP_DBG_LOG_ERR 0 + +unsigned int gStpDbgDbgLevel = STP_DBG_LOG_INFO; +unsigned int gStpDbgLogOut = 0; + +#define STP_DBG_LOUD_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_LOUD) \ + pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_DBG_DBG_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_DBG) \ + pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_DBG_INFO_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_INFO) \ + pr_debug(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_DBG_WARN_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_WARN) \ + pr_warn(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_DBG_ERR_FUNC(fmt, arg...) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_ERR) \ + pr_err(PFX_STP_DBG "%s: " fmt, __func__ , ##arg); \ +} while (0) +#define STP_DBG_TRC_FUNC(f) \ +do { \ + if (gStpDbgDbgLevel >= STP_DBG_LOG_DBG) \ + pr_debug(PFX_STP_DBG "<%s> <%d>\n", __func__, __LINE__); \ +} while (0) + +MTKSTP_DBG_T *g_stp_dbg = NULL; + +#define STP_DBG_FAMILY_NAME "STP_DBG" +#define MAX_BIND_PROCESS (4) +#ifdef WMT_PLAT_ALPS +#define STP_DBG_AEE_EXP_API (1) +#else +#define STP_DBG_AEE_EXP_API (0) +#endif +enum { + __STP_DBG_ATTR_INVALID, + STP_DBG_ATTR_MSG, + __STP_DBG_ATTR_MAX, +}; +#define STP_DBG_ATTR_MAX (__STP_DBG_ATTR_MAX - 1) + +enum { + __STP_DBG_COMMAND_INVALID, + STP_DBG_COMMAND_BIND, + STP_DBG_COMMAND_RESET, + __STP_DBG_COMMAND_MAX, +}; +#define MTK_WIFI_COMMAND_MAX (__STP_DBG_COMMAND_MAX - 1) + +static struct genl_family stp_dbg_gnl_family = { + .id = GENL_ID_GENERATE, + .hdrsize = 0, + .name = STP_DBG_FAMILY_NAME, + .version = 1, + .maxattr = STP_DBG_ATTR_MAX, +}; + +static void stp_dbg_nl_init(void); +static void stp_dbg_nl_deinit(void); +static int stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info); +static int stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info); + +/* attribute policy */ +static struct nla_policy stp_dbg_genl_policy[STP_DBG_ATTR_MAX + 1] = { + [STP_DBG_ATTR_MSG] = {.type = NLA_NUL_STRING}, +}; + +/* operation definition */ +#if 0 +static struct genl_ops stp_dbg_gnl_ops_bind = { + .cmd = STP_DBG_COMMAND_BIND, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_bind, + .dumpit = NULL, +}; + +static struct genl_ops stp_dbg_gnl_ops_reset = { + .cmd = STP_DBG_COMMAND_RESET, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_reset, + .dumpit = NULL, +}; +#endif +static struct genl_ops stp_dbg_gnl_ops_array[] = { + { + .cmd = STP_DBG_COMMAND_BIND, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_bind, + .dumpit = NULL, + }, + { + .cmd = STP_DBG_COMMAND_RESET, + .flags = 0, + .policy = stp_dbg_genl_policy, + .doit = stp_dbg_nl_reset, + .dumpit = NULL, + }, +}; + +#if 0 +#define E2S(x) #x +static char *dmaRegsStr[] = { + E2S(CONNSYS_CLK_GATE_STATUS), + E2S(CONSYS_EMI_STATUS), + E2S(SYSRAM1), + E2S(SYSRAM2), + E2S(SYSRAM3) +}; +#endif +static unsigned int stp_dbg_seqnum; +static int num_bind_process; +static pid_t bind_pid[MAX_BIND_PROCESS]; + +static P_WCN_CORE_DUMP_T g_core_dump; + +static P_STP_DBG_CPUPCR_T g_stp_dbg_cpupcr; + +/* just show in log at present */ +static P_STP_DBG_DMAREGS_T g_stp_dbg_dmaregs; + +/* core_dump_timeout_handler - handler of coredump timeout + * @ data - core dump object's pointer + * + * No return value + */ +static void core_dump_timeout_handler(/*unsigned long data*/struct timer_list *t) +{ + //P_WCN_CORE_DUMP_T dmp = (P_WCN_CORE_DUMP_T) data; + P_WCN_CORE_DUMP_T dmp = from_timer(dmp,t,dmp_timer.timer); + + STP_DBG_INFO_FUNC(" start\n"); + + stp_btm_notify_coredump_timeout_wq(g_stp_dbg->btm); + + STP_DBG_INFO_FUNC(" end\n"); + + if (dmp) + dmp->sm = CORE_DUMP_TIMEOUT; +} + +/* wcn_core_dump_init - create core dump sys + * @ timeout - core dump time out value + * + * Return object pointer if success, else NULL + */ +P_WCN_CORE_DUMP_T wcn_core_dump_init(UINT32 packet_num, UINT32 timeout) +{ +#define KBYTES (1024*sizeof(char)) +#define L1_BUF_SIZE (32*KBYTES) + + P_WCN_CORE_DUMP_T core_dmp = NULL; + + core_dmp = (P_WCN_CORE_DUMP_T) osal_malloc(sizeof(WCN_CORE_DUMP_T)); + if (!core_dmp) { + STP_DBG_ERR_FUNC("alloc mem failed!\n"); + goto fail; + } + + osal_memset(core_dmp, 0, sizeof(WCN_CORE_DUMP_T)); + + core_dmp->compressor = wcn_compressor_init("core_dump_compressor", L1_BUF_SIZE, 18*packet_num*KBYTES); + if (!core_dmp->compressor) { + STP_DBG_ERR_FUNC("create compressor failed!\n"); + goto fail; + } + wcn_compressor_reset(core_dmp->compressor, 1, GZIP); + + core_dmp->dmp_timer.timeoutHandler = core_dump_timeout_handler; + core_dmp->dmp_timer.timeroutHandlerData = (unsigned long)core_dmp; + osal_timer_create(&core_dmp->dmp_timer); + core_dmp->timeout = timeout; + + osal_sleepable_lock_init(&core_dmp->dmp_lock); + + core_dmp->sm = CORE_DUMP_INIT; + STP_DBG_INFO_FUNC("create coredump object OK!\n"); + + return core_dmp; + +fail: + if (core_dmp && core_dmp->compressor) { + wcn_compressor_deinit(core_dmp->compressor); + core_dmp->compressor = NULL; + } + if (core_dmp) + osal_free(core_dmp); + + return NULL; +} +INT32 wcn_core_dump_init_gcoredump(UINT32 packet_num, UINT32 timeout) +{ + INT32 Ret = 0; + + g_core_dump = wcn_core_dump_init(packet_num, timeout); + if (g_core_dump == NULL) + Ret = -1; + return Ret; +} + +/* wcn_core_dump_deinit - destroy core dump object + * @ dmp - pointer of object + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_deinit(P_WCN_CORE_DUMP_T dmp) +{ + if (dmp && dmp->compressor) { + wcn_compressor_deinit(dmp->compressor); + dmp->compressor = NULL; + } + + if (dmp) { + osal_sleepable_lock_deinit(&dmp->dmp_lock); + osal_timer_stop(&dmp->dmp_timer); + osal_free(dmp); + } + + return 0; +} + +INT32 wcn_core_dump_deinit_gcoredump(VOID) +{ + wcn_core_dump_deinit(g_core_dump); + return 0; +} + +static INT32 wcn_core_dump_check_end(PUINT8 buf, INT32 len) +{ + if (strnstr(buf, "coredump end", len)) + return 1; + else + return 0; +} + +/* wcn_core_dump_in - add a packet to compressor buffer + * @ dmp - pointer of object + * @ buf - input buffer + * @ len - data length + * + * Retunr 0 if success; return 1 if find end string; else error code + */ +INT32 wcn_core_dump_in(P_WCN_CORE_DUMP_T dmp, PUINT8 buf, INT32 len) +{ + INT32 ret = 0; + INT32 tmp; + +#define INFO_HEAD ";SOC_CONSYS FW CORE, " + + if ((!dmp) || (!buf)) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + switch (dmp->sm) { + case CORE_DUMP_INIT: + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); + + /* first package, copy to info buffer */ + osal_strcpy(&dmp->info[0], INFO_HEAD); + + if (NULL == (strnstr(buf, "", 32))) { + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], "Fw warm reset exception...", + osal_strlen("Fw warm reset exception...")); + dmp->info[osal_strlen(INFO_HEAD) + osal_strlen("Fw warm reset exception...") + 1] = '\0'; + } else { + char *pStr = buf; + char *pDtr = NULL; + + pDtr = osal_strchr(pStr, '-'); + if (NULL != pDtr) { + tmp = pDtr - pStr; + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp); + dmp->info[osal_strlen(dmp->info) + 1] = '\0'; + } else { + tmp = STP_CORE_DUMP_INFO_SZ - osal_strlen(INFO_HEAD); + tmp = (len > tmp) ? tmp : len; + osal_memcpy(&dmp->info[osal_strlen(INFO_HEAD)], buf, tmp); + dmp->info[STP_CORE_DUMP_INFO_SZ] = '\0'; + } + + } + /* show coredump start info on UI */ + /* osal_dbg_assert_aee("MT662x f/w coredump start", "MT662x firmware coredump start"); */ +#if STP_DBG_AEE_EXP_API + aee_kernel_dal_show("SOC_CONSYS coredump start ....\n"); +#endif + /* parsing data, and check end srting */ + ret = wcn_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_INFO_FUNC("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } else { + dmp->sm = CORE_DUMP_DOING; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } + break; + + case CORE_DUMP_DOING: + /* parsing data, and check end srting */ + ret = wcn_core_dump_check_end(buf, len); + if (ret == 1) { + STP_DBG_INFO_FUNC("core dump end!\n"); + dmp->sm = CORE_DUMP_DONE; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } else { + dmp->sm = CORE_DUMP_DOING; + wcn_compressor_in(dmp->compressor, buf, len, 0); + } + break; + + case CORE_DUMP_DONE: + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_timer_start(&dmp->dmp_timer, STP_CORE_DUMP_TIMEOUT); + wcn_compressor_in(dmp->compressor, buf, len, 0); + dmp->sm = CORE_DUMP_DOING; + break; + + case CORE_DUMP_TIMEOUT: + break; + default: + break; + } + + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + +/* wcn_core_dump_out - get compressed data from compressor buffer + * @ dmp - pointer of object + * @ pbuf - target buffer's pointer + * @ len - data length + * + * Retunr 0 if success; else error code + */ +INT32 wcn_core_dump_out(P_WCN_CORE_DUMP_T dmp, PUINT8 *pbuf, PINT32 plen) +{ + INT32 ret = 0; + + if ((!dmp) || (!pbuf) || (!plen)) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + ret = osal_lock_sleepable_lock(&dmp->dmp_lock); + if (ret) { + STP_DBG_ERR_FUNC("--->lock dmp->dmp_lock failed, ret=%d\n", ret); + return ret; + } + + ret = wcn_compressor_out(dmp->compressor, pbuf, plen); + + osal_unlock_sleepable_lock(&dmp->dmp_lock); + + return ret; +} + +/* wcn_core_dump_reset - reset core dump sys + * @ dmp - pointer of object + * @ timeout - core dump time out value + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_reset(P_WCN_CORE_DUMP_T dmp, UINT32 timeout) +{ + if (!dmp) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + dmp->sm = CORE_DUMP_INIT; + dmp->timeout = timeout; + osal_timer_stop(&dmp->dmp_timer); + wcn_compressor_reset(dmp->compressor, 1, GZIP); + osal_memset(dmp->info, 0, STP_CORE_DUMP_INFO_SZ + 1); + + wcn_core_dump_deinit(dmp); + g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_INIT_SIZE, STP_CORE_DUMP_TIMEOUT); + + return 0; +} + +/* wcn_wmtd_timeout_collect_ftrace - wmtd timeout ,this func can collect SYS_FTRACE + * + * Retunr 0 if success + */ +#define WMTD_TIMEOUT_INFO_HEAD "Wait wmtd complation timeout ,just collect SYS_FTRACE to DB" +INT32 wcn_wmtd_timeout_collect_ftrace(void) +{ + PUINT8 pbuf; + INT32 len; + + pbuf = "Wait wmtd complation timeout"; + len = osal_strlen("Wait wmtd complation timeout"); + osal_strcpy(&g_core_dump->info[0], WMTD_TIMEOUT_INFO_HEAD); +#ifdef WMT_PLAT_ALPS + aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); +#endif + return 0; +} +/* wcn_psm_flag_trigger_collect_ftrace - wmtd timeout ,this func can collect SYS_FTRACE + * + * Retunr 0 if success + */ +#define PSM_ABNORMAL_FLAG_INFO_HEAD "Abnormal PSM flag be set ,just collect SYS_FTRACE to DB" +INT32 wcn_psm_flag_trigger_collect_ftrace(void) +{ + PUINT8 pbuf; + INT32 len; + + pbuf = "Abnormal PSM flag be set"; + len = osal_strlen("Abnormal PSM flag be set"); + osal_strcpy(&g_core_dump->info[0], PSM_ABNORMAL_FLAG_INFO_HEAD); +#ifdef WMT_PLAT_ALPS + aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); +#endif + return 0; +} +#if BTIF_RXD_BE_BLOCKED_DETECT +MTK_WCN_BOOL is_btif_rxd_be_blocked(void) +{ + MTK_WCN_BOOL flag = MTK_WCN_BOOL_FALSE; + + if (mtk_btif_rxd_be_blocked_flag_get()) + flag = MTK_WCN_BOOL_TRUE; + return flag; +} +/* wcn_btif_rxd_blocked_collect_ftrace - btif rxd be blocked,this func can collect SYS_FTRACE + * + * Retunr 0 if success + */ +#define BTIF_RXD_BLOCKED_INFO_HEAD "Btif_rxd thread be blocked too long,just collect SYS_FTRACE to DB" +INT32 wcn_btif_rxd_blocked_collect_ftrace(void) +{ + PUINT8 pbuf; + INT32 len; + + pbuf = "Btif_rxd thread be blocked too long"; + len = osal_strlen("Btif_rxd thread be blocked too long"); + osal_strcpy(&g_core_dump->info[0], BTIF_RXD_BLOCKED_INFO_HEAD); +#ifdef WMT_PLAT_ALPS + aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); +#endif + return 0; +} +#endif +/* wcn_core_dump_timeout - wait for FW assert info timeout ,this func can collect SYS_FTRACE + * + * Retunr 0 if success + */ +#define TIMEOUT_INFO_HEAD "Trigger assert timeout ,just collect SYS_FTRACE to DB" +INT32 wcn_core_dump_timeout(void) +{ + PUINT8 pbuf; + INT32 len; + + pbuf = "Trigger assert timeout"; + len = osal_strlen("Trigger assert timeout"); + osal_strcpy(&g_core_dump->info[0], TIMEOUT_INFO_HEAD); +#ifdef WMT_PLAT_ALPS + aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); +#endif + return 0; +} + +#define ENABLE_F_TRACE 0 +/* wcn_core_dump_flush - Fulsh dump data and reset core dump sys + * + * Retunr 0 if success, else error code + */ +INT32 wcn_core_dump_flush(INT32 rst, MTK_WCN_BOOL coredump_is_timeout) +{ + PUINT8 pbuf = NULL; + INT32 len = 0; + + if (!g_core_dump) { + STP_DBG_ERR_FUNC("invalid pointer!\n"); + return -1; + } + + wcn_core_dump_out(g_core_dump, &pbuf, &len); + STP_DBG_INFO_FUNC("buf 0x%zx, len %d\n", (SIZE_T) pbuf, len); +#ifdef WMT_PLAT_ALPS + /* show coredump end info on UI */ + /* osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); */ +#if STP_DBG_AEE_EXP_API + if (coredump_is_timeout) + aee_kernel_dal_show("++ SOC_CONSYS coredump tiemout ,pass received coredump to AEE ++\n"); + else + aee_kernel_dal_show("++ SOC_CONSYS coredump get successfully ++\n"); + /* call AEE driver API */ +#if ENABLE_F_TRACE + aed_combo_exception_api(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info, DB_OPT_FTRACE); +#else + aed_combo_exception(NULL, 0, (const int *)pbuf, len, (const char *)g_core_dump->info); +#endif + +#endif + +#endif // WMT_PLAT_ALPS + + /* reset */ + wcn_core_dump_reset(g_core_dump, STP_CORE_DUMP_TIMEOUT); + + return 0; +} + +static INT32 wcn_gzip_compressor(void *worker, UINT8 *in_buf, INT32 in_sz, UINT8 *out_buf, INT32 *out_sz, + INT32 finish) +{ + INT32 ret = 0; + z_stream *stream = NULL; + INT32 tmp = *out_sz; + + STP_DBG_INFO_FUNC("need to compressor :buf 0x%zx, size %d\n", (SIZE_T) in_buf, in_sz); + STP_DBG_INFO_FUNC("before compressor,avalible buf: 0x%zx, size %d\n", (SIZE_T) out_buf, tmp); + + stream = (z_stream *) worker; + if (!stream) { + STP_DBG_ERR_FUNC("invalid workspace!\n"); + return -1; + } + + if (in_sz > 0) { +#if 0 + ret = zlib_deflateReset(stream); + if (ret != Z_OK) { + STP_DBG_ERR_FUNC("reset failed!\n"); + return -2; + } +#endif + + stream->next_in = in_buf; + stream->avail_in = in_sz; + stream->next_out = out_buf; + stream->avail_out = tmp; + + zlib_deflate(stream, Z_FULL_FLUSH); + + if (finish) { + while (1) { + int val = zlib_deflate(stream, Z_FINISH); + + if (val == Z_OK) + continue; + else if (val == Z_STREAM_END) + break; + STP_DBG_ERR_FUNC("finish operation failed %d\n", val); + return -3; + } + } + + *out_sz = tmp - stream->avail_out; + } + + STP_DBG_INFO_FUNC("after compressor,avalible buf: 0x%zx, compress rate %d -> %d\n", (SIZE_T) out_buf, in_sz, + *out_sz); + + return ret; +} + +/* wcn_compressor_init - create a compressor and do init + * @ name - compressor's name + * @ L1_buf_sz - L1 buffer size + * @ L2_buf_sz - L2 buffer size + * + * Retunr object's pointer if success, else NULL + */ +P_WCN_COMPRESSOR_T wcn_compressor_init(PUINT8 name, INT32 L1_buf_sz, INT32 L2_buf_sz) +{ + z_stream *pstream = NULL; + P_WCN_COMPRESSOR_T compress = NULL; + + compress = (P_WCN_COMPRESSOR_T) osal_malloc(sizeof(WCN_COMPRESSOR_T)); + if (!compress) { + STP_DBG_ERR_FUNC("alloc compressor failed!\n"); + goto fail; + } + + osal_memset(compress, 0, sizeof(WCN_COMPRESSOR_T)); + osal_memcpy(compress->name, name, STP_OJB_NAME_SZ); + + compress->f_compress_en = 0; + compress->compress_type = GZIP; + + if (compress->compress_type == GZIP) { + compress->worker = osal_malloc(sizeof(z_stream)); + if (!compress->worker) { + STP_DBG_ERR_FUNC("alloc stream failed!\n"); + goto fail; + } + pstream = (z_stream *) compress->worker; + + pstream->workspace = osal_malloc(zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL)); + if (!pstream->workspace) { + STP_DBG_ERR_FUNC("alloc workspace failed!\n"); + goto fail; + } + zlib_deflateInit2(pstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, + DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); + } + + compress->handler = wcn_gzip_compressor; + compress->L1_buf_sz = L1_buf_sz; + compress->L2_buf_sz = L2_buf_sz; + compress->L1_pos = 0; + compress->L2_pos = 0; + compress->uncomp_size = 0; + compress->crc32 = 0xffffffffUL; + + compress->L1_buf = osal_malloc(compress->L1_buf_sz); + if (!compress->L1_buf) { + STP_DBG_ERR_FUNC("alloc %d bytes for L1 buf failed!\n", compress->L1_buf_sz); + goto fail; + } + + compress->L2_buf = osal_malloc(compress->L2_buf_sz); + if (!compress->L2_buf) { + STP_DBG_ERR_FUNC("alloc %d bytes for L2 buf failed!\n", compress->L2_buf_sz); + goto fail; + } + + STP_DBG_INFO_FUNC("create compressor OK! L1 %d bytes, L2 %d bytes\n", L1_buf_sz, L2_buf_sz); + return compress; + +fail: + if (compress) { + if (compress->L2_buf) { + osal_free(compress->L2_buf); + compress->L2_buf = NULL; + } + + if (compress->L1_buf) { + osal_free(compress->L1_buf); + compress->L1_buf = NULL; + } + + if (compress->worker) { + pstream = (z_stream *) compress->worker; + if ((compress->compress_type == GZIP) && pstream->workspace) { + zlib_deflateEnd(pstream); + osal_free(pstream->workspace); + } + osal_free(compress->worker); + compress->worker = NULL; + } + + if (compress->worker) { + osal_free(compress->worker); + compress->worker = NULL; + } + + osal_free(compress); + compress = NULL; + } + + STP_DBG_ERR_FUNC("init failed!\n"); + + return NULL; +} + +/* wcn_compressor_deinit - distroy a compressor + * @ cprs - compressor's pointer + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_deinit(P_WCN_COMPRESSOR_T cprs) +{ + z_stream *pstream = NULL; + + if (cprs) { + if (cprs->L2_buf) { + osal_free(cprs->L2_buf); + cprs->L2_buf = NULL; + } + + if (cprs->L1_buf) { + osal_free(cprs->L1_buf); + cprs->L1_buf = NULL; + } + + if (cprs->worker) { + pstream = (z_stream *) cprs->worker; + if ((cprs->compress_type == GZIP) && pstream->workspace) { + zlib_deflateEnd(pstream); + osal_free(pstream->workspace); + } + osal_free(cprs->worker); + cprs->worker = NULL; + } + + cprs->handler = NULL; + + osal_free(cprs); + } + + STP_DBG_INFO_FUNC("destroy OK\n"); + + return 0; +} + +/* wcn_compressor_in - put in a raw data, and compress L1 buffer if need + * @ cprs - compressor's pointer + * @ buf - raw data buffer + * @ len - raw data length + * @ finish - core dump finish or not, 1: finished; 0: not finish + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_in(P_WCN_COMPRESSOR_T cprs, PUINT8 buf, INT32 len, INT32 finish) +{ + INT32 tmp_len = 0; + INT32 ret = 0; + + if (!cprs) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + + cprs->uncomp_size += len; + + /* check L1 buf valid space */ + if (len > (cprs->L1_buf_sz - cprs->L1_pos)) { + STP_DBG_INFO_FUNC("L1 buffer full\n"); + + if (cprs->f_compress_en && cprs->handler) { + /* need compress */ + /* compress L1 buffer, and put result to L2 buffer */ + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + ret = + cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], + &tmp_len, finish); + if (!ret) { + cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); + cprs->L2_pos += tmp_len; + if (cprs->L2_pos > cprs->L2_buf_sz) + STP_DBG_ERR_FUNC("coredump size too large(%d), L2 buf overflow\n", + cprs->L2_pos); + + if (finish) { + /* Add 8 byte suffix + === + 32 bits UNCOMPRESS SIZE + 32 bits CRC + */ + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; + cprs->L2_pos += 8; + } + STP_DBG_INFO_FUNC("compress OK!\n"); + } else + STP_DBG_ERR_FUNC("compress error!\n"); + } else { + /* no need compress */ + /* Flush L1 buffer to L2 buffer */ + STP_DBG_INFO_FUNC("No need do compress, Put to L2 buf\n"); + + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; + osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); + cprs->L2_pos += tmp_len; + } + + /* reset L1 buf pos */ + cprs->L1_pos = 0; + + /* put curren data to L1 buf */ + if (len > cprs->L1_buf_sz) { + STP_DBG_ERR_FUNC("len=%d, too long err!\n", len); + } else { + STP_DBG_INFO_FUNC("L1 Flushed, and Put %d bytes to L1 buf\n", len); + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + } else { + /* put to L1 buffer */ + STP_DBG_INFO_FUNC("Put %d bytes to L1 buf\n", len); + + osal_memcpy(&cprs->L1_buf[cprs->L1_pos], buf, len); + cprs->L1_pos += len; + } + + return ret; +} + +/* wcn_compressor_out - get the result data from L2 buffer + * @ cprs - compressor's pointer + * @ pbuf - point to L2 buffer + * @ plen - out len + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_out(P_WCN_COMPRESSOR_T cprs, PUINT8 *pbuf, PINT32 plen) +{ + INT32 ret = 0; + INT32 tmp_len = 0; + + if ((!cprs) || (!pbuf) || (!plen)) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + /* check if there's L1 data need flush to L2 buffer */ + if (cprs->L1_pos > 0) { + tmp_len = cprs->L2_buf_sz - cprs->L2_pos; + + if (cprs->f_compress_en && cprs->handler) { + /* need compress */ + ret = + cprs->handler(cprs->worker, cprs->L1_buf, cprs->L1_pos, &cprs->L2_buf[cprs->L2_pos], + &tmp_len, 1); + + if (!ret) { + cprs->crc32 = (crc32(cprs->crc32, cprs->L1_buf, cprs->L1_pos)); + cprs->L2_pos += tmp_len; + + /* Add 8 byte suffix + === + 32 bits UNCOMPRESS SIZE + 32 bits CRC + */ + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos]) = (cprs->crc32 ^ 0xffffffffUL); + *(uint32_t *) (&cprs->L2_buf[cprs->L2_pos + 4]) = cprs->uncomp_size; + cprs->L2_pos += 8; + + STP_DBG_INFO_FUNC("compress OK!\n"); + } else { + STP_DBG_ERR_FUNC("compress error!\n"); + } + } else { + /* no need compress */ + tmp_len = (cprs->L1_pos > tmp_len) ? tmp_len : cprs->L1_pos; + osal_memcpy(&cprs->L2_buf[cprs->L2_pos], cprs->L1_buf, tmp_len); + cprs->L2_pos += tmp_len; + } + + cprs->L1_pos = 0; + } + + *pbuf = cprs->L2_buf; + *plen = cprs->L2_pos; + + STP_DBG_INFO_FUNC("0x%zx, len %d\n", (SIZE_T)*pbuf, *plen); + + return 0; +} + +/* wcn_compressor_reset - reset compressor + * @ cprs - compressor's pointer + * @ enable - enable/disable compress + * @ type - compress algorithm + * + * Retunr 0 if success, else NULL + */ +INT32 wcn_compressor_reset(P_WCN_COMPRESSOR_T cprs, UINT8 enable, WCN_COMPRESS_ALG_T type) +{ + if (!cprs) { + STP_DBG_ERR_FUNC("invalid para!\n"); + return -1; + } + + cprs->f_compress_en = enable; + /* cprs->f_compress_en = 0; // disable compress for test */ + cprs->compress_type = type; + cprs->L1_pos = 0; + cprs->L2_pos = 0; + cprs->uncomp_size = 0; + cprs->crc32 = 0xffffffffUL; + + /* zlib_deflateEnd((z_stream*)cprs->worker); */ + + STP_DBG_INFO_FUNC("OK! compress algorithm %d\n", type); + + return 0; +} + +static void stp_dbg_dump_data(unsigned char *pBuf, char *title, int len) +{ + int k = 0; + + pr_debug(" %s-len:%d\n", title, len); + + for (k = 0; k < len; k++) { + if (k % 16 == 0 && k != 0) + pr_cont("\n "); + pr_cont("0x%02x ", pBuf[k]); + } + pr_debug("--end\n"); +} + +static int _stp_dbg_enable(MTKSTP_DBG_T *stp_dbg) +{ + + unsigned long flags; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + stp_dbg->pkt_trace_no = 0; + stp_dbg->is_enable = 1; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +static int _stp_dbg_disable(MTKSTP_DBG_T *stp_dbg) +{ + + unsigned long flags; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + stp_dbg->pkt_trace_no = 0; + memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); + stp_dbg->is_enable = 0; + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +static int _stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len) +{ + unsigned long flags; + STP_DBG_HDR_T *pHdr = NULL; + char *pBuf = NULL; + unsigned int length = 0; + unsigned int internalFlag = stp_dbg->logsys->size < STP_DBG_LOG_ENTRY_NUM; + /* #ifdef CONFIG_LOG_STP_INTERNAL */ + /* Here we record log in this circle buffer, if buffer is full , + select to overlap earlier log, logic should be okay */ + internalFlag = 1; + /* #endif */ + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + if (internalFlag) { + stp_dbg->logsys->queue[stp_dbg->logsys->in].id = 0; + stp_dbg->logsys->queue[stp_dbg->logsys->in].len = len; + memset(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), + 0, ((len >= STP_DBG_LOG_ENTRY_SZ) ? (STP_DBG_LOG_ENTRY_SZ) : (len))); + memcpy(&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]), + buf, ((len >= STP_DBG_LOG_ENTRY_SZ) ? (STP_DBG_LOG_ENTRY_SZ) : (len))); + + stp_dbg->logsys->size++; + stp_dbg->logsys->size = + (stp_dbg->logsys->size > STP_DBG_LOG_ENTRY_NUM) ? STP_DBG_LOG_ENTRY_NUM : stp_dbg->logsys->size; + + if (0 != gStpDbgLogOut) { + pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]); + pBuf = (char *)&(stp_dbg->logsys->queue[stp_dbg->logsys->in].buffer[0]) + sizeof(STP_DBG_HDR_T); + length = stp_dbg->logsys->queue[stp_dbg->logsys->in].len - sizeof(STP_DBG_HDR_T); + pr_debug("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", + pHdr->sec, + pHdr->usec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + gStpDbgType[pHdr->type], pHdr->no, pHdr->len, pHdr->seq, pHdr->ack); + if (0 < length) + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", length); + } + stp_dbg->logsys->in = + (stp_dbg->logsys->in >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (stp_dbg->logsys->in + 1); + STP_DBG_DBG_FUNC("logsys size = %d, in = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->in); + } else { + STP_DBG_WARN_FUNC("logsys FULL!\n"); + } + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +int stp_gdb_notify_btm_dmp_wq(MTKSTP_DBG_T *stp_dbg) +{ + int retval = 0; +/* #ifndef CONFIG_LOG_STP_INTERNAL */ + + if (stp_dbg->btm != NULL) + retval += stp_btm_notify_wmt_dmp_wq((MTKSTP_BTM_T *) stp_dbg->btm); +/* #endif */ + + return retval; +} + +int stp_dbg_log_ctrl(unsigned int on) +{ + if (on != 0) { + gStpDbgLogOut = 1; + pr_debug("STP-DBG: enable pkt log dump out.\n"); + } else { + gStpDbgLogOut = 0; + pr_debug("STP-DBG: disable pkt log dump out.\n"); + } + return 0; +} + +int stp_dbg_dmp_in(MTKSTP_DBG_T *stp_dbg, char *buf, int len) +{ + return _stp_dbg_dmp_in(stp_dbg, buf, len); +} + +int stp_dbg_dmp_printk(MTKSTP_DBG_T *stp_dbg) +{ +#define MAX_DMP_NUM 80 + unsigned long flags; + char *pBuf = NULL; + int len = 0; + STP_DBG_HDR_T *pHdr = NULL; + UINT32 dumpSize = 0; + UINT32 inIndex = 0; + UINT32 outIndex = 0; + + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + /* Not to dequeue from loging system */ + inIndex = stp_dbg->logsys->in; + dumpSize = stp_dbg->logsys->size; + if (STP_DBG_LOG_ENTRY_NUM == dumpSize) + outIndex = inIndex; + else + outIndex = ((inIndex + STP_DBG_LOG_ENTRY_NUM) - dumpSize) % STP_DBG_LOG_ENTRY_NUM; + + if (dumpSize > MAX_DMP_NUM) { + + outIndex += (dumpSize - MAX_DMP_NUM); + outIndex %= STP_DBG_LOG_ENTRY_NUM; + dumpSize = MAX_DMP_NUM; + + } + STP_DBG_INFO_FUNC("loged packet size = %d, in(%d), out(%d)\n", dumpSize, inIndex, outIndex); + while (dumpSize > 0) { + pHdr = (STP_DBG_HDR_T *) &(stp_dbg->logsys->queue[outIndex].buffer[0]); + pBuf = &(stp_dbg->logsys->queue[outIndex].buffer[0]) + sizeof(STP_DBG_HDR_T); + len = stp_dbg->logsys->queue[outIndex].len - sizeof(STP_DBG_HDR_T); + len = len > STP_PKT_SZ ? STP_PKT_SZ : len; + pr_debug("STP-DBG:%d.%ds, %s:pT%sn(%d)l(%d)s(%d)a(%d)\n", + pHdr->sec, + pHdr->usec, + pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", + gStpDbgType[pHdr->type], pHdr->no, pHdr->len, pHdr->seq, pHdr->ack); + + if (0 < len) + stp_dbg_dump_data(pBuf, pHdr->dir == PKT_DIR_TX ? "Tx" : "Rx", len); + outIndex = (outIndex >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (outIndex + 1); + dumpSize--; + + } + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return 0; +} + +int stp_dbg_dmp_out_ex(char *buf, int *len) +{ + return stp_dbg_dmp_out(g_stp_dbg, buf, len); +} + +int stp_dbg_dmp_out(MTKSTP_DBG_T *stp_dbg, char *buf, int *len) +{ + + unsigned long flags; + int remaining = 0; + *len = 0; + spin_lock_irqsave(&(stp_dbg->logsys->lock), flags); + + if (stp_dbg->logsys->size > 0) { + memcpy(buf, &(stp_dbg->logsys->queue[stp_dbg->logsys->out].buffer[0]), + stp_dbg->logsys->queue[stp_dbg->logsys->out].len); + + (*len) = stp_dbg->logsys->queue[stp_dbg->logsys->out].len; + stp_dbg->logsys->out = + (stp_dbg->logsys->out >= (STP_DBG_LOG_ENTRY_NUM - 1)) ? (0) : (stp_dbg->logsys->out + 1); + stp_dbg->logsys->size--; + + STP_DBG_DBG_FUNC("logsys size = %d, out = %d\n", stp_dbg->logsys->size, stp_dbg->logsys->out); + } else { + STP_DBG_LOUD_FUNC("logsys EMPTY!\n"); + } + + remaining = (stp_dbg->logsys->size == 0) ? (0) : (1); + + spin_unlock_irqrestore(&(stp_dbg->logsys->lock), flags); + + return remaining; +} + +static int stp_dbg_fill_hdr(struct stp_dbg_pkt_hdr *hdr, int type, int ack, int seq, int crc, int dir, int len, + int dbg_type) +{ + + struct timeval now; + + if (!hdr) { + STP_DBG_ERR_FUNC("function invalid\n"); + return -EINVAL; + } + do_gettimeofday(&now); + hdr->dbg_type = dbg_type; + hdr->ack = ack; + hdr->seq = seq; + hdr->sec = now.tv_sec; + hdr->usec = now.tv_usec; + hdr->crc = crc; + hdr->dir = dir; /* rx */ + hdr->dmy = 0xffffffff; + hdr->len = len; + hdr->type = type; + return 0; + +} + +static int stp_dbg_add_pkt(MTKSTP_DBG_T *stp_dbg, struct stp_dbg_pkt_hdr *hdr, const unsigned char *body) +{ + /* fix the frame size large issues. */ + static struct stp_dbg_pkt stp_pkt; + uint32_t hdr_sz = sizeof(struct stp_dbg_pkt_hdr); + uint32_t body_sz = 0; + + BUG_ON(!stp_dbg); + + if (hdr->dbg_type == STP_DBG_PKT) + body_sz = (hdr->len <= STP_PKT_SZ) ? (hdr->len) : (STP_PKT_SZ); + else + body_sz = (hdr->len <= STP_DMP_SZ) ? (hdr->len) : (STP_DMP_SZ); + + hdr->no = stp_dbg->pkt_trace_no++; + memcpy((uint8_t *) &stp_pkt.hdr, (uint8_t *) hdr, hdr_sz); + if (body != NULL) + memcpy((uint8_t *) &stp_pkt.raw[0], body, body_sz); + + _stp_dbg_dmp_in(stp_dbg, (char *)&stp_pkt, hdr_sz + body_sz); + /* Only FW DMP MSG should inform BTM-CORE to dump packet to native process */ + if (hdr->dbg_type == STP_DBG_FW_DMP) + stp_gdb_notify_btm_dmp_wq(stp_dbg); + + return 0; +} + +int stp_dbg_log_pkt(MTKSTP_DBG_T *stp_dbg, int dbg_type, + int type, int ack_no, int seq_no, int crc, int dir, int len, const unsigned char *body) +{ + + struct stp_dbg_pkt_hdr hdr; + + if (stp_dbg->is_enable == 0) { + /*dbg is disable,and not to log */ + } else { + hdr.no = 0; + hdr.chs = 0; + stp_dbg_fill_hdr(&hdr, + (int)type, (int)ack_no, (int)seq_no, (int)crc, (int)dir, (int)len, (int)dbg_type); + + stp_dbg_add_pkt(stp_dbg, &hdr, body); + } + + return 0; +} + +int stp_dbg_enable(MTKSTP_DBG_T *stp_dbg) +{ + return _stp_dbg_enable(stp_dbg); +} + +int stp_dbg_disable(MTKSTP_DBG_T *stp_dbg) +{ + return _stp_dbg_disable(stp_dbg); +} + +static void stp_dbg_nl_init(void) +{ +#if 0 + if (genl_register_family(&stp_dbg_gnl_family) != 0) { + STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__); + } else { + if (genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_bind) != 0) + STP_DBG_ERR_FUNC("%s(): BIND operation registration fail\n", __func__); + + if (genl_register_ops(&stp_dbg_gnl_family, &stp_dbg_gnl_ops_reset) != 0) + STP_DBG_ERR_FUNC("%s(): RESET operation registration fail\n", __func__); + + } +#endif + if (genl_register_family_with_ops(&stp_dbg_gnl_family, stp_dbg_gnl_ops_array) != 0) + STP_DBG_ERR_FUNC("%s(): GE_NELINK family registration fail\n", __func__); +} + +static void stp_dbg_nl_deinit(void) +{ + genl_unregister_family(&stp_dbg_gnl_family); +} + +static int stp_dbg_nl_bind(struct sk_buff *skb, struct genl_info *info) +{ + struct nlattr *na; + char *mydata; + + if (info == NULL) + goto out; + + STP_DBG_INFO_FUNC("%s():->\n", __func__); + + na = info->attrs[STP_DBG_ATTR_MSG]; + + if (na) + mydata = (char *)nla_data(na); + + if (num_bind_process < MAX_BIND_PROCESS) { + bind_pid[num_bind_process] = info->snd_portid; + num_bind_process++; + STP_DBG_INFO_FUNC("%s():-> pid = %d\n", __func__, info->snd_portid); + } else { + STP_DBG_ERR_FUNC("%s(): exceeding binding limit %d\n", __func__, MAX_BIND_PROCESS); + } + +out: + return 0; +} + +static int stp_dbg_nl_reset(struct sk_buff *skb, struct genl_info *info) +{ + STP_DBG_ERR_FUNC("%s(): should not be invoked\n", __func__); + + return 0; +} + +INT8 stp_dbg_nl_send(PINT8 aucMsg, UINT8 cmd, INT32 len) +{ + struct sk_buff *skb = NULL; + void *msg_head = NULL; + int rc = -1; + int i; + + if (num_bind_process == 0) { + /* no listening process */ + STP_DBG_ERR_FUNC("%s(): the process is not invoked\n", __func__); + return 0; + } + + for (i = 0; i < num_bind_process; i++) { + skb = genlmsg_new(2048, GFP_KERNEL); + + if (skb) { + msg_head = genlmsg_put(skb, 0, stp_dbg_seqnum++, &stp_dbg_gnl_family, 0, cmd); + if (msg_head == NULL) { + nlmsg_free(skb); + STP_DBG_ERR_FUNC("%s(): genlmsg_put fail...\n", __func__); + return -1; + } + + rc = nla_put(skb, STP_DBG_ATTR_MSG, len, aucMsg); + if (rc != 0) { + nlmsg_free(skb); + STP_DBG_ERR_FUNC("%s(): nla_put_string fail...%d\n", __func__, rc); + return -1; + } + + /* finalize the message */ + genlmsg_end(skb, msg_head); + + /* sending message */ + rc = genlmsg_unicast(&init_net, skb, bind_pid[i]); + if (rc != 0) { + STP_DBG_ERR_FUNC("%s(): genlmsg_unicast fail...\n", __func__); + return -1; + } + } else { + STP_DBG_ERR_FUNC("%s(): genlmsg_new fail...\n", __func__); + return -1; + } + } + + return 0; +} + +INT32 stp_dbg_aee_send(unsigned char *aucMsg, INT32 len, INT32 cmd) +{ + INT32 ret = 0; + + /* buffered to compressor */ + ret = wcn_core_dump_in(g_core_dump, aucMsg, len); + if (ret == 1) + wcn_core_dump_flush(0, MTK_WCN_BOOL_FALSE); + + return ret; +} + +UINT8 *_stp_dbg_id_to_task(UINT32 id) +{ + UINT8 *taskStr[] = { + "Task_WMT", + "Task_BT", + "Task_Wifi", + "Task_Tst", + "Task_FM", + "Task_Idle", + "Task_DrvStp", + "Task_DrvBtif", + "Task_NatBt" + }; + return taskStr[id]; +} + +INT32 _stp_dbg_parser_assert_str(PINT8 str, ENUM_ASSERT_INFO_PARSER_TYPE type) +{ + char *pStr = NULL; + char *pDtr = NULL; + char *pTemp = NULL; + char *pTemp2 = NULL; + char tempBuf[64] = { 0 }; + UINT32 len = 0; + long res; + INT32 ret; + + PUINT8 parser_sub_string[] = { + " ", + "id=", + "isr=", + "irq=", + "rc=" + }; + + if (!str) { + STP_DBG_ERR_FUNC("NULL string source\n"); + return -1; + } + + if (!g_stp_dbg_cpupcr) { + STP_DBG_ERR_FUNC("NULL pointer\n"); + return -2; + } + + pStr = str; + STP_DBG_DBG_FUNC("source infor:%s\n", pStr); + switch (type) { + case STP_DBG_ASSERT_INFO: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (NULL != pDtr) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ' '); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + len = pTemp - pDtr; + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], "assert@", osal_strlen("assert@")); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@")], pDtr, len); + g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len] = '_'; + + pTemp = osal_strchr(pDtr, '#'); + pTemp += 1; + + pTemp2 = osal_strchr(pTemp, ' '); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1], pTemp, pTemp2 - pTemp); + g_stp_dbg_cpupcr->assert_info[osal_strlen("assert@") + len + 1 + pTemp2 - pTemp] = '\0'; + STP_DBG_INFO_FUNC("assert info:%s\n", &g_stp_dbg_cpupcr->assert_info[0]); + break; + case STP_DBG_FW_TASK_ID: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (NULL != pDtr) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ' '); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_ERR_FUNC("get fw task id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; + + STP_DBG_INFO_FUNC("fw task id :%x\n", (UINT32)res); + break; + case STP_DBG_FW_ISR: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (NULL != pDtr) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_ERR_FUNC("get fw isr id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwIsr = (UINT32)res; + + STP_DBG_INFO_FUNC("fw isr str:%x\n", (UINT32)res); + break; + case STP_DBG_FW_IRQ: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (NULL != pDtr) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_ERR_FUNC("get fw irq id fail(%d)\n", ret); + return -4; + } + g_stp_dbg_cpupcr->fwRrq = (UINT32)res; + + STP_DBG_INFO_FUNC("fw irq value:%x\n", (UINT32)res); + break; + case STP_DBG_ASSERT_TYPE: + pDtr = osal_strstr(pStr, parser_sub_string[type]); + if (NULL != pDtr) { + pDtr += osal_strlen(parser_sub_string[type]); + pTemp = osal_strchr(pDtr, ','); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(%s)\n", parser_sub_string[type]); + return -3; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + + if (0 == osal_memcmp(tempBuf, "*", len)) + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "general assert", osal_strlen("general assert")); + if (0 == osal_memcmp(tempBuf, "Watch Dog Timeout", len)) + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], "wdt", osal_strlen("wdt")); + if (0 == osal_memcmp(tempBuf, "RB_FULL", osal_strlen("RB_FULL"))) { + osal_memcpy(&g_stp_dbg_cpupcr->assert_type[0], tempBuf, len); + + pDtr = osal_strstr(&g_stp_dbg_cpupcr->assert_type[0], "RB_FULL("); + if (NULL != pDtr) { + pDtr += osal_strlen("RB_FULL("); + pTemp = osal_strchr(pDtr, ')'); + } else { + STP_DBG_ERR_FUNC("parser str is NULL,substring(RB_FULL()\n"); + return -4; + } + len = pTemp - pDtr; + osal_memcpy(&tempBuf[0], pDtr, len); + tempBuf[len] = '\0'; + ret = osal_strtol(tempBuf, 16, &res); + if (ret) { + STP_DBG_ERR_FUNC("get fw task id fail(%d)\n", ret); + return -5; + } + g_stp_dbg_cpupcr->fwTaskId = (UINT32)res; + + STP_DBG_INFO_FUNC("update fw task id :%x\n", (UINT32)res); + } + + STP_DBG_INFO_FUNC("fw asert type:%s\n", g_stp_dbg_cpupcr->assert_type); + break; + default: + STP_DBG_ERR_FUNC("unknown parser type\n"); + break; + } + + return 0; +} + +P_STP_DBG_CPUPCR_T stp_dbg_cpupcr_init(VOID) +{ + P_STP_DBG_CPUPCR_T pSdCpupcr = NULL; + + pSdCpupcr = (P_STP_DBG_CPUPCR_T) osal_malloc(osal_sizeof(STP_DBG_CPUPCR_T)); + if (!pSdCpupcr) { + STP_DBG_ERR_FUNC("stp dbg cpupcr allocate memory fail!\n"); + return NULL; + } + + osal_memset(pSdCpupcr, 0, osal_sizeof(STP_DBG_CPUPCR_T)); + + osal_sleepable_lock_init(&pSdCpupcr->lock); + + return pSdCpupcr; +} + +P_STP_DBG_DMAREGS_T stp_dbg_dmaregs_init(VOID) +{ + P_STP_DBG_DMAREGS_T pDmaRegs = NULL; + + pDmaRegs = (P_STP_DBG_DMAREGS_T) osal_malloc(osal_sizeof(STP_DBG_DMAREGS_T)); + if (!pDmaRegs) { + STP_DBG_ERR_FUNC("stp dbg dmareg allocate memory fail!\n"); + return NULL; + } + + osal_memset(pDmaRegs, 0, osal_sizeof(STP_DBG_DMAREGS_T)); + + osal_sleepable_lock_init(&pDmaRegs->lock); + + return pDmaRegs; +} + +VOID stp_dbg_cpupcr_deinit(P_STP_DBG_CPUPCR_T pCpupcr) +{ + if (pCpupcr) { + osal_sleepable_lock_deinit(&pCpupcr->lock); + osal_free(pCpupcr); + pCpupcr = NULL; + } +} + +VOID stp_dbg_dmaregs_deinit(P_STP_DBG_DMAREGS_T pDmaRegs) +{ + if (pDmaRegs) { + osal_sleepable_lock_deinit(&pDmaRegs->lock); + osal_free(pDmaRegs); + pDmaRegs = NULL; + } +} + +INT32 stp_dbg_poll_cpupcr(UINT32 times, UINT32 sleep, UINT32 cmd) +{ + INT32 i = 0; + + if (!g_stp_dbg_cpupcr) { + STP_DBG_ERR_FUNC("NULL reference pointer\n"); + return -1; + } + + if (!cmd) { + if (g_stp_dbg_cpupcr->count + times > STP_DBG_CPUPCR_NUM) + times = STP_DBG_CPUPCR_NUM - g_stp_dbg_cpupcr->count; + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + for (i = 0; i < times; i++) { + STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n", i, wmt_plat_read_cpupcr()); + /* osal_memcpy( + * &g_stp_dbg_cpupcr->buffer[i], + * (UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)), + * osal_sizeof(UINT32)); + */ + g_stp_dbg_cpupcr->buffer[g_stp_dbg_cpupcr->count + i] = wmt_plat_read_cpupcr(); + osal_sleep_ms(sleep); + } + g_stp_dbg_cpupcr->count += times; + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_INFO_FUNC("stp-dbg: for proc test polling cpupcr\n"); + if (times > STP_DBG_CPUPCR_NUM) + times = STP_DBG_CPUPCR_NUM; + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->count = 0; + for (i = 0; i < times; i++) { + STP_DBG_INFO_FUNC("i:%d,cpupcr:%08x\n", i, wmt_plat_read_cpupcr()); + /* osal_memcpy( + * &g_stp_dbg_cpupcr->buffer[i], + * (UINT8*)(CONSYS_REG_READ(CONSYS_CPUPCR_REG)), + * osal_sizeof(UINT32)); + */ + g_stp_dbg_cpupcr->buffer[i] = wmt_plat_read_cpupcr(); + osal_sleep_ms(sleep); + } + g_stp_dbg_cpupcr->count = times; + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + } + return 0; +} + +INT32 stp_dbg_poll_dmaregs(UINT32 times, UINT32 sleep) +{ +#if 0 + INT32 i = 0; + + if (!g_stp_dbg_dmaregs) { + STP_DBG_ERR_FUNC("NULL reference pointer\n"); + return -1; + } + + osal_lock_sleepable_lock(&g_stp_dbg_dmaregs->lock); + + if (g_stp_dbg_dmaregs->count + times > STP_DBG_DMAREGS_NUM) { + if (g_stp_dbg_dmaregs->count > STP_DBG_DMAREGS_NUM) { + STP_DBG_ERR_FUNC("g_stp_dbg_dmaregs->count:%d must less than STP_DBG_DMAREGS_NUM:%d\n", + g_stp_dbg_dmaregs->count, STP_DBG_DMAREGS_NUM); + g_stp_dbg_dmaregs->count = 0; + STP_DBG_ERR_FUNC("g_stp_dbg_dmaregs->count be set default value 0\n"); + } + times = STP_DBG_DMAREGS_NUM - g_stp_dbg_dmaregs->count; + } + if (times > STP_DBG_DMAREGS_NUM) { + STP_DBG_ERR_FUNC("times overflow, set default value:0\n"); + times = 0; + } + STP_DBG_WARN_FUNC("---------Now Polling DMA relative Regs -------------\n"); + for (i = 0; i < times; i++) { + INT32 k = 0; + + for (; k < DMA_REGS_MAX; k++) { + STP_DBG_WARN_FUNC("times:%d,i:%d reg: %s, regs:%08x\n", times, i, dmaRegsStr[k], + wmt_plat_read_dmaregs(k)); + /* g_stp_dbg_dmaregs->dmaIssue[k][g_stp_dbg_dmaregs->count + i] = wmt_plat_read_dmaregs(k); */ + } + osal_sleep_ms(sleep); + } + STP_DBG_WARN_FUNC("---------Polling DMA relative Regs End-------------\n"); + g_stp_dbg_dmaregs->count += times; + + osal_unlock_sleepable_lock(&g_stp_dbg_dmaregs->lock); +#else + return 0; +#endif +} + +INT32 stp_dbg_poll_cuppcr_ctrl(UINT32 en) +{ + + STP_DBG_INFO_FUNC("%s polling cpupcr\n", en == 0 ? "start" : "stop"); + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->stop_flag = en; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + return 0; +} + +INT32 stp_dbg_set_version_info(UINT32 chipid, UINT8 *pRomVer, UINT8 *pPatchVer, UINT8 *pPatchBrh) +{ + if (g_stp_dbg_cpupcr) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->chipId = chipid; + + if (pRomVer) + osal_memcpy(g_stp_dbg_cpupcr->romVer, pRomVer, 2); + if (pPatchVer) + osal_memcpy(g_stp_dbg_cpupcr->patchVer, pPatchVer, 8); + if (pPatchBrh) + osal_memcpy(g_stp_dbg_cpupcr->branchVer, pPatchBrh, 4); + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_ERR_FUNC("NULL pointer\n"); + return -1; + } + STP_DBG_INFO_FUNC("chipid(0x%x),romver(%s),patchver(%s),branchver(%s)\n", g_stp_dbg_cpupcr->chipId, + &g_stp_dbg_cpupcr->romVer[0], &g_stp_dbg_cpupcr->patchVer[0], &g_stp_dbg_cpupcr->branchVer[0]); + return 0; +} +INT32 stp_dbg_set_wifiver(UINT32 wifiver) +{ + if (g_stp_dbg_cpupcr) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + g_stp_dbg_cpupcr->wifiVer = wifiver; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_ERR_FUNC("NULL pointer\n"); + return -1; + } + STP_DBG_INFO_FUNC("wifiver(%x)\n", g_stp_dbg_cpupcr->wifiVer); + return 0; +} + +INT32 stp_dbg_set_host_assert_info(UINT32 drv_type, UINT32 reason, UINT32 en) +{ + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + g_stp_dbg_cpupcr->host_assert_info.assert_from_host = en; + g_stp_dbg_cpupcr->host_assert_info.drv_type = drv_type; + g_stp_dbg_cpupcr->host_assert_info.reason = reason; + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + return 0; +} + +UINT32 stp_dbg_get_host_trigger_assert(VOID) +{ + return g_stp_dbg_cpupcr->host_assert_info.assert_from_host; +} + +INT32 stp_dbg_set_fw_info(UINT8 *issue_info, UINT32 len, ENUM_STP_FW_ISSUE_TYPE issue_type) +{ + ENUM_ASSERT_INFO_PARSER_TYPE type_index; + PUINT8 tempbuf = NULL; + UINT32 i = 0; + INT32 iRet = 0; + + if (NULL == issue_info) { + STP_DBG_ERR_FUNC("null issue infor\n"); + return -1; + } + STP_DBG_INFO_FUNC("issue type(%d)\n", issue_type); + g_stp_dbg_cpupcr->issue_type = issue_type; + osal_memset(&g_stp_dbg_cpupcr->assert_info[0], 0, STP_ASSERT_INFO_SIZE); + + /*print patch version when assert happened */ + STP_DBG_INFO_FUNC("=======================================\n"); + STP_DBG_INFO_FUNC("[consys patch]patch version:%s\n", g_stp_dbg_cpupcr->patchVer); + STP_DBG_INFO_FUNC("[consys patch]ALPS branch:%s\n", g_stp_dbg_cpupcr->branchVer); + STP_DBG_INFO_FUNC("=======================================\n"); + + if ((STP_FW_ASSERT_ISSUE == issue_type) || + (STP_HOST_TRIGGER_FW_ASSERT == issue_type) || (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type)) { + if ((STP_FW_ASSERT_ISSUE == issue_type) || (STP_HOST_TRIGGER_FW_ASSERT == issue_type)) { + tempbuf = osal_malloc(len + 1); + if (!tempbuf) + return -2; + + osal_memcpy(&tempbuf[0], issue_info, len); + + for (i = 0; i < len; i++) { + if (tempbuf[i] == '\0') + tempbuf[i] = '?'; + } + + tempbuf[len] = '\0'; + + for (type_index = STP_DBG_ASSERT_INFO; type_index < STP_DBG_PARSER_TYPE_MAX; type_index++) + iRet += _stp_dbg_parser_assert_str(&tempbuf[0], type_index); + + if (iRet) + STP_DBG_ERR_FUNC("passert assert infor fail(%d)\n", iRet); + + } + if ((STP_HOST_TRIGGER_FW_ASSERT == issue_type) || (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type)) { + switch (g_stp_dbg_cpupcr->host_assert_info.drv_type) { + case 0: + STP_DBG_INFO_FUNC("BT trigger assert\n"); + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + if (31 != g_stp_dbg_cpupcr->host_assert_info.reason) + /*BT firmware trigger assert */ + { + g_stp_dbg_cpupcr->fwTaskId = 1; + + } else + /*BT stack trigger assert */ + { + g_stp_dbg_cpupcr->fwTaskId = 8; + } + + g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0; + /* g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; */ + /* g_stp_dbg_cpupcr->host_assert_info.reason = 0; */ + + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + break; + case 4: + STP_DBG_INFO_FUNC("WMT trigger assert\n"); + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + if (STP_HOST_TRIGGER_ASSERT_TIMEOUT == issue_type) + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + + if ((38 == g_stp_dbg_cpupcr->host_assert_info.reason) || + (39 == g_stp_dbg_cpupcr->host_assert_info.reason) || + (40 == g_stp_dbg_cpupcr->host_assert_info.reason)) + g_stp_dbg_cpupcr->fwTaskId = 6; /* HOST schedule reason trigger */ + else + g_stp_dbg_cpupcr->fwTaskId = 0; /* Must be firmware reason */ + g_stp_dbg_cpupcr->host_assert_info.assert_from_host = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + break; + default: + break; + } + + } + osal_free(tempbuf); + } else if (STP_FW_NOACK_ISSUE == issue_type) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = 6; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else if (STP_DBG_PROC_TEST == issue_type) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = 0; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else if (STP_FW_WARM_RST_ISSUE == issue_type) { + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memcpy(&g_stp_dbg_cpupcr->assert_info[0], issue_info, len); + g_stp_dbg_cpupcr->fwTaskId = 0; + g_stp_dbg_cpupcr->fwRrq = 0; + g_stp_dbg_cpupcr->fwIsr = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + } else { + STP_DBG_ERR_FUNC("invalid issue type(%d)\n", issue_type); + return -3; + } + + return iRet; +} + +INT32 stp_dbg_cpupcr_infor_format(PPUINT8 buf, PUINT32 str_len) +{ + UINT32 len = 0; + UINT32 i = 0; + + if (!g_stp_dbg_cpupcr) { + STP_DBG_ERR_FUNC("NULL pointer\n"); + return -1; + } + + /*format common information about issue */ + len = osal_sprintf(*buf, "
\n\t"); + len += osal_sprintf(*buf + len, "\n\t\tMT%x\n\t\n\t", g_stp_dbg_cpupcr->chipId); + len += osal_sprintf(*buf + len, "\n\t\t"); + len += osal_sprintf(*buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->romVer); + if (!(osal_memcmp(g_stp_dbg_cpupcr->branchVer, "ALPS", strlen("ALPS")))) + len += osal_sprintf(*buf + len, "Internal Dev\n\t\t", g_stp_dbg_cpupcr->branchVer); + else + len += osal_sprintf(*buf + len, "W%sMP\n\t\t", g_stp_dbg_cpupcr->branchVer); + + len += osal_sprintf(*buf + len, "%s\n\t\t", g_stp_dbg_cpupcr->patchVer); + + if (0 == g_stp_dbg_cpupcr->wifiVer) + len += osal_sprintf(*buf + len, "NULL\n\t"); + else + len += osal_sprintf(*buf + len, "0x%X.%X\n\t", + (UINT8)((g_stp_dbg_cpupcr->wifiVer & 0xFF00)>>8), (UINT8)(g_stp_dbg_cpupcr->wifiVer & 0xFF)); + + len += osal_sprintf(*buf + len, "\n\t"); + + /*format issue information: no ack, assert */ + len += osal_sprintf(*buf + len, "\n\t\t\n\t\t\t"); + if ((STP_FW_NOACK_ISSUE == g_stp_dbg_cpupcr->issue_type) || + (STP_DBG_PROC_TEST == g_stp_dbg_cpupcr->issue_type) || + (STP_FW_WARM_RST_ISSUE == g_stp_dbg_cpupcr->issue_type)) { + len += + osal_sprintf(*buf + len, "%s\n\t\t\n\t\t\n\t\t\t", + g_stp_dbg_cpupcr->assert_info); + len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n\t"); + len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t"); + len += + osal_sprintf(*buf + len, "\n\t\t\t%s\n\t\t\t", + _stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); + len += osal_sprintf(*buf + len, "IRQ_0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwRrq); + len += osal_sprintf(*buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + } else if ((STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type) || + (STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type) || + (STP_HOST_TRIGGER_ASSERT_TIMEOUT == g_stp_dbg_cpupcr->issue_type)) { + len += + osal_sprintf(*buf + len, "%s\n\t\t\n\t\t\n\t\t\t", + g_stp_dbg_cpupcr->assert_info); + len += osal_sprintf(*buf + len, "%s\n\t\t\n\t\n\t", g_stp_dbg_cpupcr->assert_type); + len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t"); + len += + osal_sprintf(*buf + len, "\n\t\t\t%s\n\t\t\t", + _stp_dbg_id_to_task(g_stp_dbg_cpupcr->fwTaskId)); + if (32 == g_stp_dbg_cpupcr->host_assert_info.reason || 33 == g_stp_dbg_cpupcr->host_assert_info.reason + || 34 == g_stp_dbg_cpupcr->host_assert_info.reason + || 35 == g_stp_dbg_cpupcr->host_assert_info.reason + || 36 == g_stp_dbg_cpupcr->host_assert_info.reason + || 37 == g_stp_dbg_cpupcr->host_assert_info.reason + || 38 == g_stp_dbg_cpupcr->host_assert_info.reason + || 39 == g_stp_dbg_cpupcr->host_assert_info.reason + || 40 == g_stp_dbg_cpupcr->host_assert_info.reason) { + /*handling wmt turn on/off bt cmd has ack but no evt issue */ + /*one of both the irqx and irs is nULL, then use task to find MOF */ + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + } else { + len += osal_sprintf(*buf + len, "IRQ_0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwRrq); + } + len += osal_sprintf(*buf + len, "0x%x\n\t\t\t", g_stp_dbg_cpupcr->fwIsr); + + if (STP_FW_ASSERT_ISSUE == g_stp_dbg_cpupcr->issue_type) { + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + } + + if ((STP_HOST_TRIGGER_FW_ASSERT == g_stp_dbg_cpupcr->issue_type) || + (STP_HOST_TRIGGER_ASSERT_TIMEOUT == g_stp_dbg_cpupcr->issue_type)) { + len += + osal_sprintf(*buf + len, "%d\n\t\t\t", + g_stp_dbg_cpupcr->host_assert_info.drv_type); + len += + osal_sprintf(*buf + len, "%d\n\t\t\t", + g_stp_dbg_cpupcr->host_assert_info.reason); + } + } else { + len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\t\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n\t"); + len += osal_sprintf(*buf + len, "\n\t\tNULL\n\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t"); + len += osal_sprintf(*buf + len, "\n\t\t\tNULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\t"); + } + + len += osal_sprintf(*buf + len, ""); + STP_DBG_INFO_FUNC("stp-dbg:sub len1 for debug(%d)\n", len); + + if (!g_stp_dbg_cpupcr->count) + len += osal_sprintf(*buf + len, "NULL"); + else { + for (i = 0; i < g_stp_dbg_cpupcr->count; i++) + len += osal_sprintf(*buf + len, "%08x,", g_stp_dbg_cpupcr->buffer[i]); + } + STP_DBG_INFO_FUNC("stp-dbg:sub len2 for debug(%d)\n", len); + len += osal_sprintf(*buf + len, "\n\t\t\t"); + len += osal_sprintf(*buf + len, "NULL\n\t\t\n\t\n
\n"); + STP_DBG_INFO_FUNC("buffer len[%d]\n", len); + /* STP_DBG_INFO_FUNC("Format infor:\n%s\n",*buf); */ + *str_len = len; + + osal_lock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + osal_memset(&g_stp_dbg_cpupcr->buffer[0], 0, STP_DBG_CPUPCR_NUM); + g_stp_dbg_cpupcr->count = 0; + g_stp_dbg_cpupcr->host_assert_info.reason = 0; + g_stp_dbg_cpupcr->host_assert_info.drv_type = 0; + osal_unlock_sleepable_lock(&g_stp_dbg_cpupcr->lock); + + return 0; + +} + +MTKSTP_DBG_T *stp_dbg_init(void *btm_half) +{ + + MTKSTP_DBG_T *stp_dbg = NULL; + + STP_DBG_INFO_FUNC("stp-dbg init\n"); + + stp_dbg = kzalloc(sizeof(MTKSTP_DBG_T), GFP_KERNEL); + if (stp_dbg == NULL) + goto ERR_EXIT1; + if (IS_ERR(stp_dbg)) { + STP_DBG_ERR_FUNC("-ENOMEM\n"); + goto ERR_EXIT1; + } + + stp_dbg->logsys = vmalloc(sizeof(MTKSTP_LOG_SYS_T)); + if (stp_dbg->logsys == NULL) + goto ERR_EXIT2; + if (IS_ERR(stp_dbg->logsys)) { + STP_DBG_ERR_FUNC("-ENOMEM stp_gdb->logsys\n"); + goto ERR_EXIT2; + } + memset(stp_dbg->logsys, 0, sizeof(MTKSTP_LOG_SYS_T)); + spin_lock_init(&(stp_dbg->logsys->lock)); + stp_dbg->pkt_trace_no = 0; + stp_dbg->is_enable = 0; + g_stp_dbg = stp_dbg; + + if (btm_half != NULL) + stp_dbg->btm = btm_half; + else + stp_dbg->btm = NULL; + + + /* bind to netlink */ + stp_dbg_nl_init(); + g_core_dump = wcn_core_dump_init(STP_CORE_DUMP_INIT_SIZE, STP_CORE_DUMP_TIMEOUT); + g_stp_dbg_cpupcr = stp_dbg_cpupcr_init(); + g_stp_dbg_dmaregs = stp_dbg_dmaregs_init(); + + return stp_dbg; + +ERR_EXIT2: + kfree(stp_dbg); + return NULL; + +ERR_EXIT1: + kfree(stp_dbg); + return NULL; +} + +int stp_dbg_deinit(MTKSTP_DBG_T *stp_dbg) +{ + + STP_DBG_INFO_FUNC("stp-dbg deinit\n"); + + wcn_core_dump_deinit(g_core_dump); + + stp_dbg_cpupcr_deinit(g_stp_dbg_cpupcr); + stp_dbg_dmaregs_deinit(g_stp_dbg_dmaregs); + /* unbind with netlink */ + stp_dbg_nl_deinit(); + + if (stp_dbg->logsys) + vfree(stp_dbg->logsys); + + kfree(stp_dbg); + + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c new file mode 100644 index 0000000000000..f7f4aff010d4a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/stp_exp.c @@ -0,0 +1,279 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* udelay() */ + +#include + + +#include "osal_typedef.h" +#include "stp_core.h" +#include "stp_exp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static MTK_WCN_STP_IF_TX stp_uart_if_tx; +static MTK_WCN_STP_IF_TX stp_sdio_if_tx; +static MTK_WCN_STP_IF_TX stp_btif_if_tx; +static ENUM_STP_TX_IF_TYPE g_stp_if_type = STP_MAX_IF_TX; +static MTK_WCN_STP_IF_RX stp_if_rx; +static MTK_WCN_STP_EVENT_CB event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; +static MTK_WCN_STP_EVENT_CB tx_event_callback_tbl[MTKSTP_MAX_TASK_NUM] = { 0x0 }; + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +INT32 mtk_wcn_sys_if_rx(UINT8 *data, INT32 size) +{ + if (stp_if_rx == 0x0) + return -1; + + (*stp_if_rx) (data, size); + return 0; +} + +static INT32 mtk_wcn_sys_if_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size) +{ + + if (STP_UART_IF_TX == g_stp_if_type) + return stp_uart_if_tx != NULL ? (*stp_uart_if_tx) (data, size, written_size) : -1; + else if (STP_SDIO_IF_TX == g_stp_if_type) + return stp_sdio_if_tx != NULL ? (*stp_sdio_if_tx) (data, size, written_size) : -1; + else if (STP_BTIF_IF_TX == g_stp_if_type) + return stp_btif_if_tx != NULL ? (*stp_btif_if_tx) (data, size, written_size) : -1; + /*if (g_stp_if_type >= STP_MAX_IF_TX) *//* George: remove ALWAYS TRUE condition */ + return -1; +} + +static INT32 mtk_wcn_sys_event_set(UINT8 function_type) +{ + if ((function_type < MTKSTP_MAX_TASK_NUM) && (event_callback_tbl[function_type] != 0x0)) { + (*event_callback_tbl[function_type]) (); + } else { + /* FIXME: error handling */ + pr_err("[%s] STP set event fail. It seems the function is not active.\n", __func__); + } + + return 0; +} + +static INT32 mtk_wcn_sys_event_tx_resume(UINT8 winspace) +{ + int type = 0; + + for (type = 0; type < MTKSTP_MAX_TASK_NUM; type++) { + if (tx_event_callback_tbl[type]) + tx_event_callback_tbl[type] (); + } + + return 0; +} + +static INT32 mtk_wcn_sys_check_function_status(UINT8 type, UINT8 op) +{ + + /* op == FUNCTION_ACTIVE, to check if funciton[type] is active ? */ + if (!(type < MTKSTP_MAX_TASK_NUM)) + return STATUS_FUNCTION_INVALID; + + if (op == OP_FUNCTION_ACTIVE) { + if (event_callback_tbl[type] != 0x0) + return STATUS_FUNCTION_ACTIVE; + else + return STATUS_FUNCTION_INACTIVE; + + } + /* you can define more operation here ..., to queury function's status/information */ + + return STATUS_OP_INVALID; +} + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +#else +INT32 mtk_wcn_stp_register_if_rx(MTK_WCN_STP_IF_RX func) +#endif +{ + stp_if_rx = func; + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_if_rx); +#endif + +VOID mtk_wcn_stp_set_if_tx_type(ENUM_STP_TX_IF_TYPE stp_if_type) +{ + static const char * const ifType[] = { + "UART", + "SDIO", + "BTIF", + "UNKNOWN" + }; + g_stp_if_type = stp_if_type; + pr_debug("[%s] set STP_IF_TX to %s.\n", __func__, ifType[stp_if_type]); +} + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) +#else +INT32 mtk_wcn_stp_register_if_tx(ENUM_STP_TX_IF_TYPE stp_if, MTK_WCN_STP_IF_TX func) +#endif +{ + if (STP_UART_IF_TX == stp_if) { + stp_uart_if_tx = func; + } else if (STP_SDIO_IF_TX == stp_if) { + stp_sdio_if_tx = func; + } else if (STP_BTIF_IF_TX == stp_if) { + stp_btif_if_tx = func; + } else { + pr_debug("[%s] STP_IF_TX(%d) out of boundary.\n", __func__, stp_if); + return -1; + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_if_tx); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#else +INT32 mtk_wcn_stp_register_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#endif +{ + if (type < MTKSTP_MAX_TASK_NUM) { + event_callback_tbl[type] = func; + + /*clear rx queue */ + pr_debug("Flush type = %d Rx Queue\n", type); + mtk_wcn_stp_flush_rx_queue(type); + } + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_event_cb); +#endif + +#if STP_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#else +INT32 mtk_wcn_stp_register_tx_event_cb(INT32 type, MTK_WCN_STP_EVENT_CB func) +#endif +{ + if (type < MTKSTP_MAX_TASK_NUM) + tx_event_callback_tbl[type] = func; + else + BUG_ON(0); + + return 0; +} +#if !STP_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_register_tx_event_cb); +#endif + +INT32 stp_drv_init(VOID) +{ + INT32 ret = 0; + + mtkstp_callback cb = { + .cb_if_tx = mtk_wcn_sys_if_tx, + .cb_event_set = mtk_wcn_sys_event_set, + .cb_event_tx_resume = mtk_wcn_sys_event_tx_resume, + .cb_check_funciton_status = mtk_wcn_sys_check_function_status + }; + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + MTK_WCN_STP_EXP_CB_INFO stpExpCb = { + .stp_send_data_cb = _mtk_wcn_stp_send_data, + .stp_send_data_raw_cb = _mtk_wcn_stp_send_data_raw, + .stp_parser_data_cb = _mtk_wcn_stp_parser_data, + .stp_receive_data_cb = _mtk_wcn_stp_receive_data, + .stp_is_rxqueue_empty_cb = _mtk_wcn_stp_is_rxqueue_empty, + .stp_is_ready_cb = _mtk_wcn_stp_is_ready, + .stp_set_bluez_cb = _mtk_wcn_stp_set_bluez, + .stp_if_tx_cb = _mtk_wcn_stp_register_if_tx, + .stp_if_rx_cb = _mtk_wcn_stp_register_if_rx, + .stp_reg_event_cb = _mtk_wcn_stp_register_event_cb, + .stp_reg_tx_event_cb = _mtk_wcn_stp_register_tx_event_cb, + .stp_coredump_start_get_cb = _mtk_wcn_stp_coredump_start_get, + }; +#endif + + ret = mtk_wcn_stp_init(&cb); +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_stp_exp_cb_reg(&stpExpCb); +#endif + return ret; +} + +VOID stp_drv_exit(VOID) +{ + mtk_wcn_stp_deinit(); + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + mtk_wcn_stp_exp_cb_unreg(); +#endif + +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c new file mode 100644 index 0000000000000..f70c88796f091 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_dev.c @@ -0,0 +1,2566 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief brief description + + Detailed descriptions here. + +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-DEV]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "osal_typedef.h" +#include "osal.h" +#include "wmt_dev.h" +#include "wmt_core.h" +#include "wmt_exp.h" +#include "wmt_lib.h" +#include "wmt_conf.h" +#include "psm_core.h" +#include "stp_core.h" +#include "stp_exp.h" +#include "bgw_desense.h" +#include +#include "wmt_idc.h" +#ifdef CONFIG_COMPAT +#include +#endif +#if WMT_CREATE_NODE_DYNAMIC +#include +#endif +#define BUF_LEN_MAX 384 +#include +#ifdef CONFIG_COMPAT +#define COMPAT_WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, compat_uptr_t) +#define COMPAT_WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, compat_uptr_t) +#define COMPAT_WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, compat_uptr_t) +#define COMPAT_WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, compat_uptr_t) +#define COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, compat_uptr_t) +#define COMPAT_WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, compat_uptr_t) +#endif + +#define WMT_IOC_MAGIC 0xa0 +#define WMT_IOCTL_SET_PATCH_NAME _IOW(WMT_IOC_MAGIC, 4, char*) +#define WMT_IOCTL_SET_STP_MODE _IOW(WMT_IOC_MAGIC, 5, int) +#define WMT_IOCTL_FUNC_ONOFF_CTRL _IOW(WMT_IOC_MAGIC, 6, int) +#define WMT_IOCTL_LPBK_POWER_CTRL _IOW(WMT_IOC_MAGIC, 7, int) +#define WMT_IOCTL_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 8, char*) +#define WMT_IOCTL_GET_CHIP_INFO _IOR(WMT_IOC_MAGIC, 12, int) +#define WMT_IOCTL_SET_LAUNCHER_KILL _IOW(WMT_IOC_MAGIC, 13, int) +#define WMT_IOCTL_SET_PATCH_NUM _IOW(WMT_IOC_MAGIC, 14, int) +#define WMT_IOCTL_SET_PATCH_INFO _IOW(WMT_IOC_MAGIC, 15, char*) +#define WMT_IOCTL_PORT_NAME _IOWR(WMT_IOC_MAGIC, 20, char*) +#define WMT_IOCTL_WMT_CFG_NAME _IOWR(WMT_IOC_MAGIC, 21, char*) +#define WMT_IOCTL_WMT_QUERY_CHIPID _IOR(WMT_IOC_MAGIC, 22, int) +#define WMT_IOCTL_WMT_TELL_CHIPID _IOW(WMT_IOC_MAGIC, 23, int) +#define WMT_IOCTL_WMT_COREDUMP_CTRL _IOW(WMT_IOC_MAGIC, 24, int) +#define WMT_IOCTL_SEND_BGW_DS_CMD _IOW(WMT_IOC_MAGIC, 25, char*) +#define WMT_IOCTL_ADIE_LPBK_TEST _IOWR(WMT_IOC_MAGIC, 26, char*) +#define WMT_IOCTL_FW_DBGLOG_CTRL _IOR(WMT_IOC_MAGIC, 29, int) +#define WMT_IOCTL_DYNAMIC_DUMP_CTRL _IOR(WMT_IOC_MAGIC, 30, char*) + +#define MTK_WMT_VERSION "SOC Consys WMT Driver - v1.0" +#define MTK_WMT_DATE "2013/01/20" +#define WMT_DEV_MAJOR 190 /* never used number */ +#define WMT_DEV_NUM 1 +#define WMT_DEV_INIT_TO_MS (2 * 1000) +#define DYNAMIC_DUMP_BUF 109 + +#if CFG_WMT_DBG_SUPPORT +#define WMT_DBG_PROCNAME "driver/wmt_dbg" +#endif + +#define WMT_DRIVER_NAME "mtk_stp_wmt" + +P_OSAL_EVENT gpRxEvent = NULL; + +UINT32 u4RxFlag = 0x0; +static atomic_t gRxCount = ATOMIC_INIT(0); + +/* Linux UINT8 device */ +static int gWmtMajor = WMT_DEV_MAJOR; +static struct cdev gWmtCdev; +static atomic_t gWmtRefCnt = ATOMIC_INIT(0); +/* WMT driver information */ +static UINT8 gLpbkBuf[1024+5] = { 0 }; + +static UINT32 gLpbkBufLog; /* George LPBK debug */ +static INT32 gWmtInitDone; +static wait_queue_head_t gWmtInitWq; + +P_WMT_PATCH_INFO pPatchInfo = NULL; +UINT32 pAtchNum = 0; + +#if (defined(CONFIG_MTK_GMO_RAM_OPTIMIZE) && !defined(CONFIG_MT_ENG_BUILD)) +#define WMT_EMI_DEBUG_BUF_SIZE (8*1024) +#else +#define WMT_EMI_DEBUG_BUF_SIZE (32*1024) +#endif + +static UINT8 gEmiBuf[WMT_EMI_DEBUG_BUF_SIZE]; +UINT8 *buf_emi; + +#if CFG_WMT_PROC_FOR_AEE +static struct proc_dir_entry *gWmtAeeEntry; +#define WMT_AEE_PROCNAME "driver/wmt_aee" +#define WMT_PROC_AEE_SIZE 3072 +static UINT32 g_buf_len; +static UINT8 *pBuf; +#endif + +#if WMT_CREATE_NODE_DYNAMIC +struct class *wmt_class = NULL; +struct device *wmt_dev = NULL; +#endif + +#if CFG_WMT_DBG_SUPPORT +static struct proc_dir_entry *gWmtDbgEntry; +COEX_BUF gCoexBuf; + +static INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd); +static INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3); + +#if CFG_CORE_INTERNAL_TXRX +static INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3); +#endif +static INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3); +static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3); +#if CONSYS_ENALBE_SET_JTAG +static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3); +#endif +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3); +#endif +#endif +static void wmt_dbg_fwinfor_print_buff(UINT32 len) +{ + UINT32 i = 0; + UINT32 idx = 0; + + for (i = 0; i < len; i++) { + buf_emi[idx] = gEmiBuf[i]; + if (gEmiBuf[i] == '\n') { + pr_cont("%s", buf_emi); + osal_memset(buf_emi, 0, BUF_LEN_MAX); + idx = 0; + } else { + idx++; + } + if (idx == BUF_LEN_MAX-1) { + buf_emi[idx] = '\0'; + pr_cont("%s", buf_emi); + osal_memset(buf_emi, 0, BUF_LEN_MAX); + idx = 0; + } + } +} + +/*LCM on/off ctrl for wmt varabile*/ +static struct work_struct gPwrOnOffWork; +UINT32 g_es_lr_flag_for_quick_sleep = 1; /* for ctrl quick sleep flag */ +UINT32 g_es_lr_flag_for_lpbk_onoff = 0; /* for ctrl lpbk on off */ +OSAL_SLEEPABLE_LOCK g_es_lr_lock; + +#ifdef CONFIG_EARLYSUSPEND + +static void wmt_dev_early_suspend(struct early_suspend *h) +{ + osal_lock_sleepable_lock(&g_es_lr_lock); + g_es_lr_flag_for_quick_sleep = 1; + g_es_lr_flag_for_lpbk_onoff = 0; + osal_unlock_sleepable_lock(&g_es_lr_lock); + + WMT_WARN_FUNC("@@@@@@@@@@wmt enter early suspend@@@@@@@@@@@@@@\n"); + + schedule_work(&gPwrOnOffWork); +} + +static void wmt_dev_late_resume(struct early_suspend *h) +{ + osal_lock_sleepable_lock(&g_es_lr_lock); + g_es_lr_flag_for_quick_sleep = 0; + g_es_lr_flag_for_lpbk_onoff = 1; + osal_unlock_sleepable_lock(&g_es_lr_lock); + + WMT_WARN_FUNC("@@@@@@@@@@wmt enter late resume@@@@@@@@@@@@@@\n"); + + schedule_work(&gPwrOnOffWork); + +} + +struct early_suspend wmt_early_suspend_handler = { + .suspend = wmt_dev_early_suspend, + .resume = wmt_dev_late_resume, +}; + +#else + +static struct notifier_block wmt_fb_notifier; +static int wmt_fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data) +{ + struct fb_event *evdata = data; + INT32 blank; + + WMT_DBG_FUNC("wmt_fb_notifier_callback\n"); + + /* If we aren't interested in this event, skip it immediately ... */ + if (event != FB_EVENT_BLANK) + return 0; + + blank = *(INT32 *)evdata->data; + WMT_DBG_FUNC("fb_notify(blank=%d)\n", blank); + + switch (blank) { + case FB_BLANK_UNBLANK: + osal_lock_sleepable_lock(&g_es_lr_lock); + g_es_lr_flag_for_quick_sleep = 0; + g_es_lr_flag_for_lpbk_onoff = 1; + osal_unlock_sleepable_lock(&g_es_lr_lock); + WMT_WARN_FUNC("@@@@@@@@@@wmt enter UNBLANK @@@@@@@@@@@@@@\n"); + schedule_work(&gPwrOnOffWork); + break; + case FB_BLANK_POWERDOWN: + osal_lock_sleepable_lock(&g_es_lr_lock); + g_es_lr_flag_for_quick_sleep = 1; + g_es_lr_flag_for_lpbk_onoff = 0; + osal_unlock_sleepable_lock(&g_es_lr_lock); + WMT_WARN_FUNC("@@@@@@@@@@wmt enter early POWERDOWN @@@@@@@@@@@@@@\n"); + schedule_work(&gPwrOnOffWork); + break; + default: + break; + } + return 0; +} +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static void wmt_pwr_on_off_handler(struct work_struct *work) +{ + INT32 retryCounter = 1; + + WMT_DBG_FUNC("wmt_pwr_on_off_handler start to run\n"); + + osal_lock_sleepable_lock(&g_es_lr_lock); + + if (g_es_lr_flag_for_lpbk_onoff) { + do { + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK)) { + WMT_WARN_FUNC("WMT turn on LPBK fail, retrying, retryCounter left:%d!\n", retryCounter); + retryCounter--; + osal_sleep_ms(1000); + } else { + WMT_INFO_FUNC("WMT turn on LPBK suceed\n"); + break; + } + } while (retryCounter > 0); + } else { + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK)) + WMT_WARN_FUNC("WMT turn off LPBK fail\n"); + else + WMT_DBG_FUNC("WMT turn off LPBK suceed\n"); + + } + + osal_unlock_sleepable_lock(&g_es_lr_lock); + +} + + +MTK_WCN_BOOL wmt_dev_get_early_suspend_state(void) +{ + MTK_WCN_BOOL bRet = (0 == g_es_lr_flag_for_quick_sleep) ? MTK_WCN_BOOL_FALSE : MTK_WCN_BOOL_TRUE; + /* WMT_INFO_FUNC("bRet:%d\n", bRet); */ + return bRet; +} + +#if CFG_WMT_DBG_SUPPORT + +static const WMT_DEV_DBG_FUNC wmt_dev_dbg_func[] = { + [0] = wmt_dbg_psm_ctrl, + [1] = wmt_dbg_quick_sleep_ctrl, + [2] = wmt_dbg_dsns_ctrl, + [3] = wmt_dbg_hwver_get, + [4] = wmt_dbg_assert_test, + [5] = wmt_dbg_inband_rst, + [6] = wmt_dbg_chip_rst, + [7] = wmt_dbg_func_ctrl, + [8] = wmt_dbg_raed_chipid, + [9] = wmt_dbg_wmt_dbg_level, + [0xa] = wmt_dbg_stp_dbg_level, + [0xb] = wmt_dbg_reg_read, + [0xc] = wmt_dbg_reg_write, + [0xd] = wmt_dbg_coex_test, + [0xe] = wmt_dbg_rst_ctrl, + [0xf] = wmt_dbg_ut_test, + [0x10] = wmt_dbg_efuse_read, + [0x11] = wmt_dbg_efuse_write, + [0x12] = wmt_dbg_sdio_ctrl, + [0x13] = wmt_dbg_stp_dbg_ctrl, + [0x14] = wmt_dbg_stp_dbg_log_ctrl, + [0x15] = wmt_dbg_wmt_assert_ctrl, + [0x16] = wmt_dbg_fwinfor_from_emi, + [0x17] = wmt_dbg_set_mcu_clock, + [0x18] = wmt_dbg_poll_cpupcr, + [0x19] = wmt_dbg_jtag_flag_ctrl, +#if CFG_WMT_LTE_COEX_HANDLING + [0x20] = wmt_dbg_lte_coex_test, +#endif +}; + +INT32 wmt_dbg_psm_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +#if CFG_WMT_PS_SUPPORT + if (0 == par2) { + wmt_lib_ps_ctrl(0); + WMT_INFO_FUNC("disable PSM\n"); + } else { + par2 = (1 > par2 || 20000 < par2) ? STP_PSM_IDLE_TIME_SLEEP : par2; + wmt_lib_ps_set_idle_time(par2); + wmt_lib_ps_ctrl(1); + WMT_WARN_FUNC("enable PSM, idle to sleep time = %d ms\n", par2); + } +#else + WMT_INFO_FUNC("WMT PS not supported\n"); +#endif + return 0; +} + +INT32 wmt_dbg_quick_sleep_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +#if CFG_WMT_PS_SUPPORT + UINT32 en_flag = par2; + + wmt_lib_quick_sleep_ctrl(en_flag); +#else + WMT_WARN_FUNC("WMT PS not supported\n"); +#endif + return 0; +} + +INT32 wmt_dbg_dsns_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (WMTDSNS_FM_DISABLE <= par2 && WMTDSNS_MAX > par2) { + WMT_INFO_FUNC("DSNS type (%d)\n", par2); + mtk_wcn_wmt_dsns_ctrl(par2); + } else { + WMT_WARN_FUNC("invalid DSNS type\n"); + } + return 0; +} + +INT32 wmt_dbg_hwver_get(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("query chip version\n"); + mtk_wcn_wmt_hwver_get(); + return 0; +} + +INT32 wmt_dbg_assert_test(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par3) { + /* par2 = 0: send assert command */ + /* par2 != 0: send exception command */ + return wmt_dbg_cmd_test_api(0 == par2 ? 0 : 1); + } else if (1 == par3) { + /* send noack command */ + return wmt_dbg_cmd_test_api(18); + } else if (2 == par3) { + /* warn reset test */ + return wmt_dbg_cmd_test_api(19); + } else if (3 == par3) { + /* firmware trace test */ + return wmt_dbg_cmd_test_api(20); + } + { + INT32 sec = 8; + INT32 times = 0; + + times = par3; + do { + WMT_INFO_FUNC("Send Assert Command per 8 secs!!\n"); + wmt_dbg_cmd_test_api(0); + osal_sleep_ms(sec * 1000); + } while (--times); + } + return 0; +} + +INT32 wmt_dbg_cmd_test_api(ENUM_WMTDRV_CMD_T cmd) +{ + + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = WMT_OPID_CMD_TEST; + + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + /*this test command should be run with usb cable connected, so no host awake is needed */ + /* wmt_lib_host_awake_get(); */ + switch (cmd) { + case WMTDRV_CMD_ASSERT: + pOp->op.au4OpData[0] = 0; + break; + case WMTDRV_CMD_EXCEPTION: + pOp->op.au4OpData[0] = 1; + break; + case WMTDRV_CMD_NOACK_TEST: + pOp->op.au4OpData[0] = 3; + break; + case WMTDRV_CMD_WARNRST_TEST: + pOp->op.au4OpData[0] = 4; + break; + case WMTDRV_CMD_FWTRACE_TEST: + pOp->op.au4OpData[0] = 5; + break; + default: + if (WMTDRV_CMD_COEXDBG_00 <= cmd && WMTDRV_CMD_COEXDBG_15 >= cmd) { + pOp->op.au4OpData[0] = 2; + pOp->op.au4OpData[1] = cmd - 2; + } else { + pOp->op.au4OpData[0] = 0xff; + pOp->op.au4OpData[1] = 0xff; + } + pOp->op.au4OpData[2] = (SIZE_T) gCoexBuf.buffer; + pOp->op.au4OpData[3] = osal_sizeof(gCoexBuf.buffer); + break; + } + WMT_INFO_FUNC("CMD_TEST, opid(%d), par(%d, %d)\n", pOp->op.opId, pOp->op.au4OpData[0], pOp->op.au4OpData[1]); + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if ((cmd != WMTDRV_CMD_ASSERT) && + (cmd != WMTDRV_CMD_EXCEPTION) && + (cmd != WMTDRV_CMD_NOACK_TEST) && (cmd != WMTDRV_CMD_WARNRST_TEST) && (cmd != WMTDRV_CMD_FWTRACE_TEST)) { + if (MTK_WCN_BOOL_FALSE == bRet) { + gCoexBuf.availSize = 0; + } else { + gCoexBuf.availSize = pOp->op.au4OpData[3]; + WMT_INFO_FUNC("gCoexBuf.availSize = %d\n", gCoexBuf.availSize); + } + } + /* wmt_lib_host_awake_put(); */ + WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", + pOp->op.opId, + pOp->op.au4OpData[0], + pOp->op.au4OpData[1], bRet, MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + return 0; +} + +INT32 wmt_dbg_inband_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par2) { + WMT_INFO_FUNC("inband reset test!!\n"); + mtk_wcn_stp_inband_reset(); + } else { + WMT_INFO_FUNC("STP context reset in host side!!\n"); + mtk_wcn_stp_flush_context(); + } + + return 0; +} + +INT32 wmt_dbg_chip_rst(INT32 par1, INT32 par2, INT32 par3) +{ + if (0 == par2) { + if (mtk_wcn_stp_is_ready()) { + WMT_INFO_FUNC("whole chip reset test\n"); + wmt_lib_cmb_rst(WMTRSTSRC_RESET_TEST); + } else { + WMT_INFO_FUNC("STP not ready , not to launch whole chip reset test\n"); + } + } else if (1 == par2) { + WMT_INFO_FUNC("chip hardware reset test\n"); + wmt_lib_hw_rst(); + } else { + WMT_INFO_FUNC("chip software reset test\n"); + wmt_lib_sw_rst(1); + } + return 0; +} + +INT32 wmt_dbg_func_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (WMTDRV_TYPE_WMT > par2 || WMTDRV_TYPE_LPBK == par2) { + if (0 == par3) { + WMT_INFO_FUNC("function off test, type(%d)\n", par2); + mtk_wcn_wmt_func_off(par2); + } else { + WMT_INFO_FUNC("function on test, type(%d)\n", par2); + mtk_wcn_wmt_func_on(par2); + } + } else { + WMT_INFO_FUNC("function ctrl test, invalid type(%d)\n", par2); + } + return 0; +} + +INT32 wmt_dbg_raed_chipid(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("chip version = %d\n", wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER)); + return 0; +} + +INT32 wmt_dbg_wmt_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (WMT_LOG_ERR <= par2 && WMT_LOG_LOUD >= par2) ? par2 : WMT_LOG_INFO; + wmt_lib_dbg_level_set(par2); + WMT_INFO_FUNC("set wmt log level to %d\n", par2); + return 0; +} + +INT32 wmt_dbg_stp_dbg_level(INT32 par1, INT32 par2, INT32 par3) +{ + par2 = (0 <= par2 && 4 >= par2) ? par2 : 2; + mtk_wcn_stp_dbg_level(par2); + WMT_INFO_FUNC("set stp log level to %d\n", par2); + return 0; + +} + +INT32 wmt_dbg_reg_read(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->register address */ + /* par3-->register mask */ + UINT32 value = 0x0; + UINT32 iRet = -1; +#if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(0, par2, &value, par3); + ENABLE_PSM_MONITOR(); +#endif + iRet = wmt_lib_reg_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip register (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); + return 0; +} + +INT32 wmt_dbg_reg_write(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->register address */ + /* par3-->value to set */ + UINT32 iRet = -1; +#if 0 + DISABLE_PSM_MONITOR(); + iRet = wmt_core_reg_rw_raw(1, par2, &par3, 0xffffffff); + ENABLE_PSM_MONITOR(); +#endif + iRet = wmt_lib_reg_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip register (0x%08x) with value (0x%08x) %s\n", + par2, par3, iRet != 0 ? "failed" : "succeed"); + return 0; +} + +INT32 wmt_dbg_efuse_read(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->efuse address */ + /* par3-->register mask */ + UINT32 value = 0x0; + UINT32 iRet = -1; + + iRet = wmt_lib_efuse_rw(0, par2, &value, par3); + WMT_INFO_FUNC("read combo chip efuse (0x%08x) with mask (0x%08x) %s, value = 0x%08x\n", + par2, par3, iRet != 0 ? "failed" : "succeed", iRet != 0 ? -1 : value); + return 0; +} + +INT32 wmt_dbg_efuse_write(INT32 par1, INT32 par2, INT32 par3) +{ + /* par2-->efuse address */ + /* par3-->value to set */ + UINT32 iRet = -1; + + iRet = wmt_lib_efuse_rw(1, par2, &par3, 0xffffffff); + WMT_INFO_FUNC("write combo chip efuse (0x%08x) with value (0x%08x) %s\n", + par2, par3, iRet != 0 ? "failed" : "succeed"); + return 0; +} + +INT32 wmt_dbg_sdio_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ +/*remove sdio card detect/remove control because of btif is used*/ +#if 0 + INT32 iRet = -1; + + iRet = wmt_lib_sdio_ctrl(0 != par2 ? 1 : 0); + WMT_INFO_FUNC("ctrl SDIO function %s\n", 0 == iRet ? "succeed" : "failed"); +#endif + return 0; +} + +INT32 wmt_dbg_stp_dbg_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + if (1 < par2) { + mtk_wcn_stp_dbg_dump_package(); + return 0; + } + WMT_INFO_FUNC("%s stp debug function\n", 0 == par2 ? "disable" : "enable"); + if (0 == par2) + mtk_wcn_stp_dbg_disable(); + else if (1 == par2) + mtk_wcn_stp_dbg_enable(); + + return 0; +} + +INT32 wmt_dbg_stp_dbg_log_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + mtk_wcn_stp_dbg_log_ctrl(0 != par2 ? 1 : 0); + return 0; +} + +INT32 wmt_dbg_wmt_assert_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + mtk_wcn_stp_coredump_flag_ctrl(0 != par2 ? 1 : 0); + return 0; +} + +INT32 wmt_dbg_fwinfor_from_emi(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 offset = 0; + UINT32 len = 0; + UINT32 *pAddr = NULL; + UINT32 cur_idx_pagedtrace; + static UINT32 prev_idx_pagedtrace; + MTK_WCN_BOOL isBreak = MTK_WCN_BOOL_TRUE; + + offset = par2; + len = par3; + + buf_emi = kmalloc(sizeof(UINT8) * BUF_LEN_MAX, GFP_KERNEL); + if (!buf_emi) { + WMT_ERR_FUNC("buf kmalloc memory fail\n"); + return 0; + } + osal_memset(buf_emi, 0, BUF_LEN_MAX); + osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); + wmt_lib_get_fwinfor_from_emi(0, offset, &gEmiBuf[0], 0x100); + + if (offset == 1) { + do { + pAddr = (PUINT32) wmt_plat_get_emi_virt_add(0x24); + cur_idx_pagedtrace = *pAddr; + + if (cur_idx_pagedtrace > prev_idx_pagedtrace) { + len = cur_idx_pagedtrace - prev_idx_pagedtrace; + wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); + wmt_dbg_fwinfor_print_buff(len); + prev_idx_pagedtrace = cur_idx_pagedtrace; + } + + if (cur_idx_pagedtrace < prev_idx_pagedtrace) { + if (prev_idx_pagedtrace >= 0x8000) { + pr_debug("++ prev_idx_pagedtrace invalid ...++\n\\n"); + prev_idx_pagedtrace = 0x8000 - 1; + continue; + } + + len = 0x8000 - prev_idx_pagedtrace - 1; + wmt_lib_get_fwinfor_from_emi(1, prev_idx_pagedtrace, &gEmiBuf[0], len); + pr_debug("\n\n -- CONNSYS paged trace ascii output (cont...) --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + + len = cur_idx_pagedtrace; + wmt_lib_get_fwinfor_from_emi(1, 0x0, &gEmiBuf[0], len); + pr_debug("\n\n -- CONNSYS paged trace ascii output (end) --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + prev_idx_pagedtrace = cur_idx_pagedtrace; + } + msleep(100); + } while (isBreak); + } + + pr_debug("\n\n -- control word --\n\n"); + wmt_dbg_fwinfor_print_buff(256); + if (len > 1024 * 4) + len = 1024 * 4; + + WMT_WARN_FUNC("get fw infor from emi at offset(0x%x),len(0x%x)\n", offset, len); + osal_memset(&gEmiBuf[0], 0, WMT_EMI_DEBUG_BUF_SIZE); + wmt_lib_get_fwinfor_from_emi(1, offset, &gEmiBuf[0], len); + + pr_debug("\n\n -- paged trace hex output --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + pr_debug("\n\n -- paged trace ascii output --\n\n"); + wmt_dbg_fwinfor_print_buff(len); + kfree(buf_emi); + return 0; +} + +INT32 wmt_dbg_coex_test(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("coexistance test cmd!!\n"); + return wmt_dbg_cmd_test_api(par2 + WMTDRV_CMD_COEXDBG_00); +} + +INT32 wmt_dbg_rst_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + WMT_INFO_FUNC("%s audo rst\n", 0 == par2 ? "disable" : "enable"); + mtk_wcn_stp_set_auto_rst(0 == par2 ? 0 : 1); + return 0; +} + +INT32 wmt_dbg_ut_test(INT32 par1, INT32 par2, INT32 par3) +{ + + INT32 i = 0; + INT32 j = 0; + INT32 iRet = 0; + + i = 20; + while ((i--) > 0) { + WMT_INFO_FUNC("#### UT WMT and STP Function On/Off .... %d\n", i); + j = 10; + while ((j--) > 0) { + WMT_INFO_FUNC("#### BT On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### GPS On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_GPS); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### FM On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_FM); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### WIFI On .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### BT Off .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### GPS Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_GPS); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### FM Off .... (%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_FM); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + WMT_INFO_FUNC("#### WIFI Off ....(%d, %d)\n", i, j); + iRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI); + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + } + if (iRet == MTK_WCN_BOOL_FALSE) + break; + + } + if (iRet == MTK_WCN_BOOL_FALSE) + WMT_INFO_FUNC("#### UT FAIL!!\n"); + else + WMT_INFO_FUNC("#### UT PASS!!\n"); + + return iRet; +} + +#if CFG_CORE_INTERNAL_TXRX + +struct lpbk_package { + long payload_length; + unsigned char out_payload[2048]; + unsigned char in_payload[2048]; +}; + +static INT32 wmt_internal_loopback(INT32 count, INT32 max) +{ + int ret = 0; + int loop; + int offset; + struct lpbk_package lpbk_buffer; + P_OSAL_OP pOp; + P_OSAL_SIGNAL pSignal = NULL; + + for (loop = 0; loop < count; loop++) { + /* <1> init buffer */ + osal_memset((void *)&lpbk_buffer, 0, sizeof(struct lpbk_package)); + lpbk_buffer.payload_length = max; + for (offset = 0; offset < max; offset++) + lpbk_buffer.out_payload[offset] = (offset + 1) /*for test use: begin from 1 */ & 0xFF; + + + memcpy(&gLpbkBuf[0], &lpbk_buffer.out_payload[0], max); + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + ret = -1; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_LPBK; + pOp->op.au4OpData[0] = lpbk_buffer.payload_length; /* packet length */ + pOp->op.au4OpData[1] = (UINT32) &gLpbkBuf[0]; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + ret = -2; + } + + ret = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == ret) { + WMT_WARN_FUNC("OPID(%d) type(%d)fail\n", pOp->op.opId, pOp->op.au4OpData[0]); + ret = -3; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + memcpy(&lpbk_buffer.in_payload[0], &gLpbkBuf[0], max); + + ret = pOp->op.au4OpData[0]; + /*<3> compare result */ + if (memcmp(lpbk_buffer.in_payload, lpbk_buffer.out_payload, lpbk_buffer.payload_length)) { + WMT_INFO_FUNC("[%s] WMT_TEST_LPBK_CMD payload compare error\n", __func__); + ret = -4; + break; + } + WMT_ERR_FUNC("[%s] exec WMT_TEST_LPBK_CMD succeed(loop = %d, size = %ld)\n", __func__, loop, + lpbk_buffer.payload_length); + + } + + if (loop != count) + WMT_ERR_FUNC("fail at loop(%d) buf_length(%d)\n", loop, max); + + + return ret; +} + +INT32 wmt_dbg_internal_lpbk_test(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 count; + UINT32 length; + + count = par1; + length = par2; + + WMT_INFO_FUNC("count[%d],length[%d]\n", count, length); + + wmt_core_lpbk_do_stp_init(); + + wmt_internal_loopback(count, length); + + wmt_core_lpbk_do_stp_deinit(); + return 0; +} +#endif + +static INT32 wmt_dbg_set_mcu_clock(INT32 par1, INT32 par2, INT32 par3) +{ + int ret = 0; + P_OSAL_OP pOp; + P_OSAL_SIGNAL pSignal = NULL; + UINT32 kind = 0; + + kind = par2; + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return -1; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_SET_MCU_CLK; + pOp->op.au4OpData[0] = kind; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + WMT_INFO_FUNC("OPID(%d) kind(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) kind(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return -2; + } + + ret = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == ret) { + WMT_WARN_FUNC("OPID(%d) kind(%d)fail(%d)\n", pOp->op.opId, pOp->op.au4OpData[0], ret); + return -3; + } + WMT_INFO_FUNC("OPID(%d) kind(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return ret; +} + +static INT32 wmt_dbg_poll_cpupcr(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 count = 0; + UINT16 sleep = 0; + UINT16 toAee = 0; + + count = par2; + sleep = (par3 & 0xF0) >> 4; + toAee = (par3 & 0x0F); + + WMT_INFO_FUNC("polling count[%d],polling sleep[%d],toaee[%d]\n", count, sleep, toAee); + wmt_lib_poll_cpupcr(count, sleep, toAee); + + return 0; +} + +#if CONSYS_ENALBE_SET_JTAG +static INT32 wmt_dbg_jtag_flag_ctrl(INT32 par1, INT32 par2, INT32 par3) +{ + UINT32 en_flag = par2; + + wmt_lib_jtag_flag_set(en_flag); + return 0; +} +#endif + +#if CFG_WMT_LTE_COEX_HANDLING +static INT32 wmt_dbg_lte_to_wmt_test(UINT32 opcode, UINT32 msg_len) +{ + ipc_ilm_t ilm; + local_para_struct *p_buf_str; + INT32 i = 0; + INT32 iRet = -1; + + WMT_INFO_FUNC("opcode(0x%02x),msg_len(%d)\n", opcode, msg_len); + p_buf_str = osal_malloc(osal_sizeof(local_para_struct) + msg_len); + if (NULL == p_buf_str) { + WMT_ERR_FUNC("kmalloc for local para ptr structure failed.\n"); + return -1; + } + p_buf_str->msg_len = msg_len; + for (i = 0; i < msg_len; i++) + p_buf_str->data[i] = i; + + ilm.local_para_ptr = p_buf_str; + ilm.msg_id = opcode; + + iRet = wmt_lib_handle_idc_msg(&ilm); + osal_free(p_buf_str); + return iRet; + +} + +static INT32 wmt_dbg_lte_coex_test(INT32 par1, INT32 par2, INT32 par3) +{ + UINT8 *local_buffer = NULL; + UINT32 handle_len; + INT32 iRet = -1; + static UINT8 wmt_to_lte_test_evt1[] = { 0x02, 0x16, 0x0d, 0x00, + 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0xa, 0xb + }; + static UINT8 wmt_to_lte_test_evt2[] = { 0x02, 0x16, 0x09, 0x00, + 0x01, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }; + static UINT8 wmt_to_lte_test_evt3[] = { 0x02, 0x16, 0x02, 0x00, + 0x02, 0xff + }; + static UINT8 wmt_to_lte_test_evt4[] = { 0x02, 0x16, 0x0d, 0x00, + 0x03, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, + 0xa, 0xb + }; + + local_buffer = kmalloc(512, GFP_KERNEL); + if (!local_buffer) { + WMT_ERR_FUNC("local_buffer kmalloc memory fail\n"); + return 0; + } + + if (par2 == 1) { + handle_len = + wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt1)) { + WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", + handle_len, osal_sizeof(wmt_to_lte_test_evt1)); + } else { + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + } + if (par2 == 2) { + osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], + &wmt_to_lte_test_evt2[0], osal_sizeof(wmt_to_lte_test_evt2)); + + handle_len = + wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], + osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)) { + WMT_ERR_FUNC("par2=2,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", + handle_len, osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)); + } else { + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + } + if (par2 == 3) { + osal_memcpy(&local_buffer[0], &wmt_to_lte_test_evt1[0], osal_sizeof(wmt_to_lte_test_evt1)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1)], + &wmt_to_lte_test_evt2[0], osal_sizeof(wmt_to_lte_test_evt2)); + osal_memcpy(&local_buffer[osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2)], + &wmt_to_lte_test_evt3[0], osal_sizeof(wmt_to_lte_test_evt3)); + + handle_len = wmt_idc_msg_to_lte_handing_for_test(&local_buffer[0], osal_sizeof(wmt_to_lte_test_evt1) + + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)); + if (handle_len != + osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)) { + WMT_ERR_FUNC("par2=3,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", handle_len, + osal_sizeof(wmt_to_lte_test_evt1) + osal_sizeof(wmt_to_lte_test_evt2) + + osal_sizeof(wmt_to_lte_test_evt3)); + } else { + WMT_INFO_FUNC("par3=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + } + if (par2 == 4) { + handle_len = + wmt_idc_msg_to_lte_handing_for_test(&wmt_to_lte_test_evt4[0], osal_sizeof(wmt_to_lte_test_evt4)); + if (handle_len != osal_sizeof(wmt_to_lte_test_evt4)) { + WMT_ERR_FUNC("par2=1,wmt send to lte msg fail:handle_len(%d),buff_len(%d)\n", + handle_len, osal_sizeof(wmt_to_lte_test_evt4)); + } else { + WMT_INFO_FUNC("par2=1,wmt send to lte msg OK! send_len(%d)\n", handle_len); + } + } + if (par2 == 5) { + if (par3 >= 1024) + par3 = 1024; + + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_DEFAULT_PARAM_IND test result(%d)\n", iRet); + } + if (par2 == 6) { + if (par3 >= 1024) + par3 = 1024; + + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_OPER_FREQ_PARAM_IND test result(%d)\n", iRet); + } + if (par2 == 7) { + if (par3 >= 1024) + par3 = 1024; + + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_WIFI_MAX_PWR_IND test result(%d)\n", iRet); + } + if (par2 == 8) { + if (par3 >= 1024) + par3 = 1024; + + iRet = wmt_dbg_lte_to_wmt_test(IPC_MSG_ID_EL1_LTE_TX_IND, par3); + WMT_INFO_FUNC("IPC_MSG_ID_EL1_LTE_TX_IND test result(%d)\n", iRet); + } + if (par2 == 9) { + if (par3 > 0) + wmt_core_set_flag_for_test(1); + else + wmt_core_set_flag_for_test(0); + } + return 0; + kfree(local_buffer); +} +#endif + +static ssize_t wmt_dev_dbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + + INT32 retval = 0; + INT32 i_ret = 0; + PINT8 warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; + + if (*f_pos > 0) { + retval = 0; + } else { + /*len = sprintf(page, "%d\n", g_psm_enable); */ + if (gCoexBuf.availSize <= 0) { + WMT_INFO_FUNC("no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"); + retval = osal_strlen(warn_msg) + 1; + if (count < retval) + retval = count; + + i_ret = copy_to_user(buf, warn_msg, retval); + if (i_ret) { + WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } else { + INT32 i = 0; + INT32 len = 0; + INT8 msg_info[128]; + INT32 max_num = 0; + /*we do not check page buffer, because there are only + * 100 bytes in g_coex_buf, no reason page buffer is not + * enough, a bomb is placed here on unexpected condition + */ + + WMT_INFO_FUNC("%d bytes available\n", gCoexBuf.availSize); + max_num = ((osal_sizeof(msg_info) > count ? osal_sizeof(msg_info) : count) - 1) / 5; + + if (max_num > gCoexBuf.availSize) + max_num = gCoexBuf.availSize; + else + WMT_INFO_FUNC("round to %d bytes due to local buffer size limitation\n", max_num); + + + for (i = 0; i < max_num; i++) + len += osal_sprintf(msg_info + len, "0x%02x ", gCoexBuf.buffer[i]); + + + len += osal_sprintf(msg_info + len, "\n"); + retval = len; + + i_ret = copy_to_user(buf, msg_info, retval); + if (i_ret) { + WMT_ERR_FUNC("copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + + } + } + gCoexBuf.availSize = 0; +err_exit: + + return retval; +} + +static ssize_t wmt_dev_dbg_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + INT8 buf[256]; + PINT8 pBuf; + ssize_t len = count; + INT32 x = 0, y = 0, z = 0; + PINT8 pToken = NULL; + PINT8 pDelimiter = " \t"; + long res; + INT32 ret; + + WMT_INFO_FUNC("write parameter len = %d\n\r", (INT32) len); + if (len >= osal_sizeof(buf)) { + WMT_ERR_FUNC("input handling fail!\n"); + len = osal_sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + + buf[len] = '\0'; + WMT_INFO_FUNC("write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = osal_strsep(&pBuf, pDelimiter); + + if (pToken != NULL) { + ret = osal_strtol(pToken, 16, &res); + if (ret) { + WMT_ERR_FUNC("get x fail(%d)\n", ret); + x = 0; + } + x = res; + } else { + x = 0; + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + ret = osal_strtol(pToken, 16, &res); + if (ret) { + WMT_ERR_FUNC("get y fail(%d)\n", ret); + y = 0; + } + y = res; + WMT_INFO_FUNC("y = 0x%08x\n\r", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + y = 0x80000000; + + } + + pToken = osal_strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + ret = osal_strtol(pToken, 16, &res); + if (ret) { + WMT_ERR_FUNC("get z fail(%d)\n", ret); + z = 0; + } + z = res; + } else { + z = 10; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + z = 0xffffffff; + + } + + WMT_WARN_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); + + if (osal_array_size(wmt_dev_dbg_func) > x && NULL != wmt_dev_dbg_func[x]) + (*wmt_dev_dbg_func[x]) (x, y, z); + else + WMT_WARN_FUNC("no handler defined for command id(0x%08x)\n\r", x); + + return len; +} + +INT32 wmt_dev_dbg_setup(VOID) +{ + static const struct file_operations wmt_dbg_fops = { + .owner = THIS_MODULE, + .read = wmt_dev_dbg_read, + .write = wmt_dev_dbg_write, + }; + gWmtDbgEntry = proc_create(WMT_DBG_PROCNAME, 0664, NULL, &wmt_dbg_fops); + if (gWmtDbgEntry == NULL) { + WMT_ERR_FUNC("Unable to create /proc entry\n\r"); + return -1; + } + return 0; +} + +INT32 wmt_dev_dbg_remove(VOID) +{ + if (NULL != gWmtDbgEntry) + remove_proc_entry(WMT_DBG_PROCNAME, NULL); + +#if CFG_WMT_PS_SUPPORT + wmt_lib_ps_deinit(); +#endif + return 0; +} +#endif + +#if CFG_WMT_PROC_FOR_AEE + +static ssize_t wmt_dev_proc_for_aee_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = 0; + UINT32 len = 0; + + WMT_INFO_FUNC("%s: count %d pos %lld\n", __func__, count, *f_pos); + + if (0 == *f_pos) { + pBuf = wmt_lib_get_cpupcr_xml_format(&len); + g_buf_len = len; + WMT_INFO_FUNC("wmt_dev:wmt for aee buffer len(%d)\n", g_buf_len); + } + + if (g_buf_len >= count) { + + retval = copy_to_user(buf, pBuf, count); + if (retval) { + WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + + *f_pos += count; + g_buf_len -= count; + pBuf += count; + WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); + + retval = count; + } else if (0 != g_buf_len) { + + retval = copy_to_user(buf, pBuf, g_buf_len); + if (retval) { + WMT_ERR_FUNC("copy to aee buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + + *f_pos += g_buf_len; + len = g_buf_len; + g_buf_len = 0; + pBuf += len; + retval = len; + WMT_INFO_FUNC("wmt_dev:after read,wmt for aee buffer len(%d)\n", g_buf_len); + } else { + WMT_INFO_FUNC("wmt_dev: no data available for aee\n"); + retval = 0; + } +err_exit: + return retval; +} + +static ssize_t wmt_dev_proc_for_aee_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + WMT_TRC_FUNC(); + return 0; +} + +INT32 wmt_dev_proc_for_aee_setup(VOID) +{ + static const struct file_operations wmt_aee_fops = { + .owner = THIS_MODULE, + .read = wmt_dev_proc_for_aee_read, + .write = wmt_dev_proc_for_aee_write, + }; + + gWmtDbgEntry = proc_create(WMT_AEE_PROCNAME, 0664, NULL, &wmt_aee_fops); + if (gWmtDbgEntry == NULL) { + WMT_ERR_FUNC("Unable to create /proc entry\n\r"); + return -1; + } + + return 0; +} + +INT32 wmt_dev_proc_for_aee_remove(VOID) +{ + if (NULL != gWmtAeeEntry) + remove_proc_entry(WMT_AEE_PROCNAME, NULL); + + return 0; +} +#endif + +VOID wmt_dev_rx_event_cb(VOID) +{ + u4RxFlag = 1; + atomic_inc(&gRxCount); + if (NULL != gpRxEvent) { + /* u4RxFlag = 1; */ + /* atomic_inc(&gRxCount); */ + wake_up_interruptible(&gpRxEvent->waitQueue); + } else { + /* WMT_ERR_FUNC("null gpRxEvent, flush rx!\n"); */ + /* wmt_lib_flush_rx(); */ + } +} + +INT32 wmt_dev_rx_timeout(P_OSAL_EVENT pEvent) +{ + + UINT32 ms = pEvent->timeoutValue; + long lRet = 0; + + gpRxEvent = pEvent; + if (0 != ms) + lRet = wait_event_interruptible_timeout(gpRxEvent->waitQueue, 0 != u4RxFlag, msecs_to_jiffies(ms)); + else + lRet = wait_event_interruptible(gpRxEvent->waitQueue, u4RxFlag != 0); + + u4RxFlag = 0; +/* gpRxEvent = NULL; */ + if (atomic_dec_return(&gRxCount)) { + WMT_ERR_FUNC("gRxCount != 0 (%d), reset it!\n", atomic_read(&gRxCount)); + atomic_set(&gRxCount, 0); + } + + return lRet; +} + +INT32 wmt_dev_read_file(PUINT8 pName, const PPUINT8 ppBufPtr, INT32 offset, INT32 padSzBuf) +{ + INT32 iRet = -1; + struct file *fd; + /* ssize_t iRet; */ + INT32 file_len; + INT32 read_len; + PVOID pBuf; + mm_segment_t fs; + + /* struct cred *cred = get_task_cred(current); */ + //const struct cred *cred = get_current_cred(); + + if (!ppBufPtr) { + WMT_ERR_FUNC("invalid ppBufptr!\n"); + return -1; + } + *ppBufPtr = NULL; + + fd = filp_open(pName, O_RDONLY, 0); + if (IS_ERR(fd)) { + WMT_ERR_FUNC("error code:%d\n", PTR_ERR(fd)); + return -2; + } + + if(fd->f_op == NULL) { + printk(KERN_ERR "invalid file op \r\n"); + return -3; + } + +#if 0 + if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { + WMT_ERR_FUNC("failed to open or read!(0x%p, %d, %d, %d)\n", fd, PTR_ERR(fd), cred->fsuid, cred->fsgid); + if (IS_ERR(fd)) + WMT_ERR_FUNC("error code:%d\n", PTR_ERR(fd)); + return -1; + } +#endif + file_len = fd->f_path.dentry->d_inode->i_size; + file_len = fd->f_op->llseek(fd, 0, 2); + fd->f_op->llseek(fd, 0, 0); + pBuf = vmalloc((file_len + BCNT_PATCH_BUF_HEADROOM + 3) & ~0x3UL); + if (!pBuf) { + WMT_ERR_FUNC("failed to vmalloc(%d)\n", (INT32) ((file_len + 3) & ~0x3UL)); + goto read_file_done; + } + + do { + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + WMT_ERR_FUNC("failed to seek!!\n"); + goto read_file_done; + } + } else { + fd->f_pos = offset; + } + } + + fs=get_fs(); + read_len = vfs_read(fd, pBuf + padSzBuf, file_len, &fd->f_pos); + set_fs(fs); + if (read_len != file_len) + WMT_WARN_FUNC("read abnormal: read_len(%d), file_len(%d)\n", read_len, file_len); + + } while (false); + + iRet = 0; + *ppBufPtr = pBuf; + +read_file_done: + if (iRet) { + if (pBuf) + vfree(pBuf); + + } + + filp_close(fd, NULL); + + return (iRet) ? iRet : read_len; +} + +/* TODO: [ChangeFeature][George] refine this function name for general filesystem read operation, not patch only. */ +INT32 wmt_dev_patch_get(PUINT8 pPatchName, osal_firmware **ppPatch, INT32 padSzBuf) +{ + INT32 iRet = -1; + osal_firmware *pfw; + uid_t orig_uid; + gid_t orig_gid; + + /* struct cred *cred = get_task_cred(current); */ + struct cred *cred = (struct cred *)get_current_cred(); + + mm_segment_t orig_fs = get_fs(); + + if (*ppPatch) { + WMT_WARN_FUNC("f/w patch already exists\n"); + if ((*ppPatch)->data) + vfree((*ppPatch)->data); + + kfree(*ppPatch); + *ppPatch = NULL; + } + + if (!osal_strlen(pPatchName)) { + WMT_ERR_FUNC("empty f/w name\n"); + osal_assert((osal_strlen(pPatchName) > 0)); + return -1; + } + + pfw = kzalloc(sizeof(osal_firmware), /*GFP_KERNEL */ GFP_ATOMIC); + if (!pfw) { + WMT_ERR_FUNC("kzalloc(%d) fail\n", sizeof(osal_firmware)); + return -2; + } + + orig_uid = cred->fsuid.val; + orig_gid = cred->fsgid.val; + cred->fsuid.val = cred->fsgid.val = 0; + + set_fs(get_ds()); + + /* load patch file from fs */ + iRet = wmt_dev_read_file(pPatchName, (const PPUINT8)&pfw->data, 0, padSzBuf); + set_fs(orig_fs); + + cred->fsuid.val = orig_uid; + cred->fsgid.val = orig_gid; + + + if (iRet > 0) { + pfw->size = iRet; + *ppPatch = pfw; + WMT_DBG_FUNC("load (%s) to addr(0x%p) success\n", pPatchName, pfw->data); + return 0; + } + kfree(pfw); + *ppPatch = NULL; + WMT_ERR_FUNC("load file (%s) fail, iRet(%d)\n", pPatchName, iRet); + return -1; +} + +INT32 wmt_dev_patch_put(osal_firmware **ppPatch) +{ + if (NULL != *ppPatch) { + if ((*ppPatch)->data) + vfree((*ppPatch)->data); + + kfree(*ppPatch); + *ppPatch = NULL; + } + return 0; +} + +VOID wmt_dev_patch_info_free(VOID) +{ + + kfree(pPatchInfo); + pPatchInfo = NULL; + +} + +MTK_WCN_BOOL wmt_dev_is_file_exist(PUINT8 pFileName) +{ + struct file *fd = NULL; + /* ssize_t iRet; */ + INT32 fileLen = -1; + const struct cred *cred = get_current_cred(); + + if (pFileName == NULL) { + WMT_ERR_FUNC("invalid file name pointer(%p)\n", pFileName); + return MTK_WCN_BOOL_FALSE; + } + if (osal_strlen(pFileName) < osal_strlen(defaultPatchName)) { + WMT_ERR_FUNC("invalid file name(%s)\n", pFileName); + return MTK_WCN_BOOL_FALSE; + } + /* struct cred *cred = get_task_cred(current); */ + + fd = filp_open(pFileName, O_RDONLY, 0); + if (!fd || IS_ERR(fd) || !fd->f_op || !fd->f_op->read) { + WMT_ERR_FUNC("failed to open or read(%s)!(0x%p, %d, %d)\n", pFileName, fd, cred->fsuid, cred->fsgid); + return MTK_WCN_BOOL_FALSE; + } + fileLen = fd->f_path.dentry->d_inode->i_size; + filp_close(fd, NULL); + fd = NULL; + if (fileLen <= 0) { + WMT_ERR_FUNC("invalid file(%s), length(%d)\n", pFileName, fileLen); + return MTK_WCN_BOOL_FALSE; + } + WMT_ERR_FUNC("valid file(%s), length(%d)\n", pFileName, fileLen); + return true; + +} + +/* static unsigned long count_last_access_sdio = 0; */ +static unsigned long count_last_access_btif; +static unsigned long jiffies_last_poll; + +#if 0 +static INT32 wmt_dev_tra_sdio_update(void) +{ + count_last_access_sdio += 1; + /* WMT_INFO_FUNC("jiffies_last_access_sdio: jiffies = %ul\n", jiffies); */ + + return 0; +} +#endif + +extern INT32 wmt_dev_tra_bitf_update(void) +{ + count_last_access_btif += 1; + /* WMT_INFO_FUNC("jiffies_last_access_btif: jiffies = %ul\n", jiffies); */ + + return 0; +} + +static UINT32 wmt_dev_tra_ahb_poll(void) +{ +#define TIME_THRESHOLD_TO_TEMP_QUERY 3000 +#define COUNT_THRESHOLD_TO_TEMP_QUERY 200 + + unsigned long ahb_during_count = 0; + unsigned long poll_during_time = 0; + + /* if (jiffies > jiffies_last_poll) */ + if (time_after(jiffies, jiffies_last_poll)) + poll_during_time = jiffies - jiffies_last_poll; + else + poll_during_time = 0xffffffff; + + + WMT_DBG_FUNC("**jiffies_to_mesecs(0xffffffff) = %lu\n", jiffies_to_msecs(0xffffffff)); + + if (jiffies_to_msecs(poll_during_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { + WMT_DBG_FUNC("**poll_during_time = %lu < %lu, not to query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY); + return -1; + } + /* ahb_during_count = count_last_access_sdio; */ + if (NULL == mtk_wcn_wlan_bus_tx_cnt) { + WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt null pointer\n"); + return -1; + } + ahb_during_count = (*mtk_wcn_wlan_bus_tx_cnt) (); + + if (ahb_during_count < COUNT_THRESHOLD_TO_TEMP_QUERY) { + WMT_DBG_FUNC("**ahb_during_count = %lu < %lu, not to query\n", + ahb_during_count, COUNT_THRESHOLD_TO_TEMP_QUERY); + return -2; + } + + if (NULL == mtk_wcn_wlan_bus_tx_cnt_clr) { + WMT_ERR_FUNC("WMT-DEV:mtk_wcn_wlan_bus_tx_cnt_clr null pointer\n"); + return -3; + } + (*mtk_wcn_wlan_bus_tx_cnt_clr) (); + /* count_last_access_sdio = 0; */ + jiffies_last_poll = jiffies; + + WMT_INFO_FUNC("**poll_during_time = %lu > %lu, ahb_during_count = %lu > %lu, query\n", + jiffies_to_msecs(poll_during_time), TIME_THRESHOLD_TO_TEMP_QUERY, + jiffies_to_msecs(ahb_during_count), COUNT_THRESHOLD_TO_TEMP_QUERY); + + return 0; +} + +long wmt_dev_tm_temp_query(void) +{ +#define HISTORY_NUM 5 +#define TEMP_THRESHOLD 65 +#define REFRESH_TIME 300 /* sec */ + + static INT32 temp_table[HISTORY_NUM] = { 99 }; /* not query yet. */ + static INT32 idx_temp_table; + static struct timeval query_time, now_time; + + INT8 query_cond = 0; + INT32 current_temp = 0; + INT32 index = 0; + long return_temp = 0; + /* Query condition 1: */ + /* If we have the high temperature records on the past, we continue to query/monitor */ + /* the real temperature until cooling */ + for (index = 0; index < HISTORY_NUM; index++) { + if (temp_table[index] >= TEMP_THRESHOLD) { + query_cond = 1; + WMT_DBG_FUNC("temperature table is still initial value, we should query temp temperature..\n"); + } + } + + do_gettimeofday(&now_time); +#if 1 + /* Query condition 2: */ + /* Moniter the ahb bus activity to decide if we have the need to query temperature. */ + if (!query_cond) { + if (wmt_dev_tra_ahb_poll() == 0) { + query_cond = 1; + WMT_INFO_FUNC("ahb traffic , we must query temperature..\n"); + } else { + WMT_DBG_FUNC("ahb idle traffic ....\n"); + } + + /* only WIFI tx power might make temperature varies largely */ +#if 0 + if (!query_cond) { + last_access_time = wmt_dev_tra_uart_poll(); + if (jiffies_to_msecs(last_access_time) < TIME_THRESHOLD_TO_TEMP_QUERY) { + query_cond = 1; + WMT_DBG_FUNC("uart busy traffic , we must query temperature..\n"); + } else { + WMT_DBG_FUNC("uart still idle traffic , we don't query temp temperature..\n"); + } + } +#endif + } +#endif + /* Query condition 3: */ + /* If the query time exceeds the a certain of period, refresh temp table. */ + /* */ + if (!query_cond) { + /* time overflow, we refresh temp table again for simplicity! */ + if ((now_time.tv_sec < query_time.tv_sec) || + ((now_time.tv_sec > query_time.tv_sec) && (now_time.tv_sec - query_time.tv_sec) > REFRESH_TIME)) { + query_cond = 1; + + WMT_INFO_FUNC("It is long time (> %d sec) not to query, we must query temp temperature..\n", + REFRESH_TIME); + for (index = 0; index < HISTORY_NUM; index++) + temp_table[index] = 99; + + } + } + + if (query_cond) { + /* update the temperature record */ + mtk_wcn_wmt_therm_ctrl(WMTTHERM_ENABLE); + current_temp = mtk_wcn_wmt_therm_ctrl(WMTTHERM_READ); + mtk_wcn_wmt_therm_ctrl(WMTTHERM_DISABLE); + idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; + temp_table[idx_temp_table] = current_temp; + do_gettimeofday(&query_time); + + WMT_INFO_FUNC("[Thermal] current_temp = 0x%x\n", (current_temp & 0xFF)); + } else { + current_temp = temp_table[idx_temp_table]; + idx_temp_table = (idx_temp_table + 1) % HISTORY_NUM; + temp_table[idx_temp_table] = current_temp; + } + + /* */ + /* Dump information */ + /* */ + WMT_DBG_FUNC("[Thermal] idx_temp_table = %d\n", idx_temp_table); + WMT_DBG_FUNC("[Thermal] now.time = %d, query.time = %d, REFRESH_TIME = %d\n", now_time.tv_sec, + query_time.tv_sec, REFRESH_TIME); + + WMT_DBG_FUNC("[0] = %d, [1] = %d, [2] = %d, [3] = %d, [4] = %d\n----\n", + temp_table[0], temp_table[1], temp_table[2], temp_table[3], temp_table[4]); + + return_temp = ((current_temp & 0x80) == 0x0) ? current_temp : (-1) * (current_temp & 0x7f); + + return return_temp; +} + +ssize_t WMT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 iRet = 0; + UINT8 wrBuf[NAME_MAX + 1] = { 0 }; + INT32 copySize = (count < NAME_MAX) ? count : NAME_MAX; + + WMT_LOUD_FUNC("count:%d copySize:%d\n", count, copySize); + + if (copySize > 0) { + if (copy_from_user(wrBuf, buf, copySize)) { + iRet = -EFAULT; + goto write_done; + } + iRet = copySize; + wrBuf[NAME_MAX] = '\0'; + + if (!strncasecmp(wrBuf, "ok", NAME_MAX)) { + WMT_DBG_FUNC("resp str ok\n"); + /* pWmtDevCtx->cmd_result = 0; */ + wmt_lib_trigger_cmd_signal(0); + } else { + WMT_WARN_FUNC("warning resp str (%s)\n", wrBuf); + /* pWmtDevCtx->cmd_result = -1; */ + wmt_lib_trigger_cmd_signal(-1); + } + /* complete(&pWmtDevCtx->cmd_comp); */ + + } + +write_done: + return iRet; +} + +ssize_t WMT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 iRet = 0; + PUINT8 pCmd = NULL; + UINT32 cmdLen = 0; + + pCmd = wmt_lib_get_cmd(); + + if (pCmd != NULL) { + cmdLen = osal_strlen(pCmd) < NAME_MAX ? osal_strlen(pCmd) : NAME_MAX; + WMT_DBG_FUNC("cmd str(%s)\n", pCmd); + if (copy_to_user(buf, pCmd, cmdLen)) + iRet = -EFAULT; + else + iRet = cmdLen; + + } +#if 0 + if (test_and_clear_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) { + iRet = osal_strlen(localBuf) < NAME_MAX ? osal_strlen(localBuf) : NAME_MAX; + /* we got something from STP driver */ + WMT_DBG_FUNC("copy cmd to user by read:%s\n", localBuf); + if (copy_to_user(buf, localBuf, iRet)) { + iRet = -EFAULT; + goto read_done; + } + } +#endif + return iRet; +} + +unsigned int WMT_poll(struct file *filp, poll_table *wait) +{ + UINT32 mask = 0; + P_OSAL_EVENT pEvent = wmt_lib_get_cmd_event(); + + poll_wait(filp, &pEvent->waitQueue, wait); + /* empty let select sleep */ + if (MTK_WCN_BOOL_TRUE == wmt_lib_get_cmd_status()) + mask |= POLLIN | POLLRDNORM; /* readable */ + +#if 0 + if (test_bit(WMT_STAT_CMD, &pWmtDevCtx->state)) + mask |= POLLIN | POLLRDNORM; /* readable */ + +#endif + mask |= POLLOUT | POLLWRNORM; /* writable */ + return mask; +} + +/* INT32 WMT_ioctl(struct inode *inode, struct file *filp, UINT32 cmd, unsigned long arg) */ +long WMT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + + INT32 iRet = 0; + UINT8 *pBuffer = NULL; + + WMT_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg); + switch (cmd) { + case WMT_IOCTL_SET_PATCH_NAME: /* patch location */ + { + + pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!pBuffer) { + WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); + return 0; + } + if (copy_from_user(pBuffer, (void *)arg, NAME_MAX)) { + iRet = -EFAULT; + kfree(pBuffer); + break; + } + pBuffer[NAME_MAX] = '\0'; + wmt_lib_set_patch_name(pBuffer); + kfree(pBuffer); + } + break; + + case WMT_IOCTL_SET_STP_MODE: /* stp/hif/fm mode */ + + /* set hif conf */ + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal = NULL; + P_WMT_HIF_CONF pHif = NULL; + + iRet = wmt_lib_set_hif(arg); + if (0 != iRet) { + WMT_INFO_FUNC("wmt_lib_set_hif fail\n"); + break; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_INFO_FUNC("get_free_lxop fail\n"); + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_HIF_CONF; + + pHif = wmt_lib_get_hif(); + + osal_memcpy(&pOp->op.au4OpData[0], pHif, sizeof(WMT_HIF_CONF)); + pOp->op.u4InfoBit = WMT_OP_HIF_BIT; + pSignal->timeoutValue = 0; + + bRet = wmt_lib_put_act_op(pOp); + WMT_DBG_FUNC("WMT_OPID_HIF_CONF result(%d)\n", bRet); + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + } while (0); + + break; + + case WMT_IOCTL_FUNC_ONOFF_CTRL: /* test turn on/off func */ + + do { + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + if (arg & 0x80000000) + bRet = mtk_wcn_wmt_func_on(arg & 0xF); + else + bRet = mtk_wcn_wmt_func_off(arg & 0xF); + + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + } while (0); + + break; + + case WMT_IOCTL_LPBK_POWER_CTRL: + /*switch Loopback function on/off + arg: bit0 = 1:turn loopback function on + bit0 = 0:turn loopback function off + */ + do { + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + + if (arg & 0x01) + bRet = mtk_wcn_wmt_func_on(WMTDRV_TYPE_LPBK); + else + bRet = mtk_wcn_wmt_func_off(WMTDRV_TYPE_LPBK); + + iRet = (MTK_WCN_BOOL_FALSE == bRet) ? -EFAULT : 0; + } while (0); + + break; + + case WMT_IOCTL_LPBK_TEST: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT32 u4Wait; + /* UINT8 lpbk_buf[1024] = {0}; */ + UINT32 effectiveLen = 0; + P_OSAL_SIGNAL pSignal = NULL; + + if (copy_from_user(&effectiveLen, (void *)arg, sizeof(effectiveLen))) { + iRet = -EFAULT; + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + break; + } + if (effectiveLen > sizeof(gLpbkBuf)) { + iRet = -EFAULT; + WMT_ERR_FUNC("length is too long\n"); + break; + } + WMT_DBG_FUNC("len = %d\n", effectiveLen); + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + u4Wait = 2000; + if (copy_from_user(&gLpbkBuf[0], (void *)arg + sizeof(unsigned long), effectiveLen)) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_LPBK; + pOp->op.au4OpData[0] = effectiveLen; /* packet length */ + pOp->op.au4OpData[1] = (SIZE_T) &gLpbkBuf[0]; /* packet buffer pointer */ + memcpy(&gLpbkBufLog, &gLpbkBuf[((effectiveLen >= 4) ? effectiveLen - 4 : 0)], 4); + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", + pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) buf tail(0x%08x) fail\n", + pOp->op.opId, pOp->op.au4OpData[0], gLpbkBufLog); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + if (copy_to_user((void *)arg + sizeof(SIZE_T) + sizeof(UINT8[2048]), gLpbkBuf, iRet)) { + iRet = -EFAULT; + break; + } + + } while (0); + + break; + + case WMT_IOCTL_ADIE_LPBK_TEST: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal = NULL; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_ADIE_LPBK_TEST; + pOp->op.au4OpData[0] = 0; + pOp->op.au4OpData[1] = (SIZE_T) &gLpbkBuf[0]; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d)abort\n", pOp->op.opId); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + if (copy_to_user((void *)arg + sizeof(SIZE_T), gLpbkBuf, iRet)) { + iRet = -EFAULT; + break; + } + + } while (0); + + break; + + case 10: + { + pBuffer = kmalloc(NAME_MAX + 1, GFP_KERNEL); + if (!pBuffer) { + WMT_ERR_FUNC("pBuffer kmalloc memory fail\n"); + return 0; + } + wmt_lib_host_awake_get(); + mtk_wcn_stp_coredump_start_ctrl(1); + osal_strcpy(pBuffer, "MT662x f/w coredump start-"); + if (copy_from_user + (pBuffer + osal_strlen(pBuffer), (void *)arg, NAME_MAX - osal_strlen(pBuffer))) { + /* osal_strcpy(pBuffer, "MT662x f/w assert core dump start"); */ + WMT_ERR_FUNC("copy assert string failed\n"); + } + pBuffer[NAME_MAX] = '\0'; + osal_dbg_assert_aee(pBuffer, pBuffer); + kfree(pBuffer); + } + break; + case 11: + { + osal_dbg_assert_aee("MT662x f/w coredump end", "MT662x firmware coredump ends"); + wmt_lib_host_awake_put(); + } + break; + + case WMT_IOCTL_GET_CHIP_INFO: + { + if (0 == arg) + return wmt_lib_get_icinfo(WMTCHIN_CHIPID); + else if (1 == arg) + return wmt_lib_get_icinfo(WMTCHIN_HWVER); + else if (2 == arg) + return wmt_lib_get_icinfo(WMTCHIN_FWVER); + + } + break; + + case WMT_IOCTL_SET_LAUNCHER_KILL:{ + if (1 == arg) { + WMT_INFO_FUNC("launcher may be killed,block abnormal stp tx.\n"); + wmt_lib_set_stp_wmt_last_close(1); + } else { + wmt_lib_set_stp_wmt_last_close(0); + } + + } + break; + + case WMT_IOCTL_SET_PATCH_NUM:{ + pAtchNum = arg; + WMT_DBG_FUNC(" get patch num from launcher = %d\n", pAtchNum); + wmt_lib_set_patch_num(pAtchNum); + pPatchInfo = kcalloc(pAtchNum, sizeof(WMT_PATCH_INFO), GFP_ATOMIC); + if (!pPatchInfo) { + WMT_ERR_FUNC("allocate memory fail!\n"); + break; + } + } + break; + + case WMT_IOCTL_SET_PATCH_INFO:{ + WMT_PATCH_INFO wMtPatchInfo; + P_WMT_PATCH_INFO pTemp = NULL; + UINT32 dWloadSeq; + static UINT32 counter; + + if (!pPatchInfo) { + WMT_ERR_FUNC("NULL patch info pointer\n"); + break; + } + + if (copy_from_user(&wMtPatchInfo, (void *)arg, sizeof(WMT_PATCH_INFO))) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + + dWloadSeq = wMtPatchInfo.dowloadSeq; + WMT_DBG_FUNC( + "patch dl seq %d,name %s,address info 0x%02x,0x%02x,0x%02x,0x%02x\n", + dWloadSeq, wMtPatchInfo.patchName, + wMtPatchInfo.addRess[0], + wMtPatchInfo.addRess[1], + wMtPatchInfo.addRess[2], + wMtPatchInfo.addRess[3]); + osal_memcpy(pPatchInfo + dWloadSeq - 1, &wMtPatchInfo, sizeof(WMT_PATCH_INFO)); + pTemp = pPatchInfo + dWloadSeq - 1; + if (++counter == pAtchNum) { + wmt_lib_set_patch_info(pPatchInfo); + counter = 0; + } + } + break; + + case WMT_IOCTL_WMT_COREDUMP_CTRL: + mtk_wcn_stp_coredump_flag_ctrl(arg); + break; + case WMT_IOCTL_WMT_QUERY_CHIPID: + { + iRet = mtk_wcn_wmt_chipid_query(); + WMT_WARN_FUNC("chipid = 0x%x\n", iRet); + } + break; + case WMT_IOCTL_SEND_BGW_DS_CMD: + do { + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + UINT8 desense_buf[14] = { 0 }; + UINT32 effectiveLen = 14; + P_OSAL_SIGNAL pSignal = NULL; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + iRet = -EFAULT; + break; + } + if (copy_from_user(&desense_buf[0], (void *)arg, effectiveLen)) { + WMT_ERR_FUNC("copy_from_user failed at %d\n", __LINE__); + iRet = -EFAULT; + break; + } + pSignal = &pOp->signal; + pOp->op.opId = WMT_OPID_BGW_DS; + pOp->op.au4OpData[0] = effectiveLen; /* packet length */ + pOp->op.au4OpData[1] = (SIZE_T) &desense_buf[0]; /* packet buffer pointer */ + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + WMT_INFO_FUNC("OPID(%d) start\n", pOp->op.opId); + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,opid(%d) abort\n", pOp->op.opId); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) fail\n", pOp->op.opId); + iRet = -1; + break; + } + WMT_INFO_FUNC("OPID(%d) length(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + iRet = pOp->op.au4OpData[0]; + + } while (0); + + break; + case WMT_IOCTL_FW_DBGLOG_CTRL: + { + iRet = wmt_plat_set_dbg_mode(arg); + if (iRet == 0) + wmt_dbg_fwinfor_from_emi(0, 1, 0); + } + break; + case WMT_IOCTL_DYNAMIC_DUMP_CTRL: + { + UINT32 i = 0, j = 0, k = 0; + UINT8 *pBuf = NULL; + UINT32 int_buf[10]; + char Buffer[10][11]; + + pBuf = kmalloc(DYNAMIC_DUMP_BUF + 1, GFP_KERNEL); + if (!pBuf) { + WMT_ERR_FUNC("pBuf kmalloc memory fail\n"); + return 0; + } + if (copy_from_user(pBuf, (void *)arg, DYNAMIC_DUMP_BUF)) { + iRet = -EFAULT; + kfree(pBuf); + break; + } + pBuf[DYNAMIC_DUMP_BUF] = '\0'; + WMT_INFO_FUNC("get dynamic dump data from property(%s)\n", pBuf); + memset(Buffer, 0, 10*11); + for (i = 0; i < DYNAMIC_DUMP_BUF; i++) { + if (pBuf[i] == '/') { + k = 0; + j++; + } else { + Buffer[j][k] = pBuf[i]; + k++; + } + } + for (j = 0; j < 10; j++) { + iRet = kstrtou32(Buffer[j], 0, &int_buf[j]); + if (iRet) { + WMT_ERR_FUNC("string convert fail(%d)\n", iRet); + break; + } + WMT_INFO_FUNC("dynamic dump data buf[%d]:(0x%x)\n", j, int_buf[j]); + } + wmt_plat_set_dynamic_dumpmem(int_buf); + kfree(pBuf); + } + break; + default: + iRet = -EINVAL; + WMT_WARN_FUNC("unknown cmd (%d)\n", cmd); + break; + } + + return iRet; +} +#ifdef CONFIG_COMPAT +long WMT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + long ret; + WMT_INFO_FUNC("cmd[0x%x]\n", cmd); + switch (cmd) { + case COMPAT_WMT_IOCTL_SET_PATCH_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_NAME, (unsigned long)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_LPBK_TEST: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_LPBK_TEST, (unsigned long)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_SET_PATCH_INFO: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SET_PATCH_INFO, (unsigned long)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_PORT_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_PORT_NAME, (unsigned long)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_WMT_CFG_NAME: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_WMT_CFG_NAME, (unsigned long)compat_ptr(arg)); + break; + case COMPAT_WMT_IOCTL_SEND_BGW_DS_CMD: + ret = WMT_unlocked_ioctl(filp, WMT_IOCTL_SEND_BGW_DS_CMD, (unsigned long)compat_ptr(arg)); + break; + default: { + ret = WMT_unlocked_ioctl(filp, cmd, arg); + break; + } + } + return ret; +} +#endif +static int WMT_open(struct inode *inode, struct file *file) +{ + long ret; + + WMT_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + ret = wait_event_timeout(gWmtInitWq, gWmtInitDone != 0, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); + if (!ret) { + WMT_WARN_FUNC("wait_event_timeout (%d)ms,(%d)jiffies,return -EIO\n", + WMT_DEV_INIT_TO_MS, msecs_to_jiffies(WMT_DEV_INIT_TO_MS)); + return -EIO; + } + + if (atomic_inc_return(&gWmtRefCnt) == 1) + WMT_INFO_FUNC("1st call\n"); + + return 0; +} + +static int WMT_close(struct inode *inode, struct file *file) +{ + WMT_INFO_FUNC("major %d minor %d (pid %d)\n", imajor(inode), iminor(inode), current->pid); + + if (atomic_dec_return(&gWmtRefCnt) == 0) + WMT_INFO_FUNC("last call\n"); + + return 0; +} + +const struct file_operations gWmtFops = { + .open = WMT_open, + .release = WMT_close, + .read = WMT_read, + .write = WMT_write, +/* .ioctl = WMT_ioctl, */ + .unlocked_ioctl = WMT_unlocked_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = WMT_compat_ioctl, +#endif + .poll = WMT_poll, +}; + +void wmt_dev_bgw_desense_init(VOID) +{ + bgw_init_socket(); +} + +void wmt_dev_bgw_desense_deinit(VOID) +{ + bgw_destroy_netlink_kernel(); +} + +void wmt_dev_send_cmd_to_daemon(UINT32 cmd) +{ + send_command_to_daemon(cmd); +} + +static int WMT_init(void) +{ + dev_t devID = MKDEV(gWmtMajor, 0); + INT32 cdevErr = -1; + INT32 ret = -1; + + WMT_INFO_FUNC("WMT Version= %s DATE=%s\n", MTK_WMT_VERSION, MTK_WMT_DATE); + /* Prepare a UINT8 device */ + /*static allocate chrdev */ + gWmtInitDone = 0; + init_waitqueue_head((wait_queue_head_t *) &gWmtInitWq); + stp_drv_init(); + + ret = register_chrdev_region(devID, WMT_DEV_NUM, WMT_DRIVER_NAME); + if (ret) { + WMT_ERR_FUNC("fail to register chrdev\n"); + return ret; + } + cdev_init(&gWmtCdev, &gWmtFops); + gWmtCdev.owner = THIS_MODULE; + cdevErr = cdev_add(&gWmtCdev, devID, WMT_DEV_NUM); + if (cdevErr) { + WMT_ERR_FUNC("cdev_add() fails (%d)\n", cdevErr); + goto error; + } + WMT_INFO_FUNC("driver(major %d) installed\n", gWmtMajor); +#if WMT_CREATE_NODE_DYNAMIC + wmt_class = class_create(THIS_MODULE, "stpwmt"); + if (IS_ERR(wmt_class)) + goto error; + wmt_dev = device_create(wmt_class, NULL, devID, NULL, "stpwmt"); + if (IS_ERR(wmt_dev)) + goto error; +#endif + +#if 0 + pWmtDevCtx = wmt_drv_create(); + if (!pWmtDevCtx) { + WMT_ERR_FUNC("wmt_drv_create() fails\n"); + goto error; + } + ret = wmt_drv_init(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_init() fails (%d)\n", ret); + goto error; + } + WMT_INFO_FUNC("stp_btmcb_reg\n"); + wmt_cdev_btmcb_reg(); + ret = wmt_drv_start(pWmtDevCtx); + if (ret) { + WMT_ERR_FUNC("wmt_drv_start() fails (%d)\n", ret); + goto error; + } +#endif + ret = wmt_lib_init(); + if (ret) { + WMT_ERR_FUNC("wmt_lib_init() fails (%d)\n", ret); + goto error; + } +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_setup(); +#endif + +#if CFG_WMT_PROC_FOR_AEE + wmt_dev_proc_for_aee_setup(); +#endif + + WMT_INFO_FUNC("wmt_dev register thermal cb\n"); + wmt_lib_register_thermal_ctrl_cb(wmt_dev_tm_temp_query); + wmt_dev_bgw_desense_init(); + gWmtInitDone = 1; + wake_up(&gWmtInitWq); + osal_sleepable_lock_init(&g_es_lr_lock); + INIT_WORK(&gPwrOnOffWork, wmt_pwr_on_off_handler); +#ifdef CONFIG_EARLYSUSPEND + register_early_suspend(&wmt_early_suspend_handler); + WMT_INFO_FUNC("register_early_suspend finished\n"); +#else + wmt_fb_notifier.notifier_call = wmt_fb_notifier_callback; + ret = fb_register_client(&wmt_fb_notifier); + if (ret) + WMT_ERR_FUNC("wmt register fb_notifier failed! ret(%d)\n", ret); + else + WMT_INFO_FUNC("wmt register fb_notifier OK!\n"); +#endif + WMT_INFO_FUNC("success\n"); + return 0; + +error: + wmt_lib_deinit(); +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif +#if WMT_CREATE_NODE_DYNAMIC + if (!(IS_ERR(wmt_dev))) + device_destroy(wmt_class, devID); + if (!(IS_ERR(wmt_class))) { + class_destroy(wmt_class); + wmt_class = NULL; + } +#endif + + if (cdevErr == 0) + cdev_del(&gWmtCdev); + + if (ret == 0) { + unregister_chrdev_region(devID, WMT_DEV_NUM); + gWmtMajor = -1; + } + + WMT_ERR_FUNC("fail\n"); + + return -1; +} + +static void WMT_exit(void) +{ + dev_t dev = MKDEV(gWmtMajor, 0); + + osal_sleepable_lock_deinit(&g_es_lr_lock); +#ifdef CONFIG_EARLYSUSPEND + unregister_early_suspend(&wmt_early_suspend_handler); + WMT_INFO_FUNC("unregister_early_suspend finished\n"); +#else + fb_unregister_client(&wmt_fb_notifier); +#endif + + wmt_dev_bgw_desense_deinit(); + + wmt_lib_register_thermal_ctrl_cb(NULL); + + wmt_lib_deinit(); + +#if CFG_WMT_DBG_SUPPORT + wmt_dev_dbg_remove(); +#endif + +#if CFG_WMT_PROC_FOR_AEE + wmt_dev_proc_for_aee_remove(); +#endif +#if WMT_CREATE_NODE_DYNAMIC + if (wmt_dev) { + device_destroy(wmt_class, dev); + wmt_dev = NULL; + } + if (wmt_class) { + class_destroy(wmt_class); + wmt_class = NULL; + } +#endif + cdev_del(&gWmtCdev); + unregister_chrdev_region(dev, WMT_DEV_NUM); + gWmtMajor = -1; + + stp_drv_exit(); + + WMT_INFO_FUNC("done\n"); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + +int mtk_wcn_soc_common_drv_init(void) +{ + return WMT_init(); + +} +EXPORT_SYMBOL(mtk_wcn_soc_common_drv_init); +void mtk_wcn_soc_common_drv_exit(void) +{ + return WMT_exit(); +} +EXPORT_SYMBOL(mtk_wcn_soc_common_drv_exit); + +#else +module_init(WMT_init); +module_exit(WMT_exit); +#endif +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("MediaTek Inc WCN"); +MODULE_DESCRIPTION("MTK WCN combo driver for WMT function"); + +module_param(gWmtMajor, uint, 0); diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c new file mode 100644 index 0000000000000..8d5c23732c1c7 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pri/wmt_exp.c @@ -0,0 +1,610 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-EXP]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" + +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +wmt_wlan_probe_cb mtk_wcn_wlan_probe = NULL; +wmt_wlan_remove_cb mtk_wcn_wlan_remove = NULL; +wmt_wlan_bus_cnt_get_cb mtk_wcn_wlan_bus_tx_cnt = NULL; +wmt_wlan_bus_cnt_clr_cb mtk_wcn_wlan_bus_tx_cnt_clr = NULL; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +OSAL_BIT_OP_VAR gBtWifiGpsState; +OSAL_BIT_OP_VAR gGpsFmState; +UINT32 gWifiProbed = 0; +UINT32 gWmtDbgLvl = WMT_LOG_ERR; +MTK_WCN_BOOL g_pwr_off_flag = MTK_WCN_BOOL_TRUE; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static MTK_WCN_BOOL mtk_wcn_wmt_func_ctrl(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static MTK_WCN_BOOL mtk_wcn_wmt_func_ctrl(ENUM_WMTDRV_TYPE_T type, ENUM_WMT_OPID_T opId) +{ + P_OSAL_OP pOp; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + + pOp->op.opId = opId; + pOp->op.au4OpData[0] = type; + if (WMTDRV_TYPE_WIFI == type) + pSignal->timeoutValue = 4000; + /*donot block system server/init/netd from longer than 5s, in case of ANR happens*/ + else + pSignal->timeoutValue = (WMT_OPID_FUNC_ON == pOp->op.opId) ? MAX_FUNC_ON_TIME : MAX_FUNC_OFF_TIME; + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + + /*do not check return value, we will do this either way */ + wmt_lib_host_awake_get(); + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + wmt_lib_host_awake_put(); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + wmt_lib_host_awake_put(); + + if (MTK_WCN_BOOL_FALSE == bRet) + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n", pOp->op.opId, pOp->op.au4OpData[0]); + else + WMT_WARN_FUNC("OPID(%d) type(%d) ok\n", pOp->op.opId, pOp->op.au4OpData[0]); + + return bRet; +} + +#if WMT_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) +#else +MTK_WCN_BOOL mtk_wcn_wmt_func_off(ENUM_WMTDRV_TYPE_T type) +#endif +{ + MTK_WCN_BOOL ret; + + if (type == WMTDRV_TYPE_BT) + osal_printtimeofday("############ BT OFF ====>"); + + ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_OFF); + + if (type == WMTDRV_TYPE_BT) + osal_printtimeofday("############ BT OFF <===="); + + return ret; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_func_off); +#endif + +#if WMT_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) +#else +MTK_WCN_BOOL mtk_wcn_wmt_func_on(ENUM_WMTDRV_TYPE_T type) +#endif +{ + MTK_WCN_BOOL ret; + + if (type == WMTDRV_TYPE_BT) + osal_printtimeofday("############ BT ON ====>"); + + ret = mtk_wcn_wmt_func_ctrl(type, WMT_OPID_FUNC_ON); + + if (type == WMTDRV_TYPE_BT) + osal_printtimeofday(" ############BT ON <===="); + + return ret; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_func_on); +#endif + +VOID mtk_wcn_wmt_func_ctrl_for_plat(UINT32 on, ENUM_WMTDRV_TYPE_T type) +{ + if (on) + mtk_wcn_wmt_func_on(type); + else + mtk_wcn_wmt_func_off(type); +} + +/* +return value: +enable/disable thermal sensor function: true(1)/false(0) +read thermal sensor function:thermal value + +*/ +#if WMT_EXP_HID_API_EXPORT +INT8 _mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) +#else +INT8 mtk_wcn_wmt_therm_ctrl(ENUM_WMTTHERM_TYPE_T eType) +#endif +{ + P_OSAL_OP pOp; + P_WMT_OP pOpData; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + /*parameter validation check */ + if (WMTTHERM_MAX < eType || WMTTHERM_ENABLE > eType) { + WMT_ERR_FUNC("invalid thermal control command (%d)\n", eType); + return MTK_WCN_BOOL_FALSE; + } + + /*check if chip support thermal control function or not */ + bRet = wmt_lib_is_therm_ctrl_support(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_ERR_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pOpData = &pOp->op; + pOpData->opId = WMT_OPID_THERM_CTRL; + /*parameter fill */ + pOpData->au4OpData[0] = eType; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort!\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return -1; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); + /*0xFF means read error occurs */ + /*will return to function driver */ + pOpData->au4OpData[1] = (eType == WMTTHERM_READ) ? 0xFF : MTK_WCN_BOOL_FALSE; + } else { + WMT_INFO_FUNC("OPID(%d) type(%d) return(%d) ok\n\n", + pOpData->opId, pOpData->au4OpData[0], pOpData->au4OpData[1]); + } + /*return value will be put to lxop->op.au4OpData[1] */ + WMT_DBG_FUNC("therm ctrl type(%d), iRet(0x%08x)\n", eType, pOpData->au4OpData[1]); + return (INT8) pOpData->au4OpData[1]; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_therm_ctrl); +#endif + +#if WMT_EXP_HID_API_EXPORT +ENUM_WMTHWVER_TYPE_T _mtk_wcn_wmt_hwver_get(VOID) +#else +ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID) +#endif +{ + /* TODO: [ChangeFeature][GeorgeKuo] Reconsider usage of this type */ + /* TODO: how do we extend for new chip and newer revision? */ + /* TODO: This way is hard to extend */ + return wmt_lib_get_icinfo(WMTCHIN_MAPPINGHWVER); +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_hwver_get); +#endif + +#if WMT_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) +#else +MTK_WCN_BOOL mtk_wcn_wmt_dsns_ctrl(ENUM_WMTDSNS_TYPE_T eType) +#endif +{ + P_OSAL_OP pOp; + P_WMT_OP pOpData; + MTK_WCN_BOOL bRet; + P_OSAL_SIGNAL pSignal; + + if (WMTDSNS_MAX <= eType) { + WMT_ERR_FUNC("invalid desense control command (%d)\n", eType); + return MTK_WCN_BOOL_FALSE; + } + + /*check if chip support thermal control function or not */ + bRet = wmt_lib_is_dsns_ctrl_support(); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_ERR_FUNC("thermal ctrl function not supported\n"); + return MTK_WCN_BOOL_FALSE; + } + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pOpData = &pOp->op; + pOpData->opId = WMT_OPID_DSNS; + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + /*parameter fill */ + if ((WMTDSNS_FM_DISABLE <= eType) && (WMTDSNS_FM_GPS_ENABLE >= eType)) { + pOpData->au4OpData[0] = WMTDRV_TYPE_FM; + pOpData->au4OpData[1] = eType; + } + + WMT_INFO_FUNC("OPID(%d) type(%d) start\n", pOp->op.opId, pOp->op.au4OpData[0]); + + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,OPID(%d) type(%d) abort\n", pOp->op.opId, pOp->op.au4OpData[0]); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + if (MTK_WCN_BOOL_FALSE == bRet) + WMT_WARN_FUNC("OPID(%d) type(%d) fail\n\n", pOpData->opId, pOpData->au4OpData[0]); + else + WMT_INFO_FUNC("OPID(%d) type(%d) ok\n\n", pOpData->opId, pOpData->au4OpData[0]); + + return bRet; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_dsns_ctrl); +#endif + +#if WMT_EXP_HID_API_EXPORT +INT32 _mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) +#else +INT32 mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb) +#endif +{ + return (INT32) wmt_lib_msgcb_reg(eType, pCb); +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_reg); +#endif + +#if WMT_EXP_HID_API_EXPORT +INT32 _mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) +#else +INT32 mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType) +#endif +{ + return (INT32) wmt_lib_msgcb_unreg(eType); +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_msgcb_unreg); +#endif + +#if WMT_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) +#else +INT32 mtk_wcn_stp_wmt_sdio_op_reg(PF_WMT_SDIO_PSOP own_cb) +#endif +{ + wmt_lib_ps_set_sdio_psop(own_cb); + return 0; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_op_reg); +#endif + +#if WMT_EXP_HID_API_EXPORT +INT32 _mtk_wcn_stp_wmt_sdio_host_awake(VOID) +#else +INT32 mtk_wcn_stp_wmt_sdio_host_awake(VOID) +#endif +{ + wmt_lib_ps_irq_cb(); + return 0; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_stp_wmt_sdio_host_awake); +#endif + +#if WMT_EXP_HID_API_EXPORT +MTK_WCN_BOOL _mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) +#else +MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason) +#endif +{ + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_WARN_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + wmt_lib_set_host_assert_info(type, reason, 1); + + pSignal = &pOp->signal; + + pOp->op.opId = WMT_OPID_CMD_TEST; + + pSignal->timeoutValue = MAX_EACH_WMT_CMD; + /*this test command should be run with usb cable connected, so no host awake is needed */ + /* wmt_lib_host_awake_get(); */ + pOp->op.au4OpData[0] = 0; + + /*wake up chip first */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed,assert flow abort\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + + bRet = wmt_lib_put_act_op(pOp); + ENABLE_PSM_MONITOR(); + + /* wmt_lib_host_awake_put(); */ + WMT_INFO_FUNC("CMD_TEST, opid (%d), par(%d, %d), ret(%d), result(%s)\n", + pOp->op.opId, + pOp->op.au4OpData[0], + pOp->op.au4OpData[1], bRet, MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + return bRet; +} +#if !WMT_EXP_HID_API_EXPORT +EXPORT_SYMBOL(mtk_wcn_wmt_assert); +#endif + +INT8 mtk_wcn_wmt_co_clock_flag_get(void) +{ + return wmt_lib_co_clock_get(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_co_clock_flag_get); + +INT32 mtk_wcn_wmt_system_state_reset(void) +{ + osal_memset(&gBtWifiGpsState, 0, osal_sizeof(gBtWifiGpsState)); + osal_memset(&gGpsFmState, 0, osal_sizeof(gGpsFmState)); + + return 0; +} + +INT32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo) +{ + INT32 iRet = -1; + + if (!pWmtWlanCbInfo) { + WMT_ERR_FUNC("wlan cb info in null!\n"); + return -1; + } + + WMT_INFO_FUNC("wmt wlan cb register\n"); + mtk_wcn_wlan_probe = pWmtWlanCbInfo->wlan_probe_cb; + mtk_wcn_wlan_remove = pWmtWlanCbInfo->wlan_remove_cb; + mtk_wcn_wlan_bus_tx_cnt = pWmtWlanCbInfo->wlan_bus_cnt_get_cb; + mtk_wcn_wlan_bus_tx_cnt_clr = pWmtWlanCbInfo->wlan_bus_cnt_clr_cb; + + if (gWifiProbed) { + WMT_INFO_FUNC("wlan has been done power on,call probe directly\n"); + iRet = (*mtk_wcn_wlan_probe) (); + if (!iRet) { + WMT_INFO_FUNC("call wlan probe OK when do wlan register to wmt\n"); + gWifiProbed = 0; + } else { + WMT_ERR_FUNC("call wlan probe fail(%d) when do wlan register to wmt\n", iRet); + return -2; + } + } + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_wlan_reg); + +INT32 mtk_wcn_wmt_wlan_unreg(void) +{ + WMT_INFO_FUNC("wmt wlan cb unregister\n"); + mtk_wcn_wlan_probe = NULL; + mtk_wcn_wlan_remove = NULL; + mtk_wcn_wlan_bus_tx_cnt = NULL; + mtk_wcn_wlan_bus_tx_cnt_clr = NULL; + + return 0; +} +EXPORT_SYMBOL(mtk_wcn_wmt_wlan_unreg); + +MTK_WCN_BOOL mtk_wcn_set_connsys_power_off_flag(MTK_WCN_BOOL value) +{ + g_pwr_off_flag = value; + if (g_pwr_off_flag) + WMT_DBG_FUNC("enable connsys power off flag\n"); + else + WMT_INFO_FUNC("disable connsys power off, maybe need trigger coredump!\n"); + return g_pwr_off_flag; +} +EXPORT_SYMBOL(mtk_wcn_set_connsys_power_off_flag); + +#ifdef MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT +VOID mtk_wcn_wmt_exp_init(void) +{ + MTK_WCN_WMT_EXP_CB_INFO wmtExpCb = { + + .wmt_func_on_cb = _mtk_wcn_wmt_func_on, + .wmt_func_off_cb = _mtk_wcn_wmt_func_off, + .wmt_therm_ctrl_cb = _mtk_wcn_wmt_therm_ctrl, + .wmt_hwver_get_cb = _mtk_wcn_wmt_hwver_get, + .wmt_dsns_ctrl_cb = _mtk_wcn_wmt_dsns_ctrl, + .wmt_msgcb_reg_cb = _mtk_wcn_wmt_msgcb_reg, + .wmt_msgcb_unreg_cb = _mtk_wcn_wmt_msgcb_unreg, + .wmt_sdio_op_reg_cb = _mtk_wcn_stp_wmt_sdio_op_reg, + .wmt_sdio_host_awake_cb = _mtk_wcn_stp_wmt_sdio_host_awake, + .wmt_assert_cb = _mtk_wcn_wmt_assert + }; + + mtk_wcn_wmt_exp_cb_reg(&wmtExpCb); +} + +VOID mtk_wcn_wmt_exp_deinit(void) +{ + mtk_wcn_wmt_exp_cb_unreg(); +} +#ifdef CONFIG_MTK_COMBO_ANT +/* + ctrlId: get ram code status opId or ram code download opId + pBuf: pointer to ANT ram code + length: total length of ANT ram code +*/ +ENUM_WMT_ANT_RAM_STATUS mtk_wcn_wmt_ant_ram_ctrl(ENUM_WMT_ANT_RAM_CTRL ctrlId, PUINT8 pBuf, + UINT32 length, ENUM_WMT_ANT_RAM_SEQ seq) +{ + ENUM_WMT_ANT_RAM_STATUS eRet = 0; + P_OSAL_OP pOp = NULL; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_FALSE; + P_OSAL_SIGNAL pSignal; + + /*1. parameter validation check */ + /*for WMT_ANT_RAM_GET_STATUS, ignore pBuf and length */ + /*for WMT_ANT_RAM_DOWNLOAD, + pBuf must not be NULL, kernel space memory pointer + length must be large than 0 */ + + if ((WMT_ANT_RAM_GET_STATUS > ctrlId) || (WMT_ANT_RAM_CTRL_MAX <= ctrlId)) { + WMT_ERR_FUNC("error ctrlId:%d detected.\n", ctrlId); + eRet = WMT_ANT_RAM_PARA_ERR; + return eRet; + } + + if ((WMT_ANT_RAM_DOWNLOAD == ctrlId) && + ((NULL == pBuf) || + (0 >= length) || + (1000 < length) || (seq >= WMT_ANT_RAM_SEQ_MAX) || (seq < WMT_ANT_RAM_START_PKT))) { + eRet = WMT_ANT_RAM_PARA_ERR; + WMT_ERR_FUNC + ("error parameter detected, ctrlId:%d, pBuf:%p,length(0x%x),seq(%d) .\n", + ctrlId, pBuf, length, seq); + return eRet; + } + /*get WMT opId */ + pOp = wmt_lib_get_free_op(); + if (!pOp) { + WMT_DBG_FUNC("get_free_lxop fail\n"); + return MTK_WCN_BOOL_FALSE; + } + + pSignal = &pOp->signal; + pSignal->timeoutValue = + (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? MAX_FUNC_ON_TIME : MAX_EACH_WMT_CMD; + + pOp->op.opId = + (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? WMT_OPID_ANT_RAM_DOWN : WMT_OPID_ANT_RAM_STA_GET; + pOp->op.au4OpData[0] = (size_t) pBuf; + pOp->op.au4OpData[1] = length; + pOp->op.au4OpData[2] = seq; + + + /*disable PSM monitor */ + if (DISABLE_PSM_MONITOR()) { + WMT_ERR_FUNC("wake up failed\n"); + wmt_lib_put_op_to_free_queue(pOp); + return MTK_WCN_BOOL_FALSE; + } + /*wakeup wmtd thread */ + bRet = wmt_lib_put_act_op(pOp); + + /*enable PSM monitor */ + ENABLE_PSM_MONITOR(); + + WMT_DBG_FUNC("CMD_TEST, opid (%d), ret(%d),retVal(%zu) result(%s)\n", + pOp->op.opId, + bRet, + pOp->op.au4OpData[2], MTK_WCN_BOOL_FALSE == bRet ? "failed" : "succeed"); + + /*check return value and return result */ + if (MTK_WCN_BOOL_FALSE == bRet) { + eRet = WMT_ANT_RAM_OP_ERR; + } else { + eRet = (WMT_ANT_RAM_DOWNLOAD == ctrlId) ? + WMT_ANT_RAM_DOWN_OK : + ((1 == pOp->op.au4OpData[2]) ? WMT_ANT_RAM_EXIST : WMT_ANT_RAM_NOT_EXIST); + } + + return eRet; + +} +EXPORT_SYMBOL(mtk_wcn_wmt_ant_ram_ctrl); +#endif + +#endif +VOID mtk_wcn_wmt_set_wifi_ver(UINT32 Value) +{ + wmt_lib_soc_set_wifiver(Value); +} +EXPORT_SYMBOL(mtk_wcn_wmt_set_wifi_ver); diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile new file mode 100644 index 0000000000000..eb37baf87b025 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/Makefile @@ -0,0 +1,27 @@ +ifeq ($(CONFIG_MTK_COMBO), y) + +ccflags-y += \ + -I$(src)/../../linux/include \ + -I$(src)/../../linux/pri/include \ + -I$(src)/../../core/include \ + -I$(src)/../../include \ + -I$(src)/../include \ + -I$(src)/../../../common_detect \ + -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach \ + -DMTK_BT_HCI=1 + +ccflags-y += -DWMT_CREATE_NODE_DYNAMIC=1 + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) + ccflags-y += -DCFG_TC1_FEATURE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +obj-y += osal.o \ + bgw_desense.o \ + wmt_idc.o +obj-$(CONFIG_MTK_COMBO_BT) += stp_chrdev_bt.o +obj-$(CONFIG_MTK_COMBO_WIFI) += wmt_chrdev_wifi.o + +endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c new file mode 100644 index 0000000000000..11e45aa130872 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/bgw_desense.c @@ -0,0 +1,153 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "bgw_desense.h" + +static struct sock *g_nl_sk; +/* static struct sockaddr_nl src_addr, des_addr; */ +/* static struct iovec iov; */ +static int pid; +/* static struct msghdr msg; */ + +void bgw_destroy_netlink_kernel(void) +{ + if (g_nl_sk != NULL) { + /* sock_release(g_nl_sk->sk_socket); */ + netlink_kernel_release(g_nl_sk); + MSG("release socket\n"); + return; + } + ERR("no socket yet\n"); +} + +void send_command_to_daemon(const int command /*struct sk_buff *skb */) +{ +/* + struct iphdr *iph; + struct ethhdr *ehdr; + */ + struct nlmsghdr *nlh; + struct sk_buff *nl_skb; + int res; + + MSG("here we will send command to native daemon\n"); +/* if(skb == NULL) + { + ERR("invalid sk_buff\n"); + return; + } +*/ + if (!g_nl_sk) { + ERR("invalid socket\n"); + return; + } + if (pid == 0) { + ERR("invalid native process pid\n"); + return; + } + /*alloc data buffer for sending to native */ + /*malloc data space at least 1500 bytes, which is ethernet data length */ + nl_skb = alloc_skb(NLMSG_SPACE(MAX_NL_MSG_LEN), GFP_ATOMIC); + if (nl_skb == NULL) { + ERR("malloc skb error\n"); + return; + } + MSG("malloc data space done\n"); + /* + ehdr = eth_hdr(skb); + iph = ip_hdr(skb); + */ + +/* nlh = NLMSG_PUT(nl_skb, 0, 0, 0, NLMSG_SPACE(1500)-sizeof(struct nlmsghdr)); */ + nlh = nlmsg_put(nl_skb, 0, 0, 0, MAX_NL_MSG_LEN, 0); + if (nlh == NULL) { + MSG("nlh is NULL\n"); + kfree_skb(nl_skb); + return; + } + NETLINK_CB(nl_skb).portid = 0; + +/* memcpy(NLMSG_DATA(nlh), ACK, 5); */ + *(char *)NLMSG_DATA(nlh) = command; + res = netlink_unicast(g_nl_sk, nl_skb, pid, MSG_DONTWAIT); + if (res == 0) { + MSG("send to user space process error\n"); + return; + } + ERR("send to user space process done, data length = %d\n", res); +} + +static void nl_data_handler(struct sk_buff *__skb) +{ + struct sk_buff *skb; + struct nlmsghdr *nlh; + int i; + int len; + char str[128]; + + MSG("we got netlink message\n"); + len = NLMSG_SPACE(MAX_NL_MSG_LEN); + skb = skb_get(__skb); + if (skb == NULL) + ERR("skb_get return NULL"); + if (skb->len >= NLMSG_SPACE(0)) { /*presume there is 5byte payload at leaset */ + MSG("length is enough\n"); + nlh = nlmsg_hdr(skb); /* point to data which include in skb */ + memcpy(str, NLMSG_DATA(nlh), sizeof(str)); + for (i = 0; i < 3; i++) + MSG("str[%d = %c]", i, str[i]); + MSG("str[0] = %d, str[1] = %d, str[2] = %d\n", str[0], str[1], str[2]); + if (str[0] == 'B' && str[1] == 'G' && str[2] == 'W') { + MSG("got native daemon init command, record it's pid\n"); + pid = nlh->nlmsg_pid; /*record the native process PID */ + MSG("native daemon pid is %d\n", pid); + } else { + ERR("this is not BGW message, ignore it\n"); + return; + } + } else { + ERR("not engouth data length\n"); + return; + } + + kfree_skb(skb); + + send_command_to_daemon(ACK); +} + +int bgw_init_socket(void) +{ + struct netlink_kernel_cfg cfg; + + memset(&cfg, 0, sizeof(cfg)); + cfg.input = nl_data_handler; + + g_nl_sk = __netlink_kernel_create(&init_net, NETLINK_TEST, THIS_MODULE, &cfg); + + if (g_nl_sk == NULL) { + ERR("netlink_kernel_create error\n"); + return -1; + } + MSG("netlink_kernel_create ok\n"); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c new file mode 100644 index 0000000000000..959b68de24311 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/osal.c @@ -0,0 +1,1211 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "osal_typedef.h" +#include "osal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1) */ +static UINT16 const crc16_table[256] = { + 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, + 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, + 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, + 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, + 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, + 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, + 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, + 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, + 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, + 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, + 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, + 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, + 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, + 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, + 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, + 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, + 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, + 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, + 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, + 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, + 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, + 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, + 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, + 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, + 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, + 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, + 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, + 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, + 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, + 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, + 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, + 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 +}; + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*string operations*/ +_osal_inline_ UINT32 osal_strlen(const char *str) +{ + return strlen(str); +} + +_osal_inline_ INT32 osal_strcmp(const char *dst, const char *src) +{ + return strcmp(dst, src); +} + +_osal_inline_ INT32 osal_strncmp(const char *dst, const char *src, UINT32 len) +{ + return strncmp(dst, src, len); +} + +_osal_inline_ char *osal_strcpy(char *dst, const char *src) +{ + return strcpy(dst, src); +} + +_osal_inline_ char *osal_strncpy(char *dst, const char *src, UINT32 len) +{ + return strncpy(dst, src, len); +} + +_osal_inline_ char *osal_strcat(char *dst, const char *src) +{ + return strcat(dst, src); +} + +_osal_inline_ char *osal_strncat(char *dst, const char *src, UINT32 len) +{ + return strncat(dst, src, len); +} + +_osal_inline_ char *osal_strchr(const char *str, UINT8 c) +{ + return strchr(str, c); +} + +_osal_inline_ char *osal_strsep(char **str, const char *c) +{ + return strsep(str, c); +} + +_osal_inline_ int osal_strtol(const char *str, UINT32 adecimal, long *res) +{ + return kstrtol(str, adecimal, res); +} + +_osal_inline_ char *osal_strstr(char *str1, const char *str2) +{ + return strstr(str1, str2); +} + +INT32 osal_snprintf(char *buf, UINT32 len, const char *fmt, ...) +{ + INT32 iRet = 0; + va_list args; + + /*va_start(args, fmt); */ + va_start(args, fmt); + /*iRet = snprintf(buf, len, fmt, args); */ + iRet = vsnprintf(buf, len, fmt, args); + va_end(args); + + return iRet; +} + +INT32 osal_err_print(const char *str, ...) +{ + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + pr_err("%s", tempString); + + return 0; +} + +INT32 osal_dbg_print(const char *str, ...) +{ + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + pr_debug("%s", tempString); + + return 0; +} + +INT32 osal_warn_print(const char *str, ...) +{ + va_list args; + char tempString[DBG_LOG_STR_SIZE]; + + va_start(args, str); + vsnprintf(tempString, DBG_LOG_STR_SIZE, str, args); + va_end(args); + + pr_warn("%s", tempString); + + return 0; +} + +INT32 osal_dbg_assert(INT32 expr, const char *file, INT32 line) +{ + if (!expr) { + pr_warn("%s (%d)\n", file, line); + /*BUG_ON(!expr); */ +#ifdef CFG_COMMON_GPIO_DBG_PIN +/* package this part */ + mt_set_gpio_out(GPIO70, GPIO_OUT_ZERO); + pr_warn("toggle GPIO70\n"); + udelay(10); + mt_set_gpio_out(GPIO70, GPIO_OUT_ONE); +#endif + return 1; + } + return 0; + +} + +INT32 osal_dbg_assert_aee(const char *module, const char *detail_description) +{ + osal_err_print("[WMT-ASSERT]" "[E][Module]:%s, [INFO]%s\n", module, detail_description); + +#ifdef WMT_PLAT_ALPS + /* aee_kernel_warning(module,detail_description); */ + aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_WCN_ISSUE_INFO, module, detail_description); +#endif + return 0; +} + +INT32 osal_sprintf(char *str, const char *format, ...) +{ + INT32 iRet = 0; + va_list args; + + va_start(args, format); + iRet = vsnprintf(str, DBG_LOG_STR_SIZE, format, args); + va_end(args); + + return iRet; +} + +_osal_inline_ VOID *osal_malloc(UINT32 size) +{ + return vmalloc(size); +} + +_osal_inline_ VOID osal_free(const VOID *dst) +{ + vfree(dst); +} + +_osal_inline_ VOID *osal_memset(VOID *buf, INT32 i, UINT32 len) +{ + return memset(buf, i, len); +} + +_osal_inline_ VOID *osal_memcpy(VOID *dst, const VOID *src, UINT32 len) +{ +#ifdef CONFIG_MTK_WCN_ARM64 + char *tmp; + const char *s; + size_t i; + + tmp = dst; + s = src; + for (i = 0; i < len; i++) + tmp[i] = s[i]; + + return dst; + +#else + return memcpy(dst, src, len); +#endif +} + +_osal_inline_ INT32 osal_memcmp(const VOID *buf1, const VOID *buf2, UINT32 len) +{ + return memcmp(buf1, buf2, len); +} + +_osal_inline_ UINT16 osal_crc16(const UINT8 *buffer, const UINT32 length) +{ + UINT16 crc = 0; + UINT32 i = 0; + + /* FIXME: Add STP checksum feature */ + crc = 0; + for (i = 0; i < length; i++, buffer++) + crc = (crc >> 8) ^ crc16_table[(crc ^ (*buffer)) & 0xff]; + + return crc; +} + +_osal_inline_ VOID osal_thread_show_stack(P_OSAL_THREAD pThread) +{ + return show_stack(pThread->pThread, NULL); +} + +/* + *OSAL layer Thread Opeartion related APIs + * + * +*/ +_osal_inline_ INT32 osal_thread_create(P_OSAL_THREAD pThread) +{ + pThread->pThread = kthread_create(pThread->pThreadFunc, pThread->pThreadData, pThread->threadName); + if (NULL == pThread->pThread) + return -1; + + return 0; +} + +_osal_inline_ INT32 osal_thread_run(P_OSAL_THREAD pThread) +{ + if (pThread->pThread) { + wake_up_process(pThread->pThread); + return 0; + } else { + return -1; + } +} + +_osal_inline_ INT32 osal_thread_stop(P_OSAL_THREAD pThread) +{ + INT32 iRet; + + if ((pThread) && (pThread->pThread)) { + iRet = kthread_stop(pThread->pThread); + /* pThread->pThread = NULL; */ + return iRet; + } + return -1; +} + +_osal_inline_ INT32 osal_thread_should_stop(P_OSAL_THREAD pThread) +{ + if ((pThread) && (pThread->pThread)) + return kthread_should_stop(); + else + return 1; + +} + +_osal_inline_ INT32 +osal_thread_wait_for_event(P_OSAL_THREAD pThread, P_OSAL_EVENT pEvent, P_OSAL_EVENT_CHECKER pChecker) +{ + /* P_DEV_WMT pDevWmt;*/ + + if ((pThread) && (pThread->pThread) && (pEvent) && (pChecker)) { + /* pDevWmt = (P_DEV_WMT)(pThread->pThreadData);*/ + return wait_event_interruptible(pEvent->waitQueue, (/*!RB_EMPTY(&pDevWmt->rActiveOpQ) || */ + osal_thread_should_stop(pThread) + || (*pChecker) (pThread))); + } + return -1; +} + +_osal_inline_ INT32 osal_thread_destroy(P_OSAL_THREAD pThread) +{ + if (pThread && (pThread->pThread)) { + kthread_stop(pThread->pThread); + pThread->pThread = NULL; + } + return 0; +} + +/* + *OSAL layer Signal Opeartion related APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +_osal_inline_ INT32 osal_signal_init(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + init_completion(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +_osal_inline_ INT32 osal_wait_for_signal(P_OSAL_SIGNAL pSignal) +{ + if (pSignal) { + wait_for_completion_interruptible(&pSignal->comp); + return 0; + } else { + return -1; + } +} + +_osal_inline_ INT32 osal_wait_for_signal_timeout(P_OSAL_SIGNAL pSignal) +{ + /* return wait_for_completion_interruptible_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); */ + /* [ChangeFeature][George] gps driver may be closed by -ERESTARTSYS. + * Avoid using *interruptible" version in order to complete our jobs, such + * as function off gracefully. + */ + return wait_for_completion_timeout(&pSignal->comp, msecs_to_jiffies(pSignal->timeoutValue)); +} + +_osal_inline_ INT32 osal_raise_signal(P_OSAL_SIGNAL pSignal) +{ + /* TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! */ + complete(&pSignal->comp); + return 0; +} + +_osal_inline_ INT32 osal_signal_deinit(P_OSAL_SIGNAL pSignal) +{ + /* TODO:[FixMe][GeorgeKuo]: DO sanity check here!!! */ + pSignal->timeoutValue = 0; + return 0; +} + +/* + *OSAL layer Event Opeartion related APIs + *initialization + *wait for signal + *wait for signal timerout + *raise signal + *destroy a signal + * +*/ + +INT32 osal_event_init(P_OSAL_EVENT pEvent) +{ + init_waitqueue_head(&pEvent->waitQueue); + + return 0; +} + +INT32 osal_wait_for_event(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), void *cond_pa) +{ + return wait_event_interruptible(pEvent->waitQueue, condition(cond_pa)); +} + +INT32 osal_wait_for_event_timeout(P_OSAL_EVENT pEvent, INT32(*condition) (PVOID), void *cond_pa) +{ + return wait_event_interruptible_timeout(pEvent->waitQueue, condition(cond_pa), + msecs_to_jiffies(pEvent->timeoutValue)); +} + +INT32 osal_trigger_event(P_OSAL_EVENT pEvent) +{ + INT32 ret = 0; + + wake_up_interruptible(&pEvent->waitQueue); + return ret; +} + +INT32 osal_event_deinit(P_OSAL_EVENT pEvent) +{ + return 0; +} + +_osal_inline_ long osal_wait_for_event_bit_set(P_OSAL_EVENT pEvent, unsigned long *pState, UINT32 bitOffset) +{ + UINT32 ms = pEvent->timeoutValue; + + if (ms != 0) { + return wait_event_interruptible_timeout(pEvent->waitQueue, test_bit(bitOffset, pState), + msecs_to_jiffies(ms)); + } else { + return wait_event_interruptible(pEvent->waitQueue, test_bit(bitOffset, pState)); + } + +} + +_osal_inline_ long osal_wait_for_event_bit_clr(P_OSAL_EVENT pEvent, unsigned long *pState, UINT32 bitOffset) +{ + UINT32 ms = pEvent->timeoutValue; + + if (ms != 0) { + return wait_event_interruptible_timeout(pEvent->waitQueue, !test_bit(bitOffset, pState), + msecs_to_jiffies(ms)); + } else { + return wait_event_interruptible(pEvent->waitQueue, !test_bit(bitOffset, pState)); + } + +} + +/* + *bit test and set/clear operations APIs + * + * +*/ +#if OS_BIT_OPS_SUPPORT +#define osal_bit_op_lock(x) +#define osal_bit_op_unlock(x) +#else + +_osal_inline_ INT32 osal_bit_op_lock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} + +_osal_inline_ INT32 osal_bit_op_unlock(P_OSAL_UNSLEEPABLE_LOCK pLock) +{ + + return 0; +} +#endif +_osal_inline_ INT32 osal_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + osal_bit_op_lock(&(pData->opLock)); + clear_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return 0; +} + +_osal_inline_ INT32 osal_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + osal_bit_op_lock(&(pData->opLock)); + set_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return 0; +} + +_osal_inline_ INT32 osal_test_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + + osal_bit_op_lock(&(pData->opLock)); + iRet = test_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; +} + +_osal_inline_ INT32 osal_test_and_clear_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + + osal_bit_op_lock(&(pData->opLock)); + iRet = test_and_clear_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; + +} + +_osal_inline_ INT32 osal_test_and_set_bit(UINT32 bitOffset, P_OSAL_BIT_OP_VAR pData) +{ + UINT32 iRet = 0; + + osal_bit_op_lock(&(pData->opLock)); + iRet = test_and_set_bit(bitOffset, &pData->data); + osal_bit_op_unlock(&(pData->opLock)); + return iRet; +} + +/* + *tiemr operations APIs + *create + *stop + * modify + *create + *delete + * +*/ + +INT32 osal_timer_create(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + /*init_timer(timer); + timer->function = pTimer->timeoutHandler; + timer->data = (unsigned long)pTimer->timeroutHandlerData;*/ + timer_setup(timer,pTimer->timeoutHandler,0); + return 0; +} + +INT32 osal_timer_start(P_OSAL_TIMER pTimer, UINT32 ms) +{ + + struct timer_list *timer = &pTimer->timer; + + timer->expires = jiffies + (ms / (1000 / HZ)); + add_timer(timer); + return 0; +} + +INT32 osal_timer_stop(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + del_timer(timer); + return 0; +} + +INT32 osal_timer_stop_sync(P_OSAL_TIMER pTimer) +{ + struct timer_list *timer = &pTimer->timer; + + del_timer_sync(timer); + return 0; +} + +INT32 osal_timer_modify(P_OSAL_TIMER pTimer, UINT32 ms) +{ + + mod_timer(&pTimer->timer, jiffies + (ms) / (1000 / HZ)); + return 0; +} + +INT32 _osal_fifo_init(OSAL_FIFO *pFifo, UINT8 *buf, UINT32 size) +{ + struct kfifo *fifo = NULL; + INT32 ret = -1; + + if (!pFifo) { + pr_err("pFifo must be !NULL\n"); + return -1; + } + if (pFifo->pFifoBody) { + pr_err("pFifo->pFifoBody must be NULL\n"); + pr_err("pFifo(0x%p), pFifo->pFifoBody(0x%p)\n", pFifo, pFifo->pFifoBody); + return -1; + } + fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC); + if (!buf) { + /*fifo's buffer is not ready, we allocate automatically */ + ret = kfifo_alloc(fifo, size, /*GFP_KERNEL */ GFP_ATOMIC); + } else { + if (is_power_of_2(size)) { + kfifo_init(fifo, buf, size); + ret = 0; + } else { + kfifo_free(fifo); + fifo = NULL; + ret = -1; + } + } + + pFifo->pFifoBody = fifo; + return (ret < 0) ? (-1) : (0); +} + +INT32 _osal_fifo_deinit(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_free(fifo); + + return 0; +} + +INT32 _osal_fifo_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_size(fifo); + + return ret; +} + +/*returns unused bytes in fifo*/ +INT32 _osal_fifo_avail_size(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_avail(fifo); + + return ret; +} + +/*returns used bytes in fifo*/ +INT32 _osal_fifo_len(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_len(fifo); + + return ret; +} + +INT32 _osal_fifo_is_empty(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_empty(fifo); + + return ret; +} + +INT32 _osal_fifo_is_full(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + ret = kfifo_is_full(fifo); + + return ret; +} + +INT32 _osal_fifo_data_in(OSAL_FIFO *pFifo, const VOID *buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_avail_size(pFifo))) { + ret = kfifo_in(fifo, buf, len); + } else { + pr_err("%s: kfifo_in, error, len = %d, _osal_fifo_avail_size = %d, buf=%p\n", + __func__, len, _osal_fifo_avail_size(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_data_out(OSAL_FIFO *pFifo, void *buf, UINT32 len) +{ + struct kfifo *fifo = NULL; + INT32 ret = 0; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo && buf && (len <= _osal_fifo_len(pFifo))) { + ret = kfifo_out(fifo, buf, len); + } else { + pr_err("%s: kfifo_out, error, len = %d, osal_fifo_len = %d, buf=%p\n", + __func__, len, _osal_fifo_len(pFifo), buf); + + ret = 0; + } + + return ret; +} + +INT32 _osal_fifo_reset(OSAL_FIFO *pFifo) +{ + struct kfifo *fifo = NULL; + + if (!pFifo || !pFifo->pFifoBody) { + pr_err("%s:pFifo = NULL or pFifo->pFifoBody = NULL, error\n", __func__); + return -1; + } + + fifo = (struct kfifo *)pFifo->pFifoBody; + + if (fifo) + kfifo_reset(fifo); + + return 0; +} + +INT32 osal_fifo_init(P_OSAL_FIFO pFifo, UINT8 *buffer, UINT32 size) +{ + if (!pFifo) { + pr_err("%s:pFifo = NULL, error\n", __func__); + return -1; + } + + pFifo->FifoInit = _osal_fifo_init; + pFifo->FifoDeInit = _osal_fifo_deinit; + pFifo->FifoSz = _osal_fifo_size; + pFifo->FifoAvailSz = _osal_fifo_avail_size; + pFifo->FifoLen = _osal_fifo_len; + pFifo->FifoIsEmpty = _osal_fifo_is_empty; + pFifo->FifoIsFull = _osal_fifo_is_full; + pFifo->FifoDataIn = _osal_fifo_data_in; + pFifo->FifoDataOut = _osal_fifo_data_out; + pFifo->FifoReset = _osal_fifo_reset; + + if (NULL != pFifo->pFifoBody) { + pr_err("%s:Because pFifo room is avialable, we clear the room and allocate them again.\n", __func__); + pFifo->FifoDeInit(pFifo->pFifoBody); + pFifo->pFifoBody = NULL; + } + + pFifo->FifoInit(pFifo, buffer, size); + + return 0; +} + +VOID osal_fifo_deinit(P_OSAL_FIFO pFifo) +{ + if (pFifo) + pFifo->FifoDeInit(pFifo); + else { + pr_err("%s:pFifo = NULL, error\n", __func__); + return; + } + kfree(pFifo->pFifoBody); +} + +INT32 osal_fifo_reset(P_OSAL_FIFO pFifo) +{ + INT32 ret = -1; + + if (pFifo) { + ret = pFifo->FifoReset(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = -1; + } + return ret; +} + +UINT32 osal_fifo_in(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataIn(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_out(P_OSAL_FIFO pFifo, PUINT8 buffer, UINT32 size) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoDataOut(pFifo, buffer, size); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_len(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoLen(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_sz(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_avail(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoAvailSz(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_is_empty(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsEmpty(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + + return ret; +} + +UINT32 osal_fifo_is_full(P_OSAL_FIFO pFifo) +{ + UINT32 ret = 0; + + if (pFifo) { + ret = pFifo->FifoIsFull(pFifo); + } else { + pr_err("%s:pFifo = NULL, error\n", __func__); + ret = 0; + } + return ret; +} + +INT32 osal_wake_lock_init(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + #ifdef CONFIG_PM_WAKELOCKS + wakeup_source_init(&pLock->wake_lock, pLock->name); + #else + wake_lock_init(&pLock->wake_lock, WAKE_LOCK_SUSPEND, pLock->name); + #endif + return 0; +} + +INT32 osal_wake_lock_deinit(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + #ifdef CONFIG_PM_WAKELOCKS + wakeup_source_trash(&pLock->wake_lock); + #else + wake_lock_destroy(&pLock->wake_lock); + #endif + return 0; +} + +INT32 osal_wake_lock(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + #ifdef CONFIG_PM_WAKELOCKS + __pm_stay_awake(&pLock->wake_lock); + #else + wake_lock(&pLock->wake_lock); + #endif + + return 0; +} + +INT32 osal_wake_unlock(P_OSAL_WAKE_LOCK pLock) +{ + if (!pLock) + return -1; + + #ifdef CONFIG_PM_WAKELOCKS + __pm_relax(&pLock->wake_lock); + #else + wake_unlock(&pLock->wake_lock); + #endif + + return 0; + +} + +INT32 osal_wake_lock_count(P_OSAL_WAKE_LOCK pLock) +{ + INT32 count = 0; + + if (!pLock) + return -1; + + #ifdef CONFIG_PM_WAKELOCKS + count = pLock->wake_lock.active; + #else + count = wake_lock_active(&pLock->wake_lock); + #endif + return count; +} + +/* + *sleepable lock operations APIs + *init + *lock + *unlock + *destroy + * +*/ + +#if !defined(CONFIG_PROVE_LOCKING) +INT32 osal_unsleepable_lock_init(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_init(&(pUSL->lock)); + return 0; +} +#endif + +INT32 osal_lock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_lock_irqsave(&(pUSL->lock), pUSL->flag); + return 0; +} + +INT32 osal_unlock_unsleepable_lock(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + spin_unlock_irqrestore(&(pUSL->lock), pUSL->flag); + return 0; +} + +INT32 osal_unsleepable_lock_deinit(P_OSAL_UNSLEEPABLE_LOCK pUSL) +{ + return 0; +} + +/* + *unsleepable operations APIs + *init + *lock + *unlock + *destroy + + * +*/ + +#if !defined(CONFIG_PROVE_LOCKING) +INT32 osal_sleepable_lock_init(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_init(&pSL->lock); + return 0; +} +#endif + +INT32 osal_lock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + return mutex_lock_killable(&pSL->lock); +} + +INT32 osal_unlock_sleepable_lock(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_unlock(&pSL->lock); + return 0; +} + +INT32 osal_sleepable_lock_deinit(P_OSAL_SLEEPABLE_LOCK pSL) +{ + mutex_destroy(&pSL->lock); + return 0; +} + +INT32 osal_sleep_ms(UINT32 ms) +{ + msleep(ms); + return 0; +} + +INT32 osal_udelay(UINT32 us) +{ + udelay(us); + return 0; +} + +INT32 osal_gettimeofday(PINT32 sec, PINT32 usec) +{ + INT32 ret = 0; + struct timeval now; + + do_gettimeofday(&now); + + if (sec != NULL) + *sec = now.tv_sec; + else + ret = -1; + + if (usec != NULL) + *usec = now.tv_usec; + else + ret = -1; + + return ret; +} + +INT32 osal_printtimeofday(const PUINT8 prefix) +{ + INT32 ret; + INT32 sec; + INT32 usec; + + ret = osal_gettimeofday(&sec, &usec); + ret += osal_dbg_print("%s>sec=%d, usec=%d\n", prefix, sec, usec); + + return ret; +} + +VOID osal_buffer_dump(const UINT8 *buf, const UINT8 *title, const UINT32 len, const UINT32 limit) +{ + INT32 k; + UINT32 dump_len; + + pr_warn("start of dump>[%s] len=%d, limit=%d,", title, len, limit); + + dump_len = ((0 != limit) && (len > limit)) ? limit : len; +#if 0 + if (limit != 0) + len = (len > limit) ? (limit) : (len); + +#endif + + for (k = 0; k < dump_len; k++) { + if ((k != 0) && (k % 16 == 0)) + pr_cont("\n"); + pr_cont("0x%02x ", buf[k]); + } + pr_warn("op.opId : 0xFFFFFFFF; +} + +MTK_WCN_BOOL osal_op_is_wait_for_signal(P_OSAL_OP pOp) +{ + return (pOp && pOp->signal.timeoutValue) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE; +} + +VOID osal_op_raise_signal(P_OSAL_OP pOp, INT32 result) +{ + if (pOp) { + pOp->result = result; + osal_raise_signal(&pOp->signal); + } +} + +VOID osal_set_op_result(P_OSAL_OP pOp, INT32 result) +{ + if (pOp) + pOp->result = result; + +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c new file mode 100644 index 0000000000000..190fa3944d801 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/stp_chrdev_bt.c @@ -0,0 +1,899 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if WMT_CREATE_NODE_DYNAMIC +#include +#endif +#include + +#include "osal_typedef.h" +#include "stp_exp.h" +#include "wmt_exp.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +#ifdef MTK_BT_HCI +#define MTK_BT_DEBUG 0 +#include +#include +#endif + + +#define BT_DRIVER_NAME "mtk_stp_BT_chrdev" +#define BT_DEV_MAJOR 192 /* Never used number */ + +#define PFX "[MTK-BT] " +#define BT_LOG_DBG 3 +#define BT_LOG_INFO 2 +#define BT_LOG_WARN 1 +#define BT_LOG_ERR 0 + +#define COMBO_IOC_MAGIC 0xb0 +#define COMBO_IOCTL_FW_ASSERT _IOWR(COMBO_IOC_MAGIC, 0, int) +#define COMBO_IOCTL_BT_IC_HW_VER _IOWR(COMBO_IOC_MAGIC, 1, void*) +#define COMBO_IOCTL_BT_IC_FW_VER _IOWR(COMBO_IOC_MAGIC, 2, void*) +#define COMBO_IOC_BT_HWVER _IOWR(COMBO_IOC_MAGIC, 3, void*) + +static UINT32 gDbgLevel = BT_LOG_INFO; + +#define BT_DBG_FUNC(fmt, arg...) \ + do { if (gDbgLevel >= BT_LOG_DBG) \ + pr_debug(PFX "%s: " fmt, __func__ , ##arg); \ + } while (0) +#define BT_INFO_FUNC(fmt, arg...) \ + do { if (gDbgLevel >= BT_LOG_INFO) \ + pr_warn(PFX "%s: " fmt, __func__ , ##arg); \ + } while (0) +#define BT_WARN_FUNC(fmt, arg...) \ + do { if (gDbgLevel >= BT_LOG_WARN) \ + pr_err(PFX "%s: " fmt, __func__ , ##arg); \ + } while (0) +#define BT_ERR_FUNC(fmt, arg...) \ + do { if (gDbgLevel >= BT_LOG_ERR) \ + pr_err(PFX "%s: " fmt, __func__ , ##arg); \ + } while (0) + +#define VERSION "1.0" + +#ifdef MTK_BT_HCI + +#define NUM_REASSEMBLY 32 +struct mtk_hci { + struct hci_dev *hdev; + struct work_struct work; + struct sk_buff_head txq; + struct sk_buff *reassembly[NUM_REASSEMBLY]; +}; + +static struct mtk_hci mtk_hci; + +#endif + +#if WMT_CREATE_NODE_DYNAMIC +struct class *stpbt_class = NULL; +struct device *stpbt_dev = NULL; +#endif + +static INT32 BT_devs = 1; /* Device count */ +static INT32 BT_major = BT_DEV_MAJOR; /* Dynamic allocation */ +module_param(BT_major, uint, 0); +static struct cdev BT_cdev; + +#define BT_BUFFER_SIZE 2048 +static UINT8 i_buf[BT_BUFFER_SIZE]; /* Input buffer of read() */ +static UINT8 o_buf[BT_BUFFER_SIZE]; /* Output buffer of write() */ + +static struct semaphore wr_mtx, rd_mtx; +/* Wait queue for poll and read */ +static wait_queue_head_t inq; +static DECLARE_WAIT_QUEUE_HEAD(BT_wq); +static INT32 flag; +/* Reset flag for whole chip reset senario */ +static volatile INT32 rstflag; + +#ifdef MTK_BT_HCI +static int hci_reassembly(struct hci_dev *hdev, int type, void *data, + int count, __u8 index) +{ + int len = 0; + int hlen = 0; + int offset = 0; + int remain = count; + struct sk_buff *skb; + struct bt_skb_cb *scb; + u16 opcode = 0; + unsigned char *pdata = data; + + struct mtk_hci *info = NULL; + struct hci_event_hdr *ehdr = NULL; + struct hci_ev_cmd_complete *ev = NULL; + struct hci_rp_read_local_ext_features *ext = NULL; + + info = hci_get_drvdata(hdev); + if ( NULL == info ) { + printk(KERN_ERR "mtk_bt_hci: invalid info point\n"); + return 0; + } + + if ((type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) || + index >= NUM_REASSEMBLY) + return -EILSEQ; + + skb = info->reassembly[index]; + + if (!skb) { + switch (type) { + case HCI_ACLDATA_PKT: + len = HCI_MAX_FRAME_SIZE; + hlen = HCI_ACL_HDR_SIZE; + break; + case HCI_EVENT_PKT: + len = HCI_MAX_EVENT_SIZE; + hlen = HCI_EVENT_HDR_SIZE; + break; + case HCI_SCODATA_PKT: + len = HCI_MAX_SCO_SIZE; + hlen = HCI_SCO_HDR_SIZE; + break; + } + + skb = bt_skb_alloc(len, GFP_ATOMIC); + if (!skb) + return -ENOMEM; + + scb = (void *) skb->cb; + scb->expect = hlen; + scb->pkt_type = type; + + info->reassembly[index] = skb; + } + + while (count) { + scb = (void *) skb->cb; + len = min_t(uint, scb->expect, count); + + /* + * Workaround for MT7623+MT6625 BT: the max page in response of cmd READ_LOCAL_EXT_FEATURES + * should be 1, instead of 2, so changing it to 1 here + */ + + if (HCI_EVENT_PKT == type) + { + ehdr = (void *)pdata; + offset = sizeof(struct hci_event_hdr); + if ( HCI_EV_CMD_COMPLETE == ehdr->evt) + { + ev = (struct hci_ev_cmd_complete *)&pdata[offset]; + + offset += sizeof(struct hci_ev_cmd_complete); + + opcode = __le16_to_cpu(ev->opcode); + if(HCI_OP_READ_LOCAL_EXT_FEATURES == opcode) { + ext = (struct hci_rp_read_local_ext_features *) &pdata[offset]; + if( !ext->status && ext->max_page >= 2) { + pr_info("%s: this workaround is applied for mediatek BT\n", __func__); + ext->max_page = 1; + } + } + + } + } + + memcpy(skb_put(skb, len), data, len); + + count -= len; + data += len; + scb->expect -= len; + remain = count; + + switch (type) { + case HCI_EVENT_PKT: + if (skb->len == HCI_EVENT_HDR_SIZE) { + struct hci_event_hdr *h = hci_event_hdr(skb); + + scb->expect = h->plen; + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + info->reassembly[index] = NULL; + return -ENOMEM; + } + } + + break; + + case HCI_ACLDATA_PKT: + if (skb->len == HCI_ACL_HDR_SIZE) { + struct hci_acl_hdr *h = hci_acl_hdr(skb); + + scb->expect = __le16_to_cpu(h->dlen); + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + info->reassembly[index] = NULL; + return -ENOMEM; + } + } + break; + + case HCI_SCODATA_PKT: + if (skb->len == HCI_SCO_HDR_SIZE) { + struct hci_sco_hdr *h = hci_sco_hdr(skb); + + scb->expect = h->dlen; + + if (skb_tailroom(skb) < scb->expect) { + kfree_skb(skb); + info->reassembly[index] = NULL; + return -ENOMEM; + } + } + break; + } + + if (scb->expect == 0) { + /* Complete frame */ + + bt_cb(skb)->pkt_type = type; + hci_recv_frame(hdev, skb); + + info->reassembly[index] = NULL; + return remain; + } + } + + return remain; +} + +int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count) +{ + int rem = 0; + + if (type < HCI_ACLDATA_PKT || type > HCI_EVENT_PKT) + return -EILSEQ; + + while (count) { + rem = hci_reassembly(hdev, type, data, count, type - 1); + if (rem < 0) + return rem; + + data += (count - rem); + count = rem; + } + + return rem; +} +#endif + +#ifdef MTK_BT_HCI +void +hex_dump(char *prefix, char *p, int len) +{ + int i; + + pr_err("%s ", prefix); + for (i = 0; i < len; i++) + pr_err("%02x ", (*p++ & 0xff)); + pr_err("\n"); +} + +static int +mtk_bt_hci_open(struct hci_dev *hdev) +{ + int err = 0; + +#if MTK_BT_DEBUG == 1 + pr_err("# %s\n", __func__); +#endif + + err = mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT); + if (err != MTK_WCN_BOOL_TRUE) { + pr_err("%s func on failed with %d\n", __func__, err); + return -ENODEV; + } + + set_bit(HCI_RUNNING, &hdev->flags); + + mtk_wcn_stp_set_bluez(1); + + return 0; +} + +static int +mtk_bt_hci_close(struct hci_dev *hdev) +{ + int err = 0; + +#if MTK_BT_DEBUG == 1 + pr_err("# %s\n", __func__); +#endif + + mtk_wcn_stp_set_bluez(0); + + clear_bit(HCI_RUNNING, &hdev->flags); + + err = mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + if (err != MTK_WCN_BOOL_TRUE) { + pr_err("%s func off failed with %d\n", __func__, err); + return -EIO; + } + + return 0; +} + +static void +mtk_bt_hci_work(struct work_struct *work) +{ + int err; + struct sk_buff *skb; + +#if MTK_BT_DEBUG == 1 + pr_err("# %s\n", __func__); +#endif + + while ((skb = skb_dequeue(&mtk_hci.txq))) { + skb_push(skb, 1); + skb->data[0] = bt_cb(skb)->pkt_type; + +#if MTK_BT_DEBUG == 1 + hex_dump(">>", skb->data, skb->len); +#endif + + err = mtk_wcn_stp_send_data(skb->data, skb->len, BT_TASK_INDX); + if (err < 0) { + pr_err("%s err=%d\n", __func__, err); + mtk_hci.hdev->stat.err_tx++; + skb_queue_head(&mtk_hci.txq, skb); + break; + } + + mtk_hci.hdev->stat.byte_tx += skb->len; + kfree_skb(skb); + } +} + +static int +mtk_bt_hci_send(struct hci_dev *hdev, struct sk_buff *skb) +{ +#if MTK_BT_DEBUG == 1 + pr_err("# %s\n", __func__); +#endif + + if (mtk_hci.hdev && !test_bit(HCI_RUNNING, &mtk_hci.hdev->flags)) + return -EBUSY; + + switch (bt_cb(skb)->pkt_type) { + case HCI_COMMAND_PKT: + mtk_hci.hdev->stat.cmd_tx++; + break; + + case HCI_ACLDATA_PKT: + mtk_hci.hdev->stat.acl_tx++; + break; + + case HCI_SCODATA_PKT: + mtk_hci.hdev->stat.sco_tx++; + break; + + default: + return -EILSEQ; + } + + skb_queue_tail(&mtk_hci.txq, skb); + schedule_work(&mtk_hci.work); + + return 0; +} + +static int +mtk_bt_hci_flush(struct hci_dev *hdev) +{ + pr_err("%s: todo\n", __func__); + + return 0; +} + +static void +mtk_bt_hci_receive(const PUINT8 data, INT32 size) +{ + int err; + +#if MTK_BT_DEBUG == 1 + pr_err("# %s\n", __func__); + hex_dump("<<", data, size); +#endif + + err = hci_recv_fragment(mtk_hci.hdev, data[0], (void *)&data[1], size - 1); + if (err < 0) + pr_err("%s: hci_recv_fragment failed with %d\n", __func__, err); + + if (mtk_hci.hdev) + mtk_hci.hdev->stat.byte_rx += size - 1; +} + +static void +mtk_bt_hci_notify(struct hci_dev *hdev, unsigned int evt) +{ + static const char * const notify_str[] = { + "null", + "HCI_NOTIFY_CONN_ADD", + "HCI_NOTIFY_CONN_DEL", + "HCI_NOTIFY_VOICE_SETTING" + }; + + if (evt > HCI_NOTIFY_VOICE_SETTING) + pr_info("%s event=0x%x\n", __func__, evt); + else + pr_info("%s event(%d)=%s\n", __func__, evt, notify_str[evt]); +} +#endif + +#ifdef MTK_BT_HCI + +int mtk_bt_hci_init(void) +{ + INT32 hci_err = 0; + + mtk_hci.hdev = hci_alloc_dev(); + if (!(mtk_hci.hdev)) { + mtk_hci.hdev = NULL; + BT_ERR_FUNC("%s hci_alloc_dev failed\n", __func__); + return -ENOMEM; + } + + mtk_hci.hdev->bus = HCI_SDIO; + mtk_hci.hdev->open = mtk_bt_hci_open; + mtk_hci.hdev->close = mtk_bt_hci_close; + mtk_hci.hdev->send = mtk_bt_hci_send; + mtk_hci.hdev->flush = mtk_bt_hci_flush; + mtk_hci.hdev->notify = mtk_bt_hci_notify; + SET_HCIDEV_DEV(mtk_hci.hdev, stpbt_dev); + + hci_set_drvdata(mtk_hci.hdev, &mtk_hci); + + mtk_wcn_stp_register_if_rx(mtk_bt_hci_receive); + + hci_err = hci_register_dev(mtk_hci.hdev); + if (hci_err) { + BT_ERR_FUNC("%s hci_register_dev failed with %d\n", __func__, hci_err); + hci_free_dev(mtk_hci.hdev); + mtk_hci.hdev = NULL; + return hci_err; + } + + skb_queue_head_init(&mtk_hci.txq); + INIT_WORK(&mtk_hci.work, mtk_bt_hci_work); + + return 0; +} +#endif + + +static VOID bt_cdev_rst_cb(ENUM_WMTDRV_TYPE_T src, + ENUM_WMTDRV_TYPE_T dst, ENUM_WMTMSG_TYPE_T type, PVOID buf, UINT32 sz) +{ + /* + Handle whole chip reset messages + */ + ENUM_WMTRSTMSG_TYPE_T rst_msg; + + if (sz <= sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + memcpy((PINT8)&rst_msg, (PINT8)buf, sz); + BT_DBG_FUNC("src = %d, dst = %d, type = %d, buf = 0x%x sz = %d, max = %d\n", src, + dst, type, rst_msg, sz, WMTRSTMSG_RESET_MAX); + if ((src == WMTDRV_TYPE_WMT) && (dst == WMTDRV_TYPE_BT) + && (type == WMTMSG_TYPE_RESET)) { + if (rst_msg == WMTRSTMSG_RESET_START) { + BT_INFO_FUNC("BT reset start!\n"); + rstflag = 1; + wake_up_interruptible(&inq); + + } else if (rst_msg == WMTRSTMSG_RESET_END) { + BT_INFO_FUNC("BT reset end!\n"); + rstflag = 2; + wake_up_interruptible(&inq); + } + } + } else { + /* Invalid message format */ + BT_WARN_FUNC("Invalid message format!\n"); + } +} + +VOID BT_event_cb(VOID) +{ + BT_DBG_FUNC("BT_event_cb()\n"); + + flag = 1; + + /* + * Finally, wake up any reader blocked in poll or read + */ + wake_up_interruptible(&inq); + wake_up(&BT_wq); +} + +unsigned int BT_poll(struct file *filp, poll_table *wait) +{ + UINT32 mask = 0; + +/* down(&wr_mtx); */ + /* + * The buffer is circular; it is considered full + * if "wp" is right behind "rp". "left" is 0 if the + * buffer is empty, and it is "1" if it is completely full. + */ + if (mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX)) { + poll_wait(filp, &inq, wait); + + if (!mtk_wcn_stp_is_rxqueue_empty(BT_TASK_INDX) || rstflag) + /* BT Rx queue has valid data, or whole chip reset occurs */ + mask |= POLLIN | POLLRDNORM; /* Readable */ + } else { + mask |= POLLIN | POLLRDNORM; /* Readable */ + } + + /* Do we need condition here? */ + mask |= POLLOUT | POLLWRNORM; /* Writable */ +/* up(&wr_mtx); */ + return mask; +} + +ssize_t BT_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = 0; + INT32 write_size; + INT32 written = 0; + + down(&wr_mtx); + + BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos); + if (rstflag) { + if (rstflag == 1) { /* Reset start */ + retval = -88; + BT_INFO_FUNC("%s: detect whole chip reset start\n", __func__); + } else if (rstflag == 2) { /* Reset end */ + retval = -99; + BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__); + } + goto OUT; + } + + if (count > 0) { + if (count < BT_BUFFER_SIZE) { + write_size = count; + } else { + write_size = BT_BUFFER_SIZE; + BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__); + } + + if (copy_from_user(&o_buf[0], &buf[0], write_size)) { + retval = -EFAULT; + goto OUT; + } + + written = mtk_wcn_stp_send_data(&o_buf[0], write_size, BT_TASK_INDX); + if (0 == written) { + retval = -ENOSPC; + /* No space is available, native program should not call BT_write with no delay */ + BT_ERR_FUNC + ("Packet length %zd, sent length %d, retval = %d\n", + count, written, retval); + } else { + retval = written; + } + + } else { + retval = -EFAULT; + BT_ERR_FUNC("Packet length %zd is not allowed, retval = %d\n", count, retval); + } + +OUT: + up(&wr_mtx); + return retval; +} + +ssize_t BT_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + static int chip_reset_count; + INT32 retval = 0; + + down(&rd_mtx); + + BT_DBG_FUNC("%s: count %zd pos %lld\n", __func__, count, *f_pos); + if (rstflag) { + if (rstflag == 1) { /* Reset start */ + retval = -88; + if ((chip_reset_count%500) == 0) + BT_INFO_FUNC("%s: detect whole chip reset start, %d\n", __func__, chip_reset_count); + chip_reset_count++; + } else if (rstflag == 2) { /* Reset end */ + retval = -99; + BT_INFO_FUNC("%s: detect whole chip reset end\n", __func__); + chip_reset_count = 0; + } + goto OUT; + } + + if (count > BT_BUFFER_SIZE) { + count = BT_BUFFER_SIZE; + BT_ERR_FUNC("%s: count > BT_BUFFER_SIZE\n", __func__); + } + + retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); + + while (retval == 0) { /* Got nothing, wait for STP's signal */ + /* + * If nonblocking mode, return directly. + * O_NONBLOCK is specified during open() + */ + if (filp->f_flags & O_NONBLOCK) { + BT_DBG_FUNC("Non-blocking BT_read\n"); + retval = -EAGAIN; + goto OUT; + } + + BT_DBG_FUNC("%s: wait_event 1\n", __func__); + wait_event(BT_wq, flag != 0); + BT_DBG_FUNC("%s: wait_event 2\n", __func__); + flag = 0; + retval = mtk_wcn_stp_receive_data(i_buf, count, BT_TASK_INDX); + BT_DBG_FUNC("%s: mtk_wcn_stp_receive_data returns %d\n", __func__, retval); + } + + /* Got something from STP driver */ + if (copy_to_user(buf, i_buf, retval)) { + retval = -EFAULT; + goto OUT; + } + +OUT: + up(&rd_mtx); + BT_DBG_FUNC("%s: retval = %d\n", __func__, retval); + return retval; +} + +/* int BT_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) */ +long BT_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + INT32 retval = 0; + MTK_WCN_BOOL bRet = MTK_WCN_BOOL_TRUE; + ENUM_WMTHWVER_TYPE_T hw_ver_sym = WMTHWVER_INVALID; + + BT_DBG_FUNC("%s: cmd: 0x%x\n", __func__, cmd); + + switch (cmd) { + case COMBO_IOC_BT_HWVER: + /* Get combo HW version */ + hw_ver_sym = mtk_wcn_wmt_hwver_get(); + BT_INFO_FUNC("%s: HW version = %d, sizeof(hw_ver_sym) = %zd\n", + __func__, hw_ver_sym, sizeof(hw_ver_sym)); + if (copy_to_user((int __user *)arg, &hw_ver_sym, sizeof(hw_ver_sym))) + retval = -EFAULT; + break; + + case COMBO_IOCTL_FW_ASSERT: + /* Trigger FW assert for debug */ + BT_INFO_FUNC("%s: Host trigger FW assert......, reason:%lu\n", __func__, arg); + bRet = mtk_wcn_wmt_assert(WMTDRV_TYPE_BT, arg); + if (bRet == MTK_WCN_BOOL_TRUE) { + BT_INFO_FUNC("Host trigger FW assert succeed\n"); + retval = 0; + } else { + BT_ERR_FUNC("Host trigger FW assert Failed\n"); + retval = (-EBUSY); + } + break; + case COMBO_IOCTL_BT_IC_HW_VER: + retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_HWVER); + break; + case COMBO_IOCTL_BT_IC_FW_VER: + retval = mtk_wcn_wmt_ic_info_get(WMTCHIN_FWVER); + break; + default: + retval = -EFAULT; + BT_ERR_FUNC("Unknown cmd (%d)\n", cmd); + break; + } + + return retval; +} + +long BT_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + return BT_unlocked_ioctl(filp, cmd, arg); +} + +static int BT_open(struct inode *inode, struct file *file) +{ + BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid); + + /* Turn on BT */ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_BT)) { + BT_WARN_FUNC("WMT turn on BT fail!\n"); + return -ENODEV; + } + + BT_INFO_FUNC("WMT turn on BT OK!\n"); + rstflag = 0; + + if (mtk_wcn_stp_is_ready()) { + + mtk_wcn_stp_set_bluez(0); + + BT_INFO_FUNC("Now it's in MTK Bluetooth Mode\n"); + BT_INFO_FUNC("STP is ready!\n"); + + BT_DBG_FUNC("Register BT event callback!\n"); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, BT_event_cb); + } else { + BT_ERR_FUNC("STP is not ready\n"); + mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT); + return -ENODEV; + } + + BT_DBG_FUNC("Register BT reset callback!\n"); + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_BT, bt_cdev_rst_cb); + + /* init_MUTEX(&wr_mtx); */ + sema_init(&wr_mtx, 1); + /* init_MUTEX(&rd_mtx); */ + sema_init(&rd_mtx, 1); + BT_INFO_FUNC("%s: finish\n", __func__); + + return 0; +} + +static int BT_close(struct inode *inode, struct file *file) +{ + BT_INFO_FUNC("%s: major %d minor %d pid %d\n", __func__, imajor(inode), iminor(inode), current->pid); + rstflag = 0; + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_BT); + mtk_wcn_stp_register_event_cb(BT_TASK_INDX, NULL); + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_BT)) { + BT_ERR_FUNC("WMT turn off BT fail!\n"); + return -EIO; /* Mostly, native program will not check this return value. */ + } + + BT_INFO_FUNC("WMT turn off BT OK!\n"); + + return 0; +} + +const struct file_operations BT_fops = { + .open = BT_open, + .release = BT_close, + .read = BT_read, + .write = BT_write, + /* .ioctl = BT_ioctl, */ + .unlocked_ioctl = BT_unlocked_ioctl, + .compat_ioctl = BT_compat_ioctl, + .poll = BT_poll +}; + + + +static int BT_init(void) +{ + dev_t dev = MKDEV(BT_major, 0); + INT32 alloc_ret = 0; + INT32 cdev_err = 0; + + /* Static allocate char device */ + alloc_ret = register_chrdev_region(dev, 1, BT_DRIVER_NAME); + if (alloc_ret) { + BT_ERR_FUNC("%s: Failed to register char device\n", __func__); + return alloc_ret; + } + + cdev_init(&BT_cdev, &BT_fops); + BT_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&BT_cdev, dev, BT_devs); + if (cdev_err) + goto error; + +#if WMT_CREATE_NODE_DYNAMIC + stpbt_class = class_create(THIS_MODULE, "stpbt"); + if (IS_ERR(stpbt_class)) + goto error; + stpbt_dev = device_create(stpbt_class, NULL, dev, NULL, "stpbt"); + if (IS_ERR(stpbt_dev)) + goto error; +#endif + + BT_INFO_FUNC("%s driver(major %d) installed\n", BT_DRIVER_NAME, BT_major); + + /* Init wait queue */ + init_waitqueue_head(&(inq)); + +#ifdef MTK_BT_HCI + mtk_bt_hci_init(); +#endif + + return 0; + +error: +#if WMT_CREATE_NODE_DYNAMIC + if (!IS_ERR(stpbt_dev)) + device_destroy(stpbt_class, dev); + if (!IS_ERR(stpbt_class)) { + class_destroy(stpbt_class); + stpbt_class = NULL; + } +#endif + if (cdev_err == 0) + cdev_del(&BT_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(dev, BT_devs); + + return -1; +} + +static void BT_exit(void) +{ + dev_t dev = MKDEV(BT_major, 0); + +#if WMT_CREATE_NODE_DYNAMIC + if (stpbt_dev) { + device_destroy(stpbt_class, dev); + stpbt_dev = NULL; + } + if (stpbt_class) { + class_destroy(stpbt_class); + stpbt_class = NULL; + } +#endif + + cdev_del(&BT_cdev); + unregister_chrdev_region(dev, BT_devs); + + BT_INFO_FUNC("%s driver removed\n", BT_DRIVER_NAME); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + +int mtk_wcn_stpbt_drv_init(void) +{ + return BT_init(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_init); + +void mtk_wcn_stpbt_drv_exit(void) +{ + return BT_exit(); +} +EXPORT_SYMBOL(mtk_wcn_stpbt_drv_exit); + +#else + +module_init(BT_init); +module_exit(BT_exit); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c new file mode 100644 index 0000000000000..3c7b2969c98a8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_chrdev_wifi.c @@ -0,0 +1,668 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "wmt_exp.h" +#include "stp_exp.h" + +MODULE_LICENSE("Dual BSD/GPL"); + +#define WIFI_DRIVER_NAME "mtk_wmt_WIFI_chrdev" +#define WIFI_DEV_MAJOR 155 + +#define PFX "[MTK-WIFI] " +#define WIFI_LOG_DBG 3 +#define WIFI_LOG_INFO 2 +#define WIFI_LOG_WARN 1 +#define WIFI_LOG_ERR 0 + +UINT32 gDbgLevel = WIFI_LOG_DBG; + +#define WIFI_DBG_FUNC(fmt, arg...)\ + do {if (gDbgLevel >= WIFI_LOG_DBG) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) +#define WIFI_INFO_FUNC(fmt, arg...)\ + do {if (gDbgLevel >= WIFI_LOG_INFO) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) +#define WIFI_WARN_FUNC(fmt, arg...)\ + do {if (gDbgLevel >= WIFI_LOG_WARN) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) +#define WIFI_ERR_FUNC(fmt, arg...)\ + do {if (gDbgLevel >= WIFI_LOG_ERR) printk(PFX "%s: " fmt, __func__ , ##arg); } while (0) +#define WIFI_TRC_FUNC(f)\ + do {if (gDbgLevel >= WIFI_LOG_DBG) printk(PFX "<%s> <%d>\n", __func__, __LINE__); } while (0) + +#define VERSION "1.0" + +#define WLAN_IFACE_NAME "wlan0" +#if CFG_TC1_FEATURE +#define LEGACY_IFACE_NAME "legacy0" +#endif + +enum { + WLAN_MODE_HALT, + WLAN_MODE_AP, + WLAN_MODE_STA_P2P, + WLAN_MODE_MAX +}; +static INT32 wlan_mode = WLAN_MODE_HALT; +static INT32 powered; +static INT8 *ifname = WLAN_IFACE_NAME; +#if CFG_TC1_FEATURE +volatile INT32 wlan_if_changed = 0; +EXPORT_SYMBOL(wlan_if_changed); +#endif + +typedef enum _ENUM_RESET_STATUS_T { + RESET_FAIL, + RESET_SUCCESS +} ENUM_RESET_STATUS_T; + +/* + * enable = 1, mode = 0 => init P2P network + * enable = 1, mode = 1 => init Soft AP network + * enable = 0 => uninit P2P/AP network + */ +typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { + UINT32 u4Enable; + UINT32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; +typedef INT32(*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); + +static set_p2p_mode pf_set_p2p_mode; +VOID register_set_p2p_mode_handler(set_p2p_mode handler) +{ + WIFI_INFO_FUNC("(pid %d) register set p2p mode handler %p\n", current->pid, handler); + pf_set_p2p_mode = handler; +} +EXPORT_SYMBOL(register_set_p2p_mode_handler); + +/* For dynamical debug level setting */ +/* copy of debug.h in wlan driver */ +#define DBG_CLASS_ERROR BIT(0) +#define DBG_CLASS_WARN BIT(1) +#define DBG_CLASS_STATE BIT(2) +#define DBG_CLASS_EVENT BIT(3) +#define DBG_CLASS_TRACE BIT(4) +#define DBG_CLASS_INFO BIT(5) +#define DBG_CLASS_LOUD BIT(6) +#define DBG_CLASS_TEMP BIT(7) +#define DBG_CLASS_MASK BITS(0, 7) + +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* For driver initial */ + DBG_HAL_IDX, /* For HAL(HW) Layer */ + DBG_INTR_IDX, /* For Interrupt */ + DBG_REQ_IDX, + DBG_TX_IDX, + DBG_RX_IDX, + DBG_RFTEST_IDX, /* For RF test mode */ + DBG_EMU_IDX, /* Developer specific */ + + DBG_SW1_IDX, /* Developer specific */ + DBG_SW2_IDX, /* Developer specific */ + DBG_SW3_IDX, /* Developer specific */ + DBG_SW4_IDX, /* Developer specific */ + + DBG_HEM_IDX, /* HEM */ + DBG_AIS_IDX, /* AIS */ + DBG_RLM_IDX, /* RLM */ + DBG_MEM_IDX, /* RLM */ + DBG_CNM_IDX, /* CNM */ + DBG_RSN_IDX, /* RSN */ + DBG_BSS_IDX, /* BSS */ + DBG_SCN_IDX, /* SCN */ + DBG_SAA_IDX, /* SAA */ + DBG_AAA_IDX, /* AAA */ + DBG_P2P_IDX, /* P2P */ + DBG_QM_IDX, /* QUE_MGT */ + DBG_SEC_IDX, /* SEC */ + DBG_BOW_IDX, /* BOW */ + DBG_WAPI_IDX, /* WAPI */ + DBG_ROAMING_IDX, /* ROAMING */ + + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; +/* end */ +typedef VOID(*set_dbg_level) (UINT8 modules[DBG_MODULE_NUM]); + +UINT8 wlan_dbg_level[DBG_MODULE_NUM]; +static set_dbg_level pf_set_dbg_level; +VOID register_set_dbg_level_handler(set_dbg_level handler) +{ + pf_set_dbg_level = handler; +} +EXPORT_SYMBOL(register_set_dbg_level_handler); + +static INT32 WIFI_devs = 1; +static INT32 WIFI_major = WIFI_DEV_MAJOR; +module_param(WIFI_major, uint, 0); +static struct cdev WIFI_cdev; +volatile INT32 retflag = 0; +static struct semaphore wr_mtx; + +#define WMT_CHECK_DO_CHIP_RESET() \ +do { \ + if (g_IsNeedDoChipReset) { \ + g_IsNeedDoChipReset = 0; \ + WIFI_ERR_FUNC("Do core dump and chip reset in %s line %d\n", __func__, __LINE__); \ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 40); \ + } \ +} while (0) + +/******************************************************************* + * WHOLE CHIP RESET PROCEDURE: + * + * WMTRSTMSG_RESET_START callback + * -> wlanRemove + * -> WMTRSTMSG_RESET_END callback + * + ******************************************************************* +*/ +/*-----------------------------------------------------------------*/ +/* + * Receiving RESET_START message + */ +/*-----------------------------------------------------------------*/ +INT32 wifi_reset_start(VOID) +{ + struct net_device *netdev = NULL; + PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; + + down(&wr_mtx); + + if (powered == 1) { + netdev = dev_get_by_name(&init_net, ifname); + if (netdev == NULL) { + WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); + } else { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + + if (pf_set_p2p_mode) { + if (pf_set_p2p_mode(netdev, p2pmode) != 0) + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + else + WIFI_INFO_FUNC("Turn off p2p/ap mode"); + } + dev_put(netdev); + netdev = NULL; + } + } else { + /* WIFI is off before whole chip reset, do nothing */ + } + + return 0; +} +EXPORT_SYMBOL(wifi_reset_start); + +/*-----------------------------------------------------------------*/ +/* + * Receiving RESET_END/RESET_END_FAIL message + */ +/*-----------------------------------------------------------------*/ +INT32 wifi_reset_end(ENUM_RESET_STATUS_T status) +{ + struct net_device *netdev = NULL; + PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; + INT32 wait_cnt = 0; + INT32 ret = -1; + + if (status == RESET_FAIL) { + /* whole chip reset fail, donot recover WIFI */ + ret = 0; + up(&wr_mtx); + } else if (status == RESET_SUCCESS) { + WIFI_WARN_FUNC("WIFI state recovering...\n"); + + if (powered == 1) { + /* WIFI is on before whole chip reset, reopen it now */ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + goto done; + } else { + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + } + + if (pf_set_p2p_mode == NULL) { + WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + while (netdev == NULL && wait_cnt < 10) { + WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); + msleep(300); + wait_cnt++; + netdev = dev_get_by_name(&init_net, ifname); + } + if (wait_cnt >= 10) { + WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); + goto done; + } + + if (wlan_mode == WLAN_MODE_STA_P2P) { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_STA_P2P); + ret = 0; + } + } else if (wlan_mode == WLAN_MODE_AP) { + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 1; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_WARN_FUNC("Set wlan mode %d\n", WLAN_MODE_AP); + ret = 0; + } + } +done: + if (netdev != NULL) + dev_put(netdev); + } else { + /* WIFI is off before whole chip reset, do nothing */ + ret = 0; + } + up(&wr_mtx); + } + + return ret; +} +EXPORT_SYMBOL(wifi_reset_end); + +static int WIFI_open(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + + return 0; +} + +static int WIFI_close(struct inode *inode, struct file *file) +{ + WIFI_INFO_FUNC("%s: major %d minor %d (pid %d)\n", __func__, imajor(inode), iminor(inode), current->pid); + retflag = 0; + + return 0; +} + +ssize_t WIFI_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) +{ + INT32 retval = -EIO; + INT8 local[12] = { 0 }; + struct net_device *netdev = NULL; + PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; + INT32 wait_cnt = 0; + + down(&wr_mtx); + if (count <= 0) { + WIFI_ERR_FUNC("WIFI_write invalid param\n"); + goto done; + } + + if (0 == copy_from_user(local, buf, (count > sizeof(local)) ? sizeof(local) : count)) { + local[11] = 0; + WIFI_INFO_FUNC("WIFI_write %s\n", local); + + if (local[0] == '0') { + if (powered == 0) { + WIFI_INFO_FUNC("WIFI is already power off!\n"); + retval = count; + wlan_mode = WLAN_MODE_HALT; + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + if (netdev == NULL) { + WIFI_ERR_FUNC("Fail to get %s net device\n", ifname); + } else { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + + if (pf_set_p2p_mode) { + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + } else { + WIFI_INFO_FUNC("Turn off p2p/ap mode"); + wlan_mode = WLAN_MODE_HALT; + } + } + dev_put(netdev); + netdev = NULL; + } + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_off(WMTDRV_TYPE_WIFI)) { + WIFI_ERR_FUNC("WMT turn off WIFI fail!\n"); + WMT_CHECK_DO_CHIP_RESET(); + } else { + WIFI_INFO_FUNC("WMT turn off WIFI OK!\n"); + powered = 0; + retval = count; + wlan_mode = WLAN_MODE_HALT; +#if CFG_TC1_FEATURE + ifname = WLAN_IFACE_NAME; + wlan_if_changed = 0; +#endif + } + } else if (local[0] == '1') { + if (powered == 1) { + WIFI_INFO_FUNC("WIFI is already power on!\n"); + retval = count; + goto done; + } + + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + WMT_CHECK_DO_CHIP_RESET(); + } else { + powered = 1; + retval = count; + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + wlan_mode = WLAN_MODE_HALT; + } + } else if (local[0] == 'D') { + INT32 k = 0; + /* + * 0: no debug + * 1: common debug output + * 2: more detials + * 3: verbose + */ + switch (local[1]) { + case '0': + for (k = 0; k < DBG_MODULE_NUM; k++) + wlan_dbg_level[k] = 0; + if (pf_set_dbg_level) + pf_set_dbg_level(wlan_dbg_level); + break; + case '1': + for (k = 0; k < DBG_MODULE_NUM; k++) { + wlan_dbg_level[k] = DBG_CLASS_ERROR | + DBG_CLASS_WARN | + DBG_CLASS_STATE | DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO; + } + wlan_dbg_level[DBG_TX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); + wlan_dbg_level[DBG_RX_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); + wlan_dbg_level[DBG_REQ_IDX] &= ~(DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO); + wlan_dbg_level[DBG_INTR_IDX] = 0; + wlan_dbg_level[DBG_MEM_IDX] = 0; + if (pf_set_dbg_level) + pf_set_dbg_level(wlan_dbg_level); + break; + case '2': + for (k = 0; k < DBG_MODULE_NUM; k++) { + wlan_dbg_level[k] = DBG_CLASS_ERROR | + DBG_CLASS_WARN | + DBG_CLASS_STATE | DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO; + } + wlan_dbg_level[DBG_INTR_IDX] = 0; + wlan_dbg_level[DBG_MEM_IDX] = 0; + if (pf_set_dbg_level) + pf_set_dbg_level(wlan_dbg_level); + break; + case '3': + for (k = 0; k < DBG_MODULE_NUM; k++) { + wlan_dbg_level[k] = DBG_CLASS_ERROR | + DBG_CLASS_WARN | + DBG_CLASS_STATE | + DBG_CLASS_EVENT | DBG_CLASS_TRACE | DBG_CLASS_INFO | DBG_CLASS_LOUD; + } + if (pf_set_dbg_level) + pf_set_dbg_level(wlan_dbg_level); + break; + default: + break; + } + } else if (local[0] == 'S' || local[0] == 'P' || local[0] == 'A') { + if (powered == 0) { + /* If WIFI is off, turn on WIFI first */ + if (MTK_WCN_BOOL_FALSE == mtk_wcn_wmt_func_on(WMTDRV_TYPE_WIFI)) { + WIFI_ERR_FUNC("WMT turn on WIFI fail!\n"); + WMT_CHECK_DO_CHIP_RESET(); + goto done; + } else { + powered = 1; + WIFI_INFO_FUNC("WMT turn on WIFI success!\n"); + wlan_mode = WLAN_MODE_HALT; + } + } + + if (pf_set_p2p_mode == NULL) { + WIFI_ERR_FUNC("Set p2p mode handler is NULL\n"); + goto done; + } + + netdev = dev_get_by_name(&init_net, ifname); + while (netdev == NULL && wait_cnt < 10) { + WIFI_ERR_FUNC("Fail to get %s net device, sleep 300ms\n", ifname); + msleep(300); + wait_cnt++; + netdev = dev_get_by_name(&init_net, ifname); + } + if (wait_cnt >= 10) { + WIFI_ERR_FUNC("Get %s net device timeout\n", ifname); + goto done; + } + + if ((wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'S' || local[0] == 'P')) || + (wlan_mode == WLAN_MODE_AP && (local[0] == 'A'))) { + WIFI_INFO_FUNC("WIFI is already in mode %d!\n", wlan_mode); + retval = count; + goto done; + } + + if ((wlan_mode == WLAN_MODE_AP && (local[0] == 'S' || local[0] == 'P')) || + (wlan_mode == WLAN_MODE_STA_P2P && (local[0] == 'A'))) { + p2pmode.u4Enable = 0; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Turn off p2p/ap mode fail"); + goto done; + } + } + + if (local[0] == 'S' || local[0] == 'P') { +#if CFG_TC1_FEATURE + /* Restore NIC name to wlan0 */ + rtnl_lock(); + if (strcmp(ifname, WLAN_IFACE_NAME) != 0) { + if (dev_change_name(netdev, WLAN_IFACE_NAME) != 0) { + WIFI_ERR_FUNC("netdev name change to %s fail\n", WLAN_IFACE_NAME); + rtnl_unlock(); + goto done; + } else { + WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, + WLAN_IFACE_NAME); + ifname = WLAN_IFACE_NAME; + wlan_if_changed = 0; + } + } + rtnl_unlock(); +#endif + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 0; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_STA_P2P); + wlan_mode = WLAN_MODE_STA_P2P; + retval = count; + } + } else if (local[0] == 'A') { +#if CFG_TC1_FEATURE + /* Change NIC name to legacy0, since wlan0 is used for AP */ + rtnl_lock(); + if (strcmp(ifname, LEGACY_IFACE_NAME) != 0) { + if (dev_change_name(netdev, LEGACY_IFACE_NAME) != 0) { + WIFI_ERR_FUNC("netdev name change to %s fail\n", LEGACY_IFACE_NAME); + rtnl_unlock(); + goto done; + } else { + WIFI_INFO_FUNC("netdev name changed %s --> %s\n", ifname, + LEGACY_IFACE_NAME); + ifname = LEGACY_IFACE_NAME; + wlan_if_changed = 1; + } + } + rtnl_unlock(); +#endif + p2pmode.u4Enable = 1; + p2pmode.u4Mode = 1; + if (pf_set_p2p_mode(netdev, p2pmode) != 0) { + WIFI_ERR_FUNC("Set wlan mode fail\n"); + } else { + WIFI_INFO_FUNC("Set wlan mode %d --> %d\n", wlan_mode, WLAN_MODE_AP); + wlan_mode = WLAN_MODE_AP; + retval = count; + } + } + dev_put(netdev); + netdev = NULL; + } + } +done: + if (netdev != NULL) + dev_put(netdev); + + up(&wr_mtx); + return retval; +} + +const struct file_operations WIFI_fops = { + .open = WIFI_open, + .release = WIFI_close, + .write = WIFI_write, +}; + +#if WMT_CREATE_NODE_DYNAMIC +struct class *wmtwifi_class = NULL; +#endif + +static int WIFI_init(void) +{ + dev_t dev = MKDEV(WIFI_major, 0); + INT32 alloc_ret = 0; + INT32 cdev_err = 0; +#if WMT_CREATE_NODE_DYNAMIC + struct device *wmtwifi_dev = NULL; +#endif + + /* static allocate chrdev */ + alloc_ret = register_chrdev_region(dev, 1, WIFI_DRIVER_NAME); + if (alloc_ret) { + WIFI_ERR_FUNC("Fail to register chrdev\n"); + return alloc_ret; + } + + cdev_init(&WIFI_cdev, &WIFI_fops); + WIFI_cdev.owner = THIS_MODULE; + + cdev_err = cdev_add(&WIFI_cdev, dev, WIFI_devs); + if (cdev_err) + goto error; + +#if WMT_CREATE_NODE_DYNAMIC /* mknod replace */ + wmtwifi_class = class_create(THIS_MODULE, "wmtWifi"); + if (IS_ERR(wmtwifi_class)) + goto error; + wmtwifi_dev = device_create(wmtwifi_class, NULL, dev, NULL, "wmtWifi"); + if (wmtwifi_dev == NULL) + goto error; + if (IS_ERR(wmtwifi_dev)) + goto error; +#endif + + sema_init(&wr_mtx, 1); + + WIFI_INFO_FUNC("%s driver(major %d) installed.\n", WIFI_DRIVER_NAME, WIFI_major); + retflag = 0; + wlan_mode = WLAN_MODE_HALT; + pf_set_p2p_mode = NULL; + + return 0; + +error: +#if WMT_CREATE_NODE_DYNAMIC + if (!IS_ERR(wmtwifi_dev)) + device_destroy(wmtwifi_class, dev); + if (!IS_ERR(wmtwifi_class)) { + class_destroy(wmtwifi_class); + wmtwifi_class = NULL; + } +#endif + + if (cdev_err == 0) + cdev_del(&WIFI_cdev); + + if (alloc_ret == 0) + unregister_chrdev_region(dev, WIFI_devs); + + return -1; +} + +static void WIFI_exit(void) +{ + dev_t dev = MKDEV(WIFI_major, 0); + + retflag = 0; + +#if WMT_CREATE_NODE_DYNAMIC + device_destroy(wmtwifi_class, dev); + class_destroy(wmtwifi_class); + wmtwifi_class = NULL; +#endif + + cdev_del(&WIFI_cdev); + unregister_chrdev_region(dev, WIFI_devs); + + WIFI_INFO_FUNC("%s driver removed.\n", WIFI_DRIVER_NAME); +} + +#ifdef MTK_WCN_REMOVE_KERNEL_MODULE + +INT32 mtk_wcn_wmt_wifi_init(VOID) +{ + return WIFI_init(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_wifi_init); + +VOID mtk_wcn_wmt_wifi_exit(VOID) +{ + return WIFI_exit(); +} +EXPORT_SYMBOL(mtk_wcn_wmt_wifi_exit); + +#else + +module_init(WIFI_init); +module_exit(WIFI_exit); + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c new file mode 100644 index 0000000000000..641e516f603d4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/linux/pub/wmt_idc.c @@ -0,0 +1,307 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +#include "osal_typedef.h" +#include "wmt_idc.h" +#include "wmt_lib.h" + +#if CFG_WMT_LTE_COEX_HANDLING + +MTK_WCN_WMT_IDC_INFO gWmtIdcInfo; + +INT32 wmt_idc_init(VOID) +{ + INT32 iRet; + + osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); + gWmtIdcInfo.iit.src_mod_id = AP_MOD_WMT; + gWmtIdcInfo.iit.dest_mod_id = MD_MOD_EL1; + gWmtIdcInfo.iit.sap_id = 0; + gWmtIdcInfo.ops.rx_cb = wmt_idc_msg_from_lte_handing; + + iRet = mtk_conn_md_bridge_reg(gWmtIdcInfo.iit.src_mod_id, &gWmtIdcInfo.ops); + if (iRet) { + WMT_ERR_FUNC("mtk_conn_md_bridge_reg fail(%d)\n", iRet); + return -1; + } + /* mtk_wcn_stp_flush_rx_queue(COEX_TASK_INDX); */ + return 0; + +} + +INT32 wmt_idc_deinit(VOID) +{ + INT32 iRet; + + iRet = mtk_conn_md_bridge_unreg(gWmtIdcInfo.iit.src_mod_id); + if (iRet) + WMT_ERR_FUNC("mtk_conn_md_bridge_unreg fail(%d)\n", iRet); + + osal_memset(&gWmtIdcInfo, 0, osal_sizeof(gWmtIdcInfo)); + + return 0; +} + +INT32 wmt_idc_msg_from_lte_handing(ipc_ilm_t *ilm) +{ + MTK_WCN_BOOL bRet; + + if (NULL == ilm) { + WMT_ERR_FUNC("NULL pointer\n"); + return -1; + } + if (mtk_wcn_stp_is_ready()) { + bRet = wmt_lib_handle_idc_msg(ilm); + if (MTK_WCN_BOOL_FALSE == bRet) { + WMT_ERR_FUNC("wmt handing idc msg fail\n"); + return -2; + } + } else { + WMT_INFO_FUNC("Received LTE msg,but STP is not ready,drop it!\n"); + } + return 0; +} + +VOID wmt_idc_dump_debug_msg(UINT8 *str, UINT8 *p_buf, UINT32 buf_len) +{ + UINT32 idx = 0; + + WMT_DBG_FUNC("%s:, length:%d\n", str, buf_len); + + WMT_DBG_FUNC("ASCII output:\n"); + + for (idx = 0; idx < buf_len;) { + WMT_DBG_FUNC("%c", p_buf[idx]); + idx++; + if (0 == idx % 16) + WMT_DBG_FUNC("\n"); + } + + WMT_DBG_FUNC("HEX output:\n"); + + for (idx = 0; idx < buf_len;) { + WMT_DBG_FUNC("%02x ", p_buf[idx]); + idx++; + if (0 == idx % 16) + WMT_DBG_FUNC("\n"); + } +} + +INT32 wmt_idc_msg_to_lte_handing(VOID) +{ + UINT32 readlen = 0; + local_para_struct *p_lps = NULL; + UINT8 *p_data = NULL; + UINT8 opcode = 0; + UINT16 msg_len = 0; + UINT32 handle_len = 0; +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; +#endif + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], LTE_IDC_BUFFER_MAX_SIZE, COEX_TASK_INDX); + if (readlen == 0) { + osal_sleep_ms(5); + readlen = mtk_wcn_stp_receive_data(&gWmtIdcInfo.buffer[0], LTE_IDC_BUFFER_MAX_SIZE, COEX_TASK_INDX); + } + + if (readlen > 0) { + WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); + wmt_idc_dump_debug_msg("WMT->LTE from STP buffer", &gWmtIdcInfo.buffer[0], readlen); + p_data = &gWmtIdcInfo.buffer[0]; + + while (handle_len < readlen) { + p_data += 2; /*omit direction & opcode 2 bytes */ + osal_memcpy(&msg_len, p_data, 2); + msg_len -= 1; /*flag byte */ + WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); + + p_data += 2; /*length: 2 bytes */ + + /*how to handle flag(msg type) need to Scott comment */ + /************************************************/ + + if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) + /*do not need transfer to LTE */ + { + p_data += 1; /*flag : 1 byte */ + /*need to handle these debug message */ + wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); + } else + /*need to transfer to LTE */ + { + p_lps = + (local_para_struct *) osal_malloc(osal_sizeof(local_para_struct) + + osal_sizeof(UINT8) * msg_len); + if (NULL == p_lps) { + WMT_ERR_FUNC("allocate local_para_struct memory fail\n"); + return -1; + } + + p_lps->msg_len = msg_len + osal_sizeof(local_para_struct); + + opcode = *p_data; + WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); + + p_data += 1; /*flag : 1 byte */ + osal_memcpy(p_lps->data, p_data, msg_len); + + gWmtIdcInfo.iit.local_para_ptr = p_lps; + +#if CFG_WMT_LTE_ENABLE_MSGID_MAPPING + switch (opcode) { + case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; + break; + case WMT_IDC_RX_OPCODE_LTE_FREQ_IDX_TABLE: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_FREQ_IDX_TABLE_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_PROFILE_IND: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_PROFILE_IND; + break; + case WMT_IDC_RX_OPCODE_UART_PIN_SEL: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_PIN_TYPE_IND; + break; + /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ + /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ + /* break; */ + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); + break; + } + if (MTK_WCN_BOOL_FALSE == unknown_msgid) { + /*handling flag value in wmt cmd */ + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + } +#else + if (opcode >= LTE_MSG_ID_OFFSET) { + gWmtIdcInfo.iit.msg_id = opcode + IPC_EL1_MSG_ID_BEGIN - LTE_MSG_ID_OFFSET + 1; + /*handling flag value in wmt cmd */ + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + WMT_DBG_FUNC("CONN->LTE: (0x%x->0x%x)\n", opcode, gWmtIdcInfo.iit.msg_id); + } else { + WMT_ERR_FUNC("opcode(%d)from connsys fw is out of range,drop it!\n", opcode); + } +#endif + osal_free(p_lps); + } + + p_data += msg_len; /*point to next package header */ + + handle_len += (msg_len + 5); + } + + } else { + WMT_ERR_FUNC("there is no coex data in stp buffer\n"); + } + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + + return 0; +} + +UINT32 wmt_idc_msg_to_lte_handing_for_test(UINT8 *p_buf, UINT32 len) +{ + UINT32 readlen = len; + local_para_struct *p_lps = NULL; + UINT8 *p_data = NULL; + UINT8 opcode = 0; + UINT16 msg_len = 0; + UINT32 handle_len = 0; + MTK_WCN_BOOL unknown_msgid = MTK_WCN_BOOL_FALSE; + + osal_memcpy(&gWmtIdcInfo.buffer[0], p_buf, len); + + if (readlen > 0) { + WMT_DBG_FUNC("read data len from fw(%d)\n", readlen); + p_data = &gWmtIdcInfo.buffer[0]; + + while (handle_len < readlen) { + p_data += 2; /*omit direction & opcode 2 bytes */ + osal_memcpy(&msg_len, p_data, 2); + msg_len -= 1; /*flag byte */ + WMT_DBG_FUNC("current raw data len(%d) from connsys firmware\n", msg_len); + + p_data += 2; /*length: 2 bytes */ + + /*how to handle flag(msg type) need to Scott comment */ + /************************************************/ + + if (*p_data == WMT_IDC_RX_OPCODE_DEBUG_MONITOR) + /*do not need transfer to LTE */ + { + p_data += 1; /*flag : 1 byte */ + /*need to handle these debug message */ + wmt_idc_dump_debug_msg("WIFI DEBUG MONITOR", p_data, msg_len); + } else + /*need to transfer to LTE */ + { + p_lps = + (local_para_struct *) osal_malloc(osal_sizeof(local_para_struct) + + osal_sizeof(UINT8) * msg_len); + if (NULL == p_lps) { + WMT_ERR_FUNC("allocate local_para_struct memory fail\n"); + return -1; + } + + p_lps->msg_len = msg_len + osal_sizeof(local_para_struct); + + opcode = *p_data; + WMT_DBG_FUNC("current opcode(%d) to LTE\n", opcode); + + p_data += 1; /*flag : 1 byte */ + osal_memcpy(p_lps->data, p_data, msg_len); + + gWmtIdcInfo.iit.local_para_ptr = p_lps; + + switch (opcode) { + case WMT_IDC_RX_OPCODE_BTWF_DEF_PARA: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_DEFAULT_PARAM_IND; + break; + case WMT_IDC_RX_OPCODE_BTWF_CHAN_RAN: + gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; + break; + /* case WMT_IDC_RX_OPCODE_TDM_REQ: */ + /* gWmtIdcInfo.iit.msg_id = IPC_MSG_ID_EL1_WIFIBT_OPER_FREQ_IND; */ + /* break; */ + default: + unknown_msgid = MTK_WCN_BOOL_TRUE; + WMT_ERR_FUNC("unknown opcode(%d) from connsys firmware\n", opcode); + break; + } + if (MTK_WCN_BOOL_FALSE == unknown_msgid) { + /*handling flag value in wmt cmd */ + mtk_conn_md_bridge_send_msg(&gWmtIdcInfo.iit); + } + osal_free(p_lps); + } + + p_data += msg_len; /*point to next package header */ + + handle_len += (msg_len + 5); + } + + } else { + WMT_ERR_FUNC("there is no coex data in stp buffer\n"); + } + + osal_memset(&gWmtIdcInfo.buffer[0], 0, LTE_IDC_BUFFER_MAX_SIZE); + + return handle_len; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile new file mode 100644 index 0000000000000..c201e8291b8ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/Makefile @@ -0,0 +1,25 @@ +# WMT HAL driver for MT7623 + +ccflags-y += \ + -I$(src)/include \ + -I$(src)/../linux/include \ + -I$(src)/../include \ + -I$(src)/../../common_detect + + ifeq ($(CONFIG_MTK_CLKMGR),y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach + endif + #ifeq ($(CONFIG_MTK_EMI_MPU),y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach + #endif + +subdir-ccflags-y += -D MTK_WCN_WMT_STP_EXP_SYMBOL_ABSTRACT + +ifeq ($(CONFIG_MTK_CONN_LTE_IDC_SUPPORT),y) + subdir-ccflags-y += -DWMT_IDC_SUPPORT=1 +else + subdir-ccflags-y += -DWMT_IDC_SUPPORT=0 +endif + +obj-y += mtk_wcn_consys_hw.o +obj-y += wmt_plat_alps.o diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h new file mode 100644 index 0000000000000..94d6af9d0b3ea --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/include/mtk_wcn_consys_hw.h @@ -0,0 +1,287 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MTK_WCN_CONSYS_HW_H_ +#define _MTK_WCN_CONSYS_HW_H_ + +#include +/*#include */ +#include "wmt_plat.h" + +/*device tree mode*/ +#ifdef CONFIG_OF +/* #if 1 */ +#include +#include +#include +#include +#endif + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CONSYS_BT_WIFI_SHARE_V33 0 +#define CONSYS_PMIC_CTRL_ENABLE 1 +#define CONSYS_PMIC_CTRL_UPMU 1 +#define CONSYS_EMI_MPU_SETTING 0 +#define CONSYS_AHB_CLK_MAGEMENT 1 +#define CONSYS_USE_PLATFORM_WRITE 1 +#define CONSYS_PWR_ON_OFF_API_AVAILABLE 1 +#define CONSYS_CLOCK_BUF_CTRL 0 +#if defined(CONFIG_MTK_LEGACY) +#define CONFIG_MTK_PMIC_LEGACY 0 +#endif +#define CONFIG_RESET_CONTROL 1 +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*tag start:new platform need to make sure these define */ +#define PLATFORM_SOC_CHIP 0x7623 +/*tag end*/ + +#ifdef CONFIG_OF + +struct CONSYS_BASE_ADDRESS { + SIZE_T mcu_base; + SIZE_T ap_rgu_base; + SIZE_T topckgen_base; + SIZE_T spm_base; +}; + +/*TOPCKGEN_BASE*/ +#define CONSYS_TOP_CLKCG_CLR_OFFSET 0x00000084 +#define CONSYS_TOP_CLKCG_SET_OFFSET 0x00000054 +#define CONSYS_WD_SYS_RST_OFFSET 0x00000018 +#define CONSYS_AP2CONN_OSC_EN_OFFSET 0x00000800 +#define CONSYS_EMI_MAPPING_OFFSET 0x00000310 +/*AP_RGU_BASE*/ +#define CONSYS_CPU_SW_RST_OFFSET 0x00000018 +/*SPM_BASE*/ +#define CONSYS_PWRON_CONFG_EN_OFFSET 0x00000000 +#define CONSYS_TOP1_PWR_CTRL_OFFSET 0x00000280 +#define CONSYS_PWR_CONN_ACK_OFFSET 0x0000060c +#define CONSYS_PWR_CONN_ACK_S_OFFSET 0x00000610 +/*CONN_MCU_CONFIG_BASE*/ +#define CONSYS_CHIP_ID_OFFSET 0x00000008 +#define CONSYS_ROM_RAM_DELSEL_OFFSET 0x00000114 +#define CONSYS_MCU_CFG_ACR_OFFSET 0x00000110 +#define CONSYS_CPUPCR_OFFSET 0x00000160 +/*AXI bus*/ + +#define CONSYS_TOPAXI_PROT_EN_OFFSET 0x1220 +#define CONSYS_TOPAXI_PROT_STA1_OFFSET 0x0228 +#endif + +#define CONSYS_SET_BIT(REG, BITVAL) (*((volatile UINT32*)(REG)) |= ((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT(REG, BITVAL) ((*(volatile UINT32*)(REG)) &= ~((UINT32)(BITVAL))) +#define CONSYS_CLR_BIT_WITH_KEY(REG, BITVAL, KEY) {\ + UINT32 val = (*(volatile UINT32*)(REG)); \ + val &= ~((UINT32)(BITVAL)); \ + val |= ((UINT32)(KEY)); \ + (*(volatile UINT32*)(REG)) = val;\ +} +#define CONSYS_REG_READ(addr) (*((volatile UINT32*)(addr))) +#if CONSYS_USE_PLATFORM_WRITE +#define CONSYS_REG_WRITE(addr, data) mt_reg_sync_writel(data, addr) +#else +#define CONSYS_REG_WRITE(addr, data) (*((volatile UINT32*)(addr)) = (UINT32)(data)) +#endif + +/*tag start: connsys register base address (hard code, no use) */ +#define AP_RGU_BASE 0xF0007000 +#define TOPCKGEN_BASE 0xF0000000 +#define SPM_BASE 0xF0006000 +#define CONN_MCU_CONFIG_BASE 0xF8070000 +/*GIC Interrupt ID*/ +#define MT_CONN2AP_BTIF_WAKEUP_IRQ_ID 237 +/*tag end*/ + +/*connsys register offset define(hard code mode)*/ +#if 1 + /*top clock gating control register */ +#define CONSYS_TOP_CLKCG_CLR_REG (TOPCKGEN_BASE + 0x00000084) +#define CONSYS_TOP_CLKCG_SET_REG (TOPCKGEN_BASE + 0x00000054) +#define CONSYS_TOP_CLKCG_BIT (0x1 << 26) + + /*SPM clock gating control register */ +#define CONSYS_PWRON_CONFG_EN_REG (SPM_BASE + 0x00000000) +#define CONSYS_PWRON_CONFG_EN_VALUE (0x0b160001) +#define CONSYS_PWRON_CONFG_DIS_VALUE (0x0b160000) +#endif + +#define CONSYS_CPU_SW_RST_REG (AP_RGU_BASE + 0x00000018) +#define CONSYS_TOP1_PWR_CTRL_REG (SPM_BASE + 0x00000280) +#define CONSYS_PWR_CONN_ACK_REG (SPM_BASE + 0x0000060c) +#define CONSYS_PWR_CONN_ACK_S_REG (SPM_BASE + 0x00000610) + +#define CONSYS_WD_SYS_RST_REG (TOPCKGEN_BASE + 0x00000018) +#define CONSYS_CHIP_ID_REG (CONN_MCU_CONFIG_BASE + 0x00000008) +#define CONSYS_ROM_RAM_DELSEL_REG (CONN_MCU_CONFIG_BASE + 0x00000114) +#define CONSYS_MCU_CFG_ACR_REG (CONN_MCU_CONFIG_BASE + 0x00000110) +#define CONSYS_AFE_REG (CONN_TOP_CR_BASE + 0x00002000) +#define CONSYS_AFE_REG_DIG_RCK_01 (CONSYS_AFE_REG + 0x00000010) +#define CONSYS_AFE_REG_WBG_PLL_02 (CONSYS_AFE_REG + 0x00000028) +#define CONSYS_AFE_REG_WBG_WB_TX_01 (CONSYS_AFE_REG + 0x0000003c) +#define CONSYS_AFE_REG_DIG_RCK_01_VALUE (0x174b0160) +#define CONSYS_AFE_REG_WBG_PLL_02_VALUE (0x844083fe) +#define CONSYS_AFE_REG_WBG_WB_TX_01_VALUE (0x7fc39a20) + +#define CONSYS_TOPAXI_PROT_EN (TOPCKGEN_BASE + 0x0220) +#define CONSYS_TOPAXI_PROT_STA1 (TOPCKGEN_BASE + 0x0228) +#define CONSYS_PROT_MASK ((0x1<<13) | (0x1<<14) | (0x1<<15)) /* bit 13, 14, 15 */ +/*CONSYS_CPU_SW_RST_REG*/ +#define CONSYS_CPU_SW_RST_BIT (0x1 << 12) +#define CONSYS_CPU_SW_RST_CTRL_KEY (0x88 << 24) + +/*CONSYS_TOP1_PWR_CTRL_REG*/ +#define CONSYS_SPM_PWR_RST_BIT (0x1 << 0) +#define CONSYS_SPM_PWR_ISO_S_BIT (0x1 << 1) +#define CONSYS_SPM_PWR_ON_BIT (0x1 << 2) +#define CONSYS_SPM_PWR_ON_S_BIT (0x1 << 3) +#define CONSYS_CLK_CTRL_BIT (0x1 << 4) +#define CONSYS_SRAM_CONN_PD_BIT (0x1 << 8) + +/*CONSYS_PWR_CONN_ACK_REG*/ +#define CONSYS_PWR_ON_ACK_BIT (0x1 << 1) + +/*CONSYS_PWR_CONN_ACK_S_REG*/ +#define CONSYS_PWR_CONN_ACK_S_BIT (0x1 << 1) + +/*CONSYS_WD_SYS_RST_REG*/ +#define CONSYS_WD_SYS_RST_CTRL_KEY (0x88 << 24) +#define CONSYS_WD_SYS_RST_BIT (0x1 << 9) + +/*CONSYS_MCU_CFG_ACR_REG*/ +#define CONSYS_MCU_CFG_ACR_MBIST_BIT (0x1 << 18) + +/* EMI part mapping & ctrl*/ +#define KBYTE (1024*sizeof(char)) +#define CONSYS_EMI_AP_PHY_OFFSET (0x80000) +#define CONSYS_EMI_AP_PHY_BASE (0x80080000) +#define CONSYS_EMI_FW_PHY_BASE (0xf0080000) +#define CONSYS_EMI_MEM_SIZE (343*KBYTE) /*coredump space , 343K is enough */ +#define CONSYS_EMI_PAGED_TRACE_OFFSET (0x400) +#define CONSYS_EMI_PAGED_DUMP_OFFSET (0x8400) +#define CONSYS_EMI_FULL_DUMP_OFFSET (0x10400) + +/*cpupcr*/ +#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) +/*emi mapping*/ +#define CONSYS_EMI_MAPPING (TOPCKGEN_BASE + 0x1310) + +/*control app2cnn_osc_en*/ +#define CONSYS_AP2CONN_OSC_EN_REG (TOPCKGEN_BASE + 0x00001800) +#define CONSYS_AP2CONN_OSC_EN_BIT (0x1 << 16) +#define CONSYS_AP2CONN_WAKEUP_BIT (0x1 << 17) + +/*paged dump address start*/ +#define CONSYS_PAGED_DUMP_START_ADDR (0xf0088400) +#define CONSYS_PAGED_DUMP_SIZE (32*KBYTE) + +/*full dump address start*/ +#define CONSYS_FULL_DUMP_START_ADDR (0xf0090400) +#define CONSYS_FULL_DUMP_DLM_LEN (0x1f000) +#define CONSYS_FULL_DUMP_SYSB2_START (CONSYS_FULL_DUMP_START_ADDR + CONSYS_FULL_DUMP_DLM_LEN) +#define CONSYS_FULL_DUMP_SYSB2_LEN (0x6800) +#define CONSYS_FULL_DUMP_SYSB3_START (CONSYS_FULL_DUMP_SYSB2_START + CONSYS_FULL_DUMP_SYSB2_LEN) +#define CONSYS_FULL_DUMP_SYSB3_LEN (0x16800) + +/*force fw assert pattern*/ +#define EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1 (0x19b30bb1) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_EMI_CTRL_STATE_OFFSET_ { + EXP_APMEM_CTRL_STATE = 0x0, + EXP_APMEM_CTRL_HOST_SYNC_STATE = 0x4, + EXP_APMEM_CTRL_HOST_SYNC_NUM = 0x8, + EXP_APMEM_CTRL_CHIP_SYNC_STATE = 0xc, + EXP_APMEM_CTRL_CHIP_SYNC_NUM = 0x10, + EXP_APMEM_CTRL_CHIP_SYNC_ADDR = 0x14, + EXP_APMEM_CTRL_CHIP_SYNC_LEN = 0x18, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START = 0x1c, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN = 0x20, + EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX = 0x24, + EXP_APMEM_CTRL_CHIP_INT_STATUS = 0x28, + EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END = 0x2c, + EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1 = 0x30, + EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP = 0x48, + EXP_APMEM_CTRL_MAX +} ENUM_EMI_CTRL_STATE_OFFSET, *P_ENUM_EMI_CTRL_STATE_OFFSET; + +#if CONSYS_BT_WIFI_SHARE_V33 +typedef struct _BT_WIFI_V33_STATUS_ { + UINT32 counter; + UINT32 flags; + spinlock_t lock; +} BT_WIFI_V33_STATUS; + +#endif + +typedef enum _CONSYS_GPS_CO_CLOCK_TYPE_ { + GPS_TCXO_TYPE = 0, + GPS_CO_TSX_TYPE = 1, + GPS_CO_DCXO_TYPE = 2, + GPS_CO_VCTCXO_TYPE = 3, + GPS_CO_CLOCK_TYPE_MAX +} CONSYS_GPS_CO_CLOCK_TYPE, *P_CONSYS_GPS_CO_CLOCK_TYPE; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern struct CONSYS_BASE_ADDRESS conn_reg; +#if CONSYS_BT_WIFI_SHARE_V33 +extern BT_WIFI_V33_STATUS gBtWifiV33; +#endif +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +extern INT32 mtk_wcn_consys_hw_init(VOID); +extern INT32 mtk_wcn_consys_hw_deinit(VOID); +extern INT32 mtk_wcn_consys_hw_pwr_off(VOID); +extern INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type); +extern INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type); +extern INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable); +extern INT32 mtk_wcn_consys_hw_state_show(VOID); +extern UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset); +#if CONSYS_ENALBE_SET_JTAG +extern UINT32 mtk_wcn_consys_jtag_flag_ctrl(UINT32 en); +#endif +extern UINT32 mtk_wcn_consys_soc_chipid(VOID); +#if !defined(CONFIG_MTK_GPIO_LEGACY) +extern struct pinctrl *mtk_wcn_consys_get_pinctrl(VOID); +#endif +extern INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 buf); +#endif /* _MTK_WCN_CMB_HW_H_ */ diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c new file mode 100644 index 0000000000000..53b69a7b3e872 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c @@ -0,0 +1,738 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-CONSYS-HW]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include "osal_typedef.h" +#include "mtk_wcn_consys_hw.h" +#include +#include +#include +#if CONSYS_EMI_MPU_SETTING +#include +#endif + +#include +#include +#ifdef CONFIG_MTK_HIBERNATION +#include +#endif + +#include + +#if CONSYS_CLOCK_BUF_CTRL +#include +#endif + +#include +#include + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static INT32 mtk_wmt_probe(struct platform_device *pdev); +static INT32 mtk_wmt_remove(struct platform_device *pdev); + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +struct CONSYS_BASE_ADDRESS conn_reg; +static phys_addr_t gConEmiPhyBase; +static UINT8 __iomem *pEmibaseaddr; +static struct clk *clk_infra_conn_main; /*ctrl infra_connmcu_bus clk */ +static struct platform_device *my_pdev; +static struct reset_control *rstc; +static struct regulator *reg_VCN18; +static struct regulator *reg_VCN28; +static struct regulator *reg_VCN33_BT; +static struct regulator *reg_VCN33_WIFI; +static struct pinctrl *consys_pinctrl; +static struct pinctrl *mt6625_spi_pinctrl; +static struct pinctrl_state *mt6625_spi_default; +static struct regmap *pmic_regmap; +#define DYNAMIC_DUMP_GROUP_NUM 5 + +static const struct of_device_id apwmt_of_ids[] = { + {.compatible = "mediatek,mt7623-consys",} +}; +MODULE_DEVICE_TABLE(of, apwmt_of_ids); + +static struct platform_driver mtk_wmt_dev_drv = { + .probe = mtk_wmt_probe, + .remove = mtk_wmt_remove, + .driver = { + .name = "mt7623consys", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(apwmt_of_ids), + }, +}; + +static INT32 mtk_wmt_probe(struct platform_device *pdev) +{ + int ret = 0; + struct device_node *node = NULL; + + pm_runtime_enable(&pdev->dev); + my_pdev = pdev; + mt6625_spi_pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(mt6625_spi_pinctrl)) { + ret = PTR_ERR(mt6625_spi_pinctrl); + WMT_PLAT_ERR_FUNC("Wmt cannot find pinctrl!\n"); + goto set_pin_exit; + } + mt6625_spi_default = pinctrl_lookup_state(mt6625_spi_pinctrl, "consys_pins_default"); + if (IS_ERR(mt6625_spi_default)) { + ret = PTR_ERR(mt6625_spi_default); + WMT_PLAT_ERR_FUNC("Wmt Cannot find pinctrl default!\n"); + goto set_pin_exit; + } + pinctrl_select_state(mt6625_spi_pinctrl, mt6625_spi_default); +set_pin_exit: + + node = of_parse_phandle(pdev->dev.of_node, "mediatek,pwrap-regmap", 0); + if (node) { + pmic_regmap = pwrap_node_to_regmap(node); + if (IS_ERR(pmic_regmap)) + goto set_pmic_wrap_exit; + } else { + WMT_PLAT_ERR_FUNC("Pwrap node has not register regmap.\n"); + goto set_pmic_wrap_exit; + } +set_pmic_wrap_exit: + + clk_infra_conn_main = devm_clk_get(&pdev->dev, "consysbus"); + if (IS_ERR(clk_infra_conn_main)) { + WMT_PLAT_ERR_FUNC("sean debug [CCF]cannot get clk_infra_conn_main clock.\n"); + return PTR_ERR(clk_infra_conn_main); + } + WMT_PLAT_DBG_FUNC("[CCF]clk_infra_conn_main=%p\n", clk_infra_conn_main); + + reg_VCN18 = devm_regulator_get(&pdev->dev, "vcn18"); + if (IS_ERR(reg_VCN18)) { + ret = PTR_ERR(reg_VCN18); + WMT_PLAT_ERR_FUNC("Regulator_get VCN_1V8 fail, ret=%d\n", ret); + } + reg_VCN28 = devm_regulator_get(&pdev->dev, "vcn28"); + if (IS_ERR(reg_VCN28)) { + ret = PTR_ERR(reg_VCN28); + WMT_PLAT_ERR_FUNC("Regulator_get VCN_2V8 fail, ret=%d\n", ret); + } + reg_VCN33_BT = devm_regulator_get(&pdev->dev, "vcn33_bt"); + if (IS_ERR(reg_VCN33_BT)) { + ret = PTR_ERR(reg_VCN33_BT); + WMT_PLAT_ERR_FUNC("Regulator_get VCN33_BT fail, ret=%d\n", ret); + } + reg_VCN33_WIFI = devm_regulator_get(&pdev->dev, "vcn33_wifi"); + if (IS_ERR(reg_VCN33_WIFI)) { + ret = PTR_ERR(reg_VCN33_WIFI); + WMT_PLAT_ERR_FUNC("Regulator_get VCN33_WIFI fail, ret=%d\n", ret); + } + + rstc = devm_reset_control_get(&pdev->dev, "connsys"); + if (IS_ERR(rstc)) { + ret = PTR_ERR(rstc); + WMT_PLAT_ERR_FUNC("CanNot get consys reset. ret=%d\n", ret); + return PTR_ERR(rstc); + } + + consys_pinctrl = devm_pinctrl_get(&pdev->dev); + if (IS_ERR(consys_pinctrl)) { + ret = PTR_ERR(consys_pinctrl); + WMT_PLAT_ERR_FUNC("CanNot find consys pinctrl. ret=%d\n", ret); + return PTR_ERR(consys_pinctrl); + } + return 0; +} + +static INT32 mtk_wmt_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + +VOID mtk_wcn_consys_power_on(VOID) +{ + INT32 iRet = -1; +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + iRet = pm_runtime_get_sync(&my_pdev->dev); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + if (iRet) + WMT_PLAT_ERR_FUNC("pm_runtime_get_sync() fail(%d)\n", iRet); + else + WMT_PLAT_INFO_FUNC("pm_runtime_get_sync() CONSYS ok\n"); + + iRet = device_init_wakeup(&my_pdev->dev, true); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + if (iRet) + WMT_PLAT_ERR_FUNC("device_init_wakeup(true) fail.\n"); + else + WMT_PLAT_INFO_FUNC("device_init_wakeup(true) CONSYS ok\n"); +} + +VOID mtk_wcn_consys_power_off(VOID) +{ + INT32 iRet = -1; + + iRet = pm_runtime_put_sync(&my_pdev->dev); + if (iRet) + WMT_PLAT_ERR_FUNC("pm_runtime_put_sync() fail.\n"); + else + WMT_PLAT_INFO_FUNC("pm_runtime_put_sync() CONSYS ok\n"); + + iRet = device_init_wakeup(&my_pdev->dev, false); + if (iRet) + WMT_PLAT_ERR_FUNC("device_init_wakeup(false) fail.\n"); + else + WMT_PLAT_INFO_FUNC("device_init_wakeup(false) CONSYS ok\n"); +} + +INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_type) +{ + UINT32 retry = 10; + UINT32 consysHwChipId = 0; + + WMT_PLAT_DBG_FUNC("CONSYS-HW-REG-CTRL(0x%08x),start\n", on); + if (on) { + WMT_PLAT_DBG_FUNC("++\n"); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + /*need PMIC driver provide new API protocol */ + /*1.AP power on VCN_1V8 LDO (with PMIC_WRAP API) VCN_1V8 */ + regulator_set_mode(reg_VCN18, REGULATOR_MODE_STANDBY); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + /* VOL_DEFAULT, VOL_1200, VOL_1300, VOL_1500, VOL_1800... */ + if (reg_VCN18) { +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + regulator_set_voltage(reg_VCN18, 1800000, 1800000); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + if (regulator_enable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("enable VCN18 fail\n"); + else + WMT_PLAT_DBG_FUNC("enable VCN18 ok\n"); + } + udelay(150); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + if (co_clock_type) { + /*step0,clk buf ctrl */ + WMT_PLAT_INFO_FUNC("co clock type(%d),turn on clk buf\n", co_clock_type); +#if CONSYS_CLOCK_BUF_CTRL + clk_buf_ctrl(CLK_BUF_CONN, 1); +#endif + /*if co-clock mode: */ + /*2.set VCN28 to SW control mode (with PMIC_WRAP API) */ + /*turn on VCN28 LDO only when FMSYS is activated" */ + regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x0 << 14);/*V28*/ + } else { + /*if NOT co-clock: */ + /*2.1.switch VCN28 to HW control mode (with PMIC_WRAP API) */ + regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x1 << 14);/*V28*/ + /*2.2.turn on VCN28 LDO (with PMIC_WRAP API)" */ + /*fix vcn28 not balance warning */ + if (reg_VCN28) { + regulator_set_voltage(reg_VCN28, 2800000, 2800000); + if (regulator_enable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("enable VCN_2V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("enable VCN_2V8 ok\n"); + } + } + + /*3.assert CONNSYS CPU SW reset 0x10007018 "[12]=1'b1 [31:24]=8'h88 (key)" */ +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + reset_control_reset(rstc); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + mtk_wcn_consys_power_on(); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + /*11.26M is ready now, delay 10us for mem_pd de-assert */ + udelay(10); + /*enable AP bus clock : connmcu_bus_pd API: enable_clock() ++?? */ + clk_prepare_enable(clk_infra_conn_main); +printk(KERN_ALERT "DEBUG: Passed %s %d \n",__FUNCTION__,__LINE__); + WMT_PLAT_DBG_FUNC("[CCF]enable clk_infra_conn_main\n"); + /*12.poll CONNSYS CHIP ID until chipid is returned 0x18070008 */ + while (retry-- > 0) { + consysHwChipId = CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CHIP_ID_OFFSET) - 0xf6d; + + if ((consysHwChipId == 0x0321) || (consysHwChipId == 0x0335) || (consysHwChipId == 0x0337)) { + WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); + break; + } + if ((consysHwChipId == 0x8163) || (consysHwChipId == 0x8127) || (consysHwChipId == 0x7623)) { + WMT_PLAT_INFO_FUNC("retry(%d)consys chipId(0x%08x)\n", retry, consysHwChipId); + break; + } + + WMT_PLAT_ERR_FUNC("Read CONSYS chipId(0x%08x)", consysHwChipId); + msleep(20); + } + + if ((0 == retry) || (0 == consysHwChipId)) + WMT_PLAT_ERR_FUNC("Maybe has a consys power on issue,(0x%08x)\n", consysHwChipId); + + msleep(40); + + } else { + + clk_disable_unprepare(clk_infra_conn_main); + WMT_PLAT_DBG_FUNC("[CCF] clk_disable_unprepare(clk_infra_conn_main) calling\n"); + mtk_wcn_consys_power_off(); + + if (co_clock_type) { + /*VCN28 has been turned off by GPS OR FM */ +#if CONSYS_CLOCK_BUF_CTRL + clk_buf_ctrl(CLK_BUF_CONN, 0); +#endif + } else { + regmap_update_bits(pmic_regmap, 0x41C, 0x1 << 14, 0x0 << 14);/*V28*/ + /*turn off VCN28 LDO (with PMIC_WRAP API)" */ + if (reg_VCN28) { + if (regulator_disable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("disable VCN_2V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("disable VCN_2V8 ok\n"); + } + } + + /*AP power off MT6625L VCN_1V8 LDO */ + regulator_set_mode(reg_VCN18, REGULATOR_MODE_STANDBY); + if (reg_VCN18) { + if (regulator_disable(reg_VCN18)) + WMT_PLAT_ERR_FUNC("disable VCN_1V8 fail!\n"); + else + WMT_PLAT_DBG_FUNC("disable VCN_1V8 ok\n"); + } + + } + WMT_PLAT_DBG_FUNC("CONSYS-HW-REG-CTRL(0x%08x),finish\n", on); + return 0; +} + +INT32 mtk_wcn_consys_hw_gpio_ctrl(UINT32 on) +{ + INT32 iRet = 0; + + WMT_PLAT_DBG_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), start\n", on); + + if (on) { + + /* TODO: [FixMe][GeorgeKuo] double check if BGF_INT is implemented ok */ + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_MUX); */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_INIT); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ registered and disabled\n"); + + } else { + + /* set bgf eint/all eint to deinit state, namely input low state */ + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + iRet += wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); + WMT_PLAT_DBG_FUNC("CONSYS-HW, BGF IRQ unregistered and disabled\n"); + /* iRet += wmt_plat_gpio_ctrl(PIN_BGF_EINT, PIN_STA_DEINIT); */ + } + WMT_PLAT_DBG_FUNC("CONSYS-HW-GPIO-CTRL(0x%08x), finish\n", on); + return iRet; + +} + +INT32 mtk_wcn_consys_hw_pwr_on(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, start\n"); + + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + iRet += mtk_wcn_consys_hw_gpio_ctrl(1); + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-ON, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_pwr_off(VOID) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, start\n"); + + iRet += mtk_wcn_consys_hw_reg_ctrl(0, 0); + iRet += mtk_wcn_consys_hw_gpio_ctrl(0); + + WMT_PLAT_INFO_FUNC("CONSYS-HW-PWR-OFF, finish(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_rst(UINT32 co_clock_type) +{ + INT32 iRet = 0; + + WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst start, eirq should be disabled before this step\n"); + + /*1. do whole hw power off flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(0, co_clock_type); + + /*2. do whole hw power on flow */ + iRet += mtk_wcn_consys_hw_reg_ctrl(1, co_clock_type); + + WMT_PLAT_INFO_FUNC("CONSYS-HW, hw_rst finish, eirq should be enabled after this step\n"); + return iRet; +} + +#if CONSYS_BT_WIFI_SHARE_V33 +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) +{ + /* spin_lock_irqsave(&gBtWifiV33.lock,gBtWifiV33.flags); */ + if (enable) { + if (1 == gBtWifiV33.counter) { + gBtWifiV33.counter++; + WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); + } else if (2 == gBtWifiV33.counter) { + WMT_PLAT_DBG_FUNC("V33 has been enabled,counter(%d)\n", gBtWifiV33.counter); + } else { +#if CONSYS_PMIC_CTRL_ENABLE + /*do BT PMIC on,depenency PMIC API ready */ + /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ + /* VOL_DEFAULT, VOL_3300, VOL_3400, VOL_3500, VOL_3600 */ + hwPowerOn(MT6323_POWER_LDO_VCN33, VOL_3300, "wcn_drv"); + upmu_set_vcn33_on_ctrl_bt(1); +#endif + WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 on\n"); + gBtWifiV33.counter++; + } + + } else { + if (1 == gBtWifiV33.counter) { + /*do BT PMIC off */ + /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ +#if CONSYS_PMIC_CTRL_ENABLE + upmu_set_vcn33_on_ctrl_bt(0); + hwPowerDown(MT6323_POWER_LDO_VCN33, "wcn_drv"); +#endif + WMT_PLAT_INFO_FUNC("WMT do BT/WIFI v3.3 off\n"); + gBtWifiV33.counter--; + } else if (2 == gBtWifiV33.counter) { + gBtWifiV33.counter--; + WMT_PLAT_DBG_FUNC("V33 no need disabled,counter(%d)\n", gBtWifiV33.counter); + } else { + WMT_PLAT_DBG_FUNC("V33 has been disabled,counter(%d)\n", gBtWifiV33.counter); + } + + } + /* spin_unlock_irqrestore(&gBtWifiV33.lock,gBtWifiV33.flags); */ + return 0; +} + +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) +{ + mtk_wcn_consys_hw_bt_paldo_ctrl(enable); + return 0; +} + +#else +INT32 mtk_wcn_consys_hw_bt_paldo_ctrl(UINT32 enable) +{ + + if (enable) { + /*do BT PMIC on,depenency PMIC API ready */ + /*switch BT PALDO control from SW mode to HW mode:0x416[5]-->0x1 */ + if (reg_VCN33_BT) { + regulator_set_voltage(reg_VCN33_BT, 3300000, 3300000); + if (regulator_enable(reg_VCN33_BT)) + WMT_PLAT_ERR_FUNC("WMT do BT PMIC on fail!\n"); + } + regmap_update_bits(pmic_regmap, 0x416, 0x1 << 5, 0x1 << 5);/*BT*/ + WMT_PLAT_INFO_FUNC("WMT do BT PMIC on\n"); + } else { + /*do BT PMIC off */ + /*switch BT PALDO control from HW mode to SW mode:0x416[5]-->0x0 */ + regmap_update_bits(pmic_regmap, 0x416, 0x1 << 5, 0x0 << 5);/*BT*/ + if (reg_VCN33_BT) + if (regulator_disable(reg_VCN33_BT)) + WMT_PLAT_ERR_FUNC("WMT do BT PMIC off fail!\n"); + WMT_PLAT_INFO_FUNC("WMT do BT PMIC off\n"); + } + + return 0; + +} + +INT32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT32 enable) +{ + + if (enable) { + /*do WIFI PMIC on,depenency PMIC API ready */ + /*switch WIFI PALDO control from SW mode to HW mode:0x418[14]-->0x1 */ + if (reg_VCN33_WIFI) { + regulator_set_voltage(reg_VCN33_WIFI, 3300000, 3300000); + if (regulator_enable(reg_VCN33_WIFI)) + WMT_PLAT_ERR_FUNC("WMT do WIFI PMIC on fail!\n"); + else + WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC on !\n"); + } + regmap_update_bits(pmic_regmap, 0x418, 0x1 << 14, 0x1 << 14);/*WIFI*/ + WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC on\n"); + } else { + /*do WIFI PMIC off */ + /*switch WIFI PALDO control from HW mode to SW mode:0x418[14]-->0x0 */ + regmap_update_bits(pmic_regmap, 0x418, 0x1 << 14, 0x0 << 14);/*WIFI*/ + if (reg_VCN33_WIFI) + if (regulator_disable(reg_VCN33_WIFI)) + WMT_PLAT_ERR_FUNC("WMT do WIFI PMIC off fail!\n"); + WMT_PLAT_INFO_FUNC("WMT do WIFI PMIC off\n"); + } + + return 0; +} + +#endif +INT32 mtk_wcn_consys_hw_vcn28_ctrl(UINT32 enable) +{ + if (enable) { + /*in co-clock mode,need to turn on vcn28 when fm on */ + if (reg_VCN28) { + regulator_set_voltage(reg_VCN28, 2800000, 2800000); + if (regulator_enable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("WMT do VCN28 PMIC on fail!\n"); + } + WMT_PLAT_INFO_FUNC("turn on vcn28 for fm/gps usage in co-clock mode\n"); + } else { + /*in co-clock mode,need to turn off vcn28 when fm off */ + if (reg_VCN28) + if (regulator_disable(reg_VCN28)) + WMT_PLAT_ERR_FUNC("WMT do VCN28 PMIC off fail!\n"); + WMT_PLAT_INFO_FUNC("turn off vcn28 for fm/gps usage in co-clock mode\n"); + } + return 0; +} + +INT32 mtk_wcn_consys_hw_state_show(VOID) +{ + return 0; +} + +INT32 mtk_wcn_consys_hw_restore(struct device *device) +{ + UINT32 addrPhy = 0; + + if (gConEmiPhyBase) { + +#if CONSYS_EMI_MPU_SETTING + /*set MPU for EMI share Memory */ + WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); + +#if 0 + emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M/2, + gConEmiPhyBase + SZ_1M, + 5, + SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); + + +#else + WMT_PLAT_WARN_FUNC("not define platform config\n"); +#endif + +#endif + /*consys to ap emi remapping register:10001310, cal remapping address */ + addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; + + /*enable consys to ap emi remapping bit12 */ + addrPhy = addrPhy | 0x1000; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); + + WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump in restore cb(0x%08x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); + +#if 1 + pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + CONSYS_EMI_AP_PHY_OFFSET, CONSYS_EMI_MEM_SIZE); +#else + pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); +#endif + if (pEmibaseaddr) { + WMT_PLAT_INFO_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); + memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); + } else { + WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); + } + } else { + WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); + } + + return 0; +} + +/*Reserved memory by device tree!*/ +int reserve_memory_consys_fn(struct reserved_mem *rmem) +{ + WMT_PLAT_WARN_FUNC(" name: %s, base: 0x%llx, size: 0x%llx\n", rmem->name, + (unsigned long long)rmem->base, (unsigned long long)rmem->size); + gConEmiPhyBase = rmem->base; + return 0; +} + +RESERVEDMEM_OF_DECLARE(reserve_memory_test, "mediatek,consys-reserve-memory", reserve_memory_consys_fn); + + +INT32 mtk_wcn_consys_hw_init(void) +{ + + INT32 iRet = -1; + UINT32 addrPhy = 0; + INT32 i = 0; + struct device_node *node = NULL; + + node = of_find_compatible_node(NULL, NULL, "mediatek,mt7623-consys"); + if (node) { + /* registers base address */ + conn_reg.mcu_base = (SIZE_T) of_iomap(node, i); + WMT_PLAT_DBG_FUNC("Get mcu register base(0x%zx)\n", conn_reg.mcu_base); + i++; + + conn_reg.topckgen_base = (SIZE_T) of_iomap(node, i); + WMT_PLAT_DBG_FUNC("Get topckgen register base(0x%zx)\n", conn_reg.topckgen_base); + i++; + } else { + WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); + return iRet; + } + if (gConEmiPhyBase) { +#if CONSYS_EMI_MPU_SETTING + /*set MPU for EMI share Memory */ + WMT_PLAT_INFO_FUNC("setting MPU for EMI share memory\n"); + +#if 0 + emi_mpu_set_region_protection(gConEmiPhyBase + SZ_1M/2, + gConEmiPhyBase + SZ_1M, + 5, + SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, NO_PROTECTION)); +#else + WMT_PLAT_WARN_FUNC("not define platform config\n"); +#endif + +#endif + WMT_PLAT_DBG_FUNC("get consys start phy address(0x%zx)\n", (SIZE_T) gConEmiPhyBase); + + /*consys to ap emi remapping register:10001310, cal remapping address */ + addrPhy = (gConEmiPhyBase & 0xFFF00000) >> 20; + + /*enable consys to ap emi remapping bit12 */ + addrPhy = addrPhy | 0x1000; + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET) | addrPhy); + + WMT_PLAT_INFO_FUNC("CONSYS_EMI_MAPPING dump(0x%08x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_EMI_MAPPING_OFFSET)); + +#if 1 + pEmibaseaddr = ioremap_nocache(gConEmiPhyBase + CONSYS_EMI_AP_PHY_OFFSET, CONSYS_EMI_MEM_SIZE); +#else + pEmibaseaddr = ioremap_nocache(CONSYS_EMI_AP_PHY_BASE, CONSYS_EMI_MEM_SIZE); +#endif + /* pEmibaseaddr = ioremap_nocache(0x80090400,270*KBYTE); */ + if (pEmibaseaddr) { + WMT_PLAT_INFO_FUNC("EMI mapping OK(0x%p)\n", pEmibaseaddr); + memset_io(pEmibaseaddr, 0, CONSYS_EMI_MEM_SIZE); + iRet = 0; + } else { + WMT_PLAT_ERR_FUNC("EMI mapping fail\n"); + } + } else { + WMT_PLAT_ERR_FUNC("consys emi memory address gConEmiPhyBase invalid\n"); + } +#ifdef CONFIG_MTK_HIBERNATION + WMT_PLAT_INFO_FUNC("register connsys restore cb for complying with IPOH function\n"); + register_swsusp_restore_noirq_func(ID_M_CONNSYS, mtk_wcn_consys_hw_restore, NULL); +#endif + iRet = platform_driver_register(&mtk_wmt_dev_drv); + if (iRet) + WMT_PLAT_ERR_FUNC("WMT platform driver registered failed(%d)\n", iRet); + return iRet; +} + +INT32 mtk_wcn_consys_hw_deinit(void) +{ + if (pEmibaseaddr) { + iounmap(pEmibaseaddr); + pEmibaseaddr = NULL; + } +#ifdef CONFIG_MTK_HIBERNATION + unregister_swsusp_restore_noirq_func(ID_M_CONNSYS); +#endif + + platform_driver_unregister(&mtk_wmt_dev_drv); + return 0; +} + +UINT8 *mtk_wcn_consys_emi_virt_addr_get(UINT32 ctrl_state_offset) +{ + UINT8 *p_virtual_addr = NULL; + + if (!pEmibaseaddr) { + WMT_PLAT_ERR_FUNC("EMI base address is NULL\n"); + return NULL; + } + WMT_PLAT_DBG_FUNC("ctrl_state_offset(%08x)\n", ctrl_state_offset); + p_virtual_addr = pEmibaseaddr + ctrl_state_offset; + + return p_virtual_addr; +} + +UINT32 mtk_wcn_consys_soc_chipid(void) +{ + return PLATFORM_SOC_CHIP; +} + +struct pinctrl *mtk_wcn_consys_get_pinctrl() +{ + return consys_pinctrl; +} +INT32 mtk_wcn_consys_set_dynamic_dump(PUINT32 str_buf) +{ + PUINT8 vir_addr = NULL; + + vir_addr = mtk_wcn_consys_emi_virt_addr_get(EXP_APMEM_CTRL_CHIP_DYNAMIC_DUMP); + if (!vir_addr) { + WMT_PLAT_ERR_FUNC("get vir address fail\n"); + return -2; + } + memcpy(vir_addr, str_buf, DYNAMIC_DUMP_GROUP_NUM*8); + WMT_PLAT_INFO_FUNC("dynamic dump register value(0x%08x)\n", CONSYS_REG_READ(vir_addr)); + return 0; +} diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c new file mode 100644 index 0000000000000..7163dc18a255e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/wmt_plat_alps.c @@ -0,0 +1,1071 @@ +/*! \file + \brief Declaration of library functions + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#ifdef DFT_TAG +#undef DFT_TAG +#endif +#define DFT_TAG "[WMT-PLAT]" + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +/* ALPS header files */ +/*#include */ +/*#include */ +#if defined(CONFIG_MTK_GPIO_LEGACY) +#include +#endif +#include + +/* MTK_WCN_COMBO header files */ +#include "osal_typedef.h" +#include "mtk_wcn_consys_hw.h" +#include "stp_dbg.h" + +#define CFG_WMT_WAKELOCK_SUPPORT 1 + +#ifdef CONFIG_MTK_MT6306_SUPPORT +#define MTK_WCN_MT6306_IS_READY 1 +#else +#define MTK_WCN_MT6306_IS_READY 0 +#endif + +#if MTK_WCN_MT6306_IS_READY +#include + +#ifdef GPIO_GPS_LNA_PIN +#undef GPIO_GPS_LNA_PIN +#endif + +#define GPIO_GPS_LNA_PIN GPIO7 +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +EMI_CTRL_STATE_OFFSET mtk_wcn_emi_state_off = { + .emi_apmem_ctrl_state = EXP_APMEM_CTRL_STATE, + .emi_apmem_ctrl_host_sync_state = EXP_APMEM_CTRL_HOST_SYNC_STATE, + .emi_apmem_ctrl_host_sync_num = EXP_APMEM_CTRL_HOST_SYNC_NUM, + .emi_apmem_ctrl_chip_sync_state = EXP_APMEM_CTRL_CHIP_SYNC_STATE, + .emi_apmem_ctrl_chip_sync_num = EXP_APMEM_CTRL_CHIP_SYNC_NUM, + .emi_apmem_ctrl_chip_sync_addr = EXP_APMEM_CTRL_CHIP_SYNC_ADDR, + .emi_apmem_ctrl_chip_sync_len = EXP_APMEM_CTRL_CHIP_SYNC_LEN, + .emi_apmem_ctrl_chip_print_buff_start = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_START, + .emi_apmem_ctrl_chip_print_buff_len = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_LEN, + .emi_apmem_ctrl_chip_print_buff_idx = EXP_APMEM_CTRL_CHIP_PRINT_BUFF_IDX, + .emi_apmem_ctrl_chip_int_status = EXP_APMEM_CTRL_CHIP_INT_STATUS, + .emi_apmem_ctrl_chip_paded_dump_end = EXP_APMEM_CTRL_CHIP_PAGED_DUMP_END, + .emi_apmem_ctrl_host_outband_assert_w1 = EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1, +}; + +CONSYS_EMI_ADDR_INFO mtk_wcn_emi_addr_info = { + .emi_phy_addr = CONSYS_EMI_FW_PHY_BASE, + .paged_trace_off = CONSYS_EMI_PAGED_TRACE_OFFSET, + .paged_dump_off = CONSYS_EMI_PAGED_DUMP_OFFSET, + .full_dump_off = CONSYS_EMI_FULL_DUMP_OFFSET, + .p_ecso = &mtk_wcn_emi_state_off, +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static VOID wmt_plat_bgf_eirq_cb(VOID); + +static INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state); +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state); + +static INT32 wmt_plat_dump_pin_conf(VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +UINT32 gCoClockFlag = 0; +BGF_IRQ_BALANCE gbgfIrqBle; +UINT32 wmtPlatLogLvl = WMT_PLAT_LOG_DBG; +#if CONSYS_BT_WIFI_SHARE_V33 +BT_WIFI_V33_STATUS gBtWifiV33; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_WMT_WAKELOCK_SUPPORT +static struct mutex gOsSLock; +#ifdef CONFIG_PM_WAKELOCKS +static struct wakeup_source wmtWakeLock; +#else +static struct wake_lock wmtWakeLock; +#endif +#endif + +irq_cb wmt_plat_bgf_irq_cb = NULL; +device_audio_if_cb wmt_plat_audio_if_cb = NULL; +func_ctrl_cb wmt_plat_func_ctrl_cb = NULL; +thermal_query_ctrl_cb wmt_plat_thermal_query_ctrl_cb = NULL; +deep_idle_ctrl_cb wmt_plat_deep_idle_ctrl_cb = NULL; + +static const fp_set_pin gfp_set_pin_table[] = { + [PIN_BGF_EINT] = wmt_plat_bgf_eint_ctrl, + [PIN_I2S_GRP] = wmt_plat_i2s_ctrl, + [PIN_GPS_SYNC] = wmt_plat_gps_sync_ctrl, + [PIN_GPS_LNA] = wmt_plat_gps_lna_ctrl, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*! + * \brief audio control callback function for CMB_STUB on ALPS + * + * A platform function required for dynamic binding with CMB_STUB on ALPS. + * + * \param state desired audio interface state to use + * \param flag audio interface control options + * + * \retval 0 operation success + * \retval -1 invalid parameters + * \retval < 0 error for operation fail + */ +INT32 wmt_plat_audio_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl) +{ + INT32 iRet = 0; + UINT32 pinShare = 0; + + /* input sanity check */ + if ((CMB_STUB_AIF_MAX <= state) + || (CMB_STUB_AIF_CTRL_MAX <= ctrl)) { + return -1; + } + + iRet = 0; + + /* set host side first */ + switch (state) { + case CMB_STUB_AIF_0: + /* BT_PCM_OFF & FM line in/out */ + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_1: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_DEINIT); + break; + + case CMB_STUB_AIF_2: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + case CMB_STUB_AIF_3: + iRet += wmt_plat_gpio_ctrl(PIN_I2S_GRP, PIN_STA_INIT); + break; + + default: + /* FIXME: move to cust folder? */ + WMT_PLAT_ERR_FUNC("invalid state [%d]\n", state); + iRet = -1; + break; + } + + if (CMB_STUB_AIF_CTRL_EN == ctrl) { + WMT_PLAT_INFO_FUNC("call chip aif setting\n"); + /* need to control chip side GPIO */ + if (NULL != wmt_plat_audio_if_cb) { + iRet += (*wmt_plat_audio_if_cb) (state, (pinShare) ? MTK_WCN_BOOL_TRUE : MTK_WCN_BOOL_FALSE); + } else { + WMT_PLAT_WARN_FUNC("wmt_plat_audio_if_cb is not registered\n"); + iRet -= 1; + } + + } else { + WMT_PLAT_INFO_FUNC("skip chip aif setting\n"); + } + + return iRet; + +} + +static VOID wmt_plat_func_ctrl(UINT32 type, UINT32 on) +{ + if (wmt_plat_func_ctrl_cb) + (*wmt_plat_func_ctrl_cb) (on, type); +} + +static long wmt_plat_thermal_ctrl(VOID) +{ + long temp = 0; + + if (wmt_plat_thermal_query_ctrl_cb) + temp = (*wmt_plat_thermal_query_ctrl_cb) (); + + return temp; +} + +static INT32 wmt_plat_deep_idle_ctrl(UINT32 dpilde_ctrl) +{ + INT32 iRet = -1; + + if (wmt_plat_deep_idle_ctrl_cb) + iRet = (*wmt_plat_deep_idle_ctrl_cb) (dpilde_ctrl); + + return iRet; +} + +static VOID wmt_plat_bgf_eirq_cb(VOID) +{ +#if CFG_WMT_PS_SUPPORT +/* #error "need to disable EINT here" */ + /* wmt_lib_ps_irq_cb(); */ + if (NULL != wmt_plat_bgf_irq_cb) + (*(wmt_plat_bgf_irq_cb)) (); + else + WMT_PLAT_WARN_FUNC("WMT-PLAT: wmt_plat_bgf_irq_cb not registered\n"); +#else + return; +#endif + +} + +irqreturn_t wmt_plat_bgf_irq_isr(INT32 i, VOID *arg) +{ +#if CFG_WMT_PS_SUPPORT + wmt_plat_eirq_ctrl(PIN_BGF_EINT, PIN_STA_EINT_DIS); + wmt_plat_bgf_eirq_cb(); +#else + WMT_PLAT_INFO_FUNC("skip irq handing because psm is disable"); +#endif + return IRQ_HANDLED; +} + +VOID wmt_plat_irq_cb_reg(irq_cb bgf_irq_cb) +{ + wmt_plat_bgf_irq_cb = bgf_irq_cb; +} +EXPORT_SYMBOL(wmt_plat_irq_cb_reg); + +VOID wmt_plat_aif_cb_reg(device_audio_if_cb aif_ctrl_cb) +{ + wmt_plat_audio_if_cb = aif_ctrl_cb; +} +EXPORT_SYMBOL(wmt_plat_aif_cb_reg); + +VOID wmt_plat_func_ctrl_cb_reg(func_ctrl_cb subsys_func_ctrl) +{ + wmt_plat_func_ctrl_cb = subsys_func_ctrl; +} +EXPORT_SYMBOL(wmt_plat_func_ctrl_cb_reg); + +VOID wmt_plat_thermal_ctrl_cb_reg(thermal_query_ctrl_cb thermal_query_ctrl) +{ + wmt_plat_thermal_query_ctrl_cb = thermal_query_ctrl; +} +EXPORT_SYMBOL(wmt_plat_thermal_ctrl_cb_reg); + +VOID wmt_plat_deep_idle_ctrl_cb_reg(deep_idle_ctrl_cb deep_idle_ctrl) +{ + wmt_plat_deep_idle_ctrl_cb = deep_idle_ctrl; +} +EXPORT_SYMBOL(wmt_plat_deep_idle_ctrl_cb_reg); + +UINT32 wmt_plat_soc_co_clock_flag_get(VOID) +{ + return gCoClockFlag; +} + +static UINT32 wmt_plat_soc_co_clock_flag_set(UINT32 flag) +{ + gCoClockFlag = flag; + return 0; +} + +INT32 wmt_plat_init(UINT32 co_clock_type) +{ + CMB_STUB_CB stub_cb; + INT32 iret; + /*init wmt function ctrl wakelock if wake lock is supported by host platform */ + + wmt_plat_soc_co_clock_flag_set(co_clock_type); + + stub_cb.aif_ctrl_cb = wmt_plat_audio_ctrl; + stub_cb.func_ctrl_cb = wmt_plat_func_ctrl; + stub_cb.thermal_query_cb = wmt_plat_thermal_ctrl; + stub_cb.deep_idle_ctrl_cb = wmt_plat_deep_idle_ctrl; + stub_cb.size = sizeof(stub_cb); + + /* register to cmb_stub */ + iret = mtk_wcn_cmb_stub_reg(&stub_cb); +#ifdef CFG_WMT_WAKELOCK_SUPPORT +#ifdef CONFIG_PM_WAKELOCKS + wakeup_source_init(&wmtWakeLock, "wmtFuncCtrl"); +#else + wake_lock_init(&wmtWakeLock, WAKE_LOCK_SUSPEND, "wmtFuncCtrl"); +#endif + mutex_init(&gOsSLock); +#endif + +#if CONSYS_BT_WIFI_SHARE_V33 + gBtWifiV33.counter = 0; + spin_lock_init(&gBtWifiV33.lock); +#endif + + iret += mtk_wcn_consys_hw_init(); + + spin_lock_init(&gbgfIrqBle.lock); + WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_init); + +INT32 wmt_plat_deinit(VOID) +{ + INT32 iret = 0; + /* 2. unreg to cmb_stub */ + iret = mtk_wcn_cmb_stub_unreg(); +printk(KERN_ALERT "DEBUG: Passed %s %d now calling wmt wakelock deinit\n",__FUNCTION__,__LINE__); + /*3. wmt wakelock deinit */ +#ifdef CFG_WMT_WAKELOCK_SUPPORT +#ifdef CONFIG_PM_WAKELOCKS +printk(KERN_ALERT "DEBUG: Passed %s %d now calling wakeup_source_trash\n",__FUNCTION__,__LINE__); + wakeup_source_trash(&wmtWakeLock); +#else +printk(KERN_ALERT "DEBUG: Passed %s %d now calling wake lock destroy %d\n",__FUNCTION__,__LINE__,(int)&wmtWakeLock); +//destroy calls wakeup_source_trash with &lock->ws +printk(KERN_ALERT "DEBUG: Passed %s %d now wmtWakeLock:%d\n",__FUNCTION__,__LINE__,(int)&wmtWakeLock); +printk(KERN_ALERT "DEBUG: Passed %s %d now wmtWakeLock->ws: %d\n",__FUNCTION__,__LINE__,(int)&(wmtWakeLock.ws)); + wake_lock_destroy(&wmtWakeLock); +#endif +printk(KERN_ALERT "DEBUG: Passed %s %d now calling mutex_destroy\n",__FUNCTION__,__LINE__); + mutex_destroy(&gOsSLock); + WMT_PLAT_DBG_FUNC("destroy wmtWakeLock\n"); +#endif +printk(KERN_ALERT "DEBUG: Passed %s %d now calling consys hw deinit\n",__FUNCTION__,__LINE__); + + iret += mtk_wcn_consys_hw_deinit(); + + WMT_PLAT_DBG_FUNC("WMT-PLAT: ALPS platform init (%d)\n", iret); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_deinit); + +static INT32 wmt_plat_dump_pin_conf(VOID) +{ + WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration start<=\n"); +#if defined(CONFIG_MTK_GPIO_LEGACY) + +#ifdef GPIO_COMBO_BGF_EINT_PIN + WMT_PLAT_DBG_FUNC("BGF_EINT(GPIO%d)\n", GPIO_COMBO_BGF_EINT_PIN); +#else + WMT_PLAT_DBG_FUNC("BGF_EINT(not defined)\n"); +#endif + +#ifdef CUST_EINT_COMBO_BGF_NUM + WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(%d)\n", CUST_EINT_COMBO_BGF_NUM); +#else + WMT_PLAT_DBG_FUNC("BGF_EINT_NUM(not defined)\n"); +#endif + +#ifdef GPIO_COMBO_URXD_PIN + WMT_PLAT_DBG_FUNC("UART_RX(GPIO%d)\n", GPIO_COMBO_URXD_PIN); +#else + WMT_PLAT_DBG_FUNC("UART_RX(not defined)\n"); +#endif +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) +#ifdef GPIO_COMBO_I2S_CK_PIN + WMT_PLAT_DBG_FUNC("I2S_CK(GPIO%d)\n", GPIO_COMBO_I2S_CK_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_CK(not defined)\n"); +#endif +#ifdef GPIO_COMBO_I2S_WS_PIN + WMT_PLAT_DBG_FUNC("I2S_WS(GPIO%d)\n", GPIO_COMBO_I2S_WS_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_WS(not defined)\n"); +#endif +#ifdef GPIO_COMBO_I2S_DAT_PIN + WMT_PLAT_DBG_FUNC("I2S_DAT(GPIO%d)\n", GPIO_COMBO_I2S_DAT_PIN); +#else + WMT_PLAT_DBG_FUNC("I2S_DAT(not defined)\n"); +#endif +#else /* FM_ANALOG_INPUT || FM_ANALOG_OUTPUT */ + WMT_PLAT_DBG_FUNC("FM digital mode is not set, no need for I2S GPIOs\n"); +#endif +#ifdef GPIO_GPS_SYNC_PIN + WMT_PLAT_DBG_FUNC("GPS_SYNC(GPIO%d)\n", GPIO_GPS_SYNC_PIN); +#else + WMT_PLAT_DBG_FUNC("GPS_SYNC(not defined)\n"); +#endif + +#ifdef GPIO_GPS_LNA_PIN + WMT_PLAT_INFO_FUNC("GPS_LNA(GPIO%d)\n", GPIO_GPS_LNA_PIN); +#else + WMT_PLAT_INFO_FUNC("GPS_LNA(not defined)\n"); +#endif + +#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ +#endif + WMT_PLAT_DBG_FUNC("[WMT-PLAT]=>dump wmt pin configuration emds<=\n"); + return 0; +} + +INT32 wmt_plat_pwr_ctrl(ENUM_FUNC_STATE state) +{ + INT32 ret = -1; + + switch (state) { + case FUNC_ON: + /* TODO:[ChangeFeature][George] always output this or by request throuth /proc or sysfs? */ + wmt_plat_dump_pin_conf(); + ret = mtk_wcn_consys_hw_pwr_on(gCoClockFlag); + break; + + case FUNC_OFF: + ret = mtk_wcn_consys_hw_pwr_off(); + break; + + case FUNC_RST: + ret = mtk_wcn_consys_hw_rst(gCoClockFlag); + break; + case FUNC_STAT: + ret = mtk_wcn_consys_hw_state_show(); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) in pwr_ctrl\n", state); + break; + } + + return ret; +} +EXPORT_SYMBOL(wmt_plat_pwr_ctrl); + +INT32 wmt_plat_eirq_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) +{ +#ifdef CONFIG_OF + struct device_node *node; + unsigned int irq_info[3] = { 0, 0, 0 }; +#endif + INT32 iret = -EINVAL; + static INT32 bgf_irq_num = -1; + static UINT32 bgf_irq_flag; + /* TODO: [ChangeFeature][GeorgeKuo]: use another function to handle this, as done in gpio_ctrls */ + + if ((PIN_STA_INIT != state) + && (PIN_STA_DEINIT != state) + && (PIN_STA_EINT_EN != state) + && (PIN_STA_EINT_DIS != state)) { + WMT_PLAT_WARN_FUNC("WMT-PLAT:invalid PIN_STATE(%d) in eirq_ctrl for PIN(%d)\n", state, id); + return -1; + } + + switch (id) { + case PIN_BGF_EINT: + + if (PIN_STA_INIT == state) { +#ifdef CONFIG_OF + node = of_find_compatible_node(NULL, NULL, "mediatek,mt7623-consys"); + if (node) { + bgf_irq_num = irq_of_parse_and_map(node, 0); + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + WMT_PLAT_ERR_FUNC("get irq flags from DTS fail!!\n"); + return iret; + } + bgf_irq_flag = irq_info[2]; + WMT_PLAT_INFO_FUNC("get irq id(%d) and irq trigger flag(%d) from DT\n", bgf_irq_num, + bgf_irq_flag); + } else { + WMT_PLAT_ERR_FUNC("[%s] can't find CONSYS compatible node\n", __func__); + return iret; + } +#else + bgf_irq_num = MT_CONN2AP_BTIF_WAKEUP_IRQ_ID; + bgf_irq_flag = IRQF_TRIGGER_LOW; +#endif + iret = request_irq(bgf_irq_num, wmt_plat_bgf_irq_isr, bgf_irq_flag, "BTIF_WAKEUP_IRQ", NULL); + if (iret) { + WMT_PLAT_ERR_FUNC("request_irq fail,irq_no(%d),iret(%d)\n", bgf_irq_num, iret); + return iret; + } + gbgfIrqBle.counter = 1; + + } else if (PIN_STA_EINT_EN == state) { + + spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); + if (gbgfIrqBle.counter) { + WMT_PLAT_DBG_FUNC("BGF INT has been enabled,counter(%d)\n", gbgfIrqBle.counter); + } else { + enable_irq(bgf_irq_num); + gbgfIrqBle.counter++; + } + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (en)\n"); + spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); + } else if (PIN_STA_EINT_DIS == state) { + spin_lock_irqsave(&gbgfIrqBle.lock, gbgfIrqBle.flags); + if (!gbgfIrqBle.counter) { + WMT_PLAT_INFO_FUNC("BGF INT has been disabled,counter(%d)\n", gbgfIrqBle.counter); + } else { + disable_irq_nosync(bgf_irq_num); + gbgfIrqBle.counter--; + } + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt (dis)\n"); + spin_unlock_irqrestore(&gbgfIrqBle.lock, gbgfIrqBle.flags); + } else { + free_irq(bgf_irq_num, NULL); + /* de-init: nothing to do in ALPS, such as un-registration... */ + } + iret = 0; + break; + + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:unsupported EIRQ(PIN_ID:%d) in eirq_ctrl\n", id); + iret = -1; + break; + } + + return iret; +} +EXPORT_SYMBOL(wmt_plat_eirq_ctrl); + +INT32 wmt_plat_gpio_ctrl(ENUM_PIN_ID id, ENUM_PIN_STATE state) +{ + if ((PIN_ID_MAX > id) + && (PIN_STA_MAX > state)) { + + /* TODO: [FixMe][GeorgeKuo] do sanity check to const function table when init and skip checking here */ + if (gfp_set_pin_table[id]) + return (*(gfp_set_pin_table[id])) (state); /* .handler */ + WMT_PLAT_WARN_FUNC("WMT-PLAT: null fp for gpio_ctrl(%d)\n", id); + return -2; + } + return -1; +} +EXPORT_SYMBOL(wmt_plat_gpio_ctrl); + +INT32 wmt_plat_bgf_eint_ctrl(ENUM_PIN_STATE state) +{ +#if defined(CONFIG_MTK_GPIO_LEGACY) +#ifdef GPIO_COMBO_BGF_EINT_PIN + switch (state) { + case PIN_STA_INIT: + /*set to gpio input low, pull down enable */ + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt init(in pd)\n"); + break; + + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_UP); + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_EINT); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt mux (eint)\n"); + break; + + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + /*set to gpio input low, pull down enable */ + mt_set_gpio_mode(GPIO_COMBO_BGF_EINT_PIN, GPIO_COMBO_BGF_EINT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_BGF_EINT_PIN, GPIO_DIR_IN); + mt_set_gpio_pull_select(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_DOWN); + mt_set_gpio_pull_enable(GPIO_COMBO_BGF_EINT_PIN, GPIO_PULL_ENABLE); + WMT_PLAT_DBG_FUNC("WMT-PLAT:BGFInt deinit(in pd)\n"); + break; + + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on BGF EINT\n", state); + break; + } +#else + WMT_PLAT_INFO_FUNC("WMT-PLAT:BGF EINT not defined\n"); +#endif +#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ +#endif + return 0; +} + +static INT32 wmt_plat_gps_sync_ctrl(ENUM_PIN_STATE state) +{ +#if defined(CONFIG_MTK_GPIO_LEGACY) + +#ifdef GPIO_GPS_SYNC_PIN +#ifndef GPIO_GPS_SYNC_PIN_M_GPS_SYNC +#ifdef GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC +#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD1_GPS_SYNC +#else +#ifdef GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC +#define GPIO_GPS_SYNC_PIN_M_GPS_SYNC GPIO_GPS_SYNC_PIN_M_MD2_GPS_SYNC +#endif +#endif +#endif + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_GPS_SYNC_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_GPS_SYNC_PIN, GPIO_OUT_ZERO); + break; + + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_GPS_SYNC_PIN, GPIO_GPS_SYNC_PIN_M_GPS_SYNC); + break; + + default: + break; + } +#endif + +#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ +#endif + return 0; +} + +#if MTK_WCN_MT6306_IS_READY +/* MT6306 GPIO7 is GPIO_GPS_LNA_EN, for K2 common phone pin modification */ +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) +{ +#ifdef GPIO_GPS_LNA_PIN + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + WMT_PLAT_ERR_FUNC("Gps LNA pin ctrl %d!\n", state); + mt6306_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + case PIN_STA_OUT_H: + WMT_PLAT_ERR_FUNC("Gps LNA pin output high!\n"); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); + break; + case PIN_STA_OUT_L: + WMT_PLAT_ERR_FUNC("Gps LNA pin output low!\n"); + mt6306_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else + WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); + return 0; +#endif +} +#else + +static INT32 wmt_plat_gps_lna_ctrl(ENUM_PIN_STATE state) +{ +#if !defined(CONFIG_MTK_GPIO_LEGACY) + static struct pinctrl_state *gps_lna_init; + static struct pinctrl_state *gps_lna_oh; + static struct pinctrl_state *gps_lna_ol; + static struct pinctrl *consys_pinctrl; + + WMT_PLAT_DBG_FUNC("ENTER++\n"); + consys_pinctrl = mtk_wcn_consys_get_pinctrl(); + if (NULL == consys_pinctrl) { + WMT_PLAT_ERR_FUNC("get consys pinctrl fail\n"); + return -1; + } + + gps_lna_init = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_init"); + if (NULL == gps_lna_init) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin init state!\n"); + return -2; + } + + gps_lna_oh = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_oh"); + if (NULL == gps_lna_oh) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin oh state!\n"); + return -3; + } + + gps_lna_ol = pinctrl_lookup_state(consys_pinctrl, "gps_lna_state_ol"); + if (NULL == gps_lna_ol) { + WMT_PLAT_ERR_FUNC("Cannot find gps lna pin ol state!\n"); + return -4; + } + + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + pinctrl_select_state(consys_pinctrl, gps_lna_init); + WMT_PLAT_INFO_FUNC("set gps lna to init\n"); + break; + case PIN_STA_OUT_H: + pinctrl_select_state(consys_pinctrl, gps_lna_oh); + WMT_PLAT_INFO_FUNC("set gps lna to oh\n"); + break; + case PIN_STA_OUT_L: + pinctrl_select_state(consys_pinctrl, gps_lna_ol); + WMT_PLAT_INFO_FUNC("set gps lna to ol\n"); + break; + + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else +#ifdef GPIO_GPS_LNA_PIN + switch (state) { + case PIN_STA_INIT: + case PIN_STA_DEINIT: + mt_set_gpio_pull_enable(GPIO_GPS_LNA_PIN, GPIO_PULL_DISABLE); + mt_set_gpio_dir(GPIO_GPS_LNA_PIN, GPIO_DIR_OUT); + mt_set_gpio_mode(GPIO_GPS_LNA_PIN, GPIO_GPS_LNA_PIN_M_GPIO); + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + case PIN_STA_OUT_H: + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ONE); + break; + case PIN_STA_OUT_L: + mt_set_gpio_out(GPIO_GPS_LNA_PIN, GPIO_OUT_ZERO); + break; + + default: + WMT_PLAT_WARN_FUNC("%d mode not defined for gps lna pin !!!\n", state); + break; + } + return 0; +#else + WMT_PLAT_WARN_FUNC("host gps lna pin not defined!!!\n"); + return 0; +#endif +#endif /* !defined(CONFIG_MTK_GPIO_LEGACY) */ +} +#endif + +INT32 wmt_plat_i2s_ctrl(ENUM_PIN_STATE state) +{ + /* TODO: [NewFeature][GeorgeKuo]: GPIO_I2Sx is changed according to different project. */ + /* TODO: provide a translation table in board_custom.h for different ALPS project customization. */ +#if defined(CONFIG_MTK_GPIO_LEGACY) + +#if defined(FM_DIGITAL_INPUT) || defined(FM_DIGITAL_OUTPUT) +#if defined(GPIO_COMBO_I2S_CK_PIN) + switch (state) { + case PIN_STA_INIT: + case PIN_STA_MUX: + mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_I2S0_CK); + mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_I2S0_WS); + mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_I2S0_DAT); + WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S init (I2S0 system)\n"); + break; + case PIN_STA_IN_L: + case PIN_STA_DEINIT: + mt_set_gpio_mode(GPIO_COMBO_I2S_CK_PIN, GPIO_COMBO_I2S_CK_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_CK_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_CK_PIN, GPIO_OUT_ZERO); + + mt_set_gpio_mode(GPIO_COMBO_I2S_WS_PIN, GPIO_COMBO_I2S_WS_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_WS_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_WS_PIN, GPIO_OUT_ZERO); + + mt_set_gpio_mode(GPIO_COMBO_I2S_DAT_PIN, GPIO_COMBO_I2S_DAT_PIN_M_GPIO); + mt_set_gpio_dir(GPIO_COMBO_I2S_DAT_PIN, GPIO_DIR_OUT); + mt_set_gpio_out(GPIO_COMBO_I2S_DAT_PIN, GPIO_OUT_ZERO); + WMT_PLAT_DBG_FUNC("WMT-PLAT:I2S deinit (out 0)\n"); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid state(%d) on I2S Group\n", state); + break; + } +#else + WMT_PLAT_ERR_FUNC("[MT6620]Error:FM digital mode set, but no I2S GPIOs defined\n"); +#endif +#else + WMT_PLAT_INFO_FUNC + ("[MT6620]warnning:FM digital mode is not set, no I2S GPIO settings should be modified by combo driver\n"); +#endif + +#else /* #if defined(CONFIG_MTK_GPIO_LEGACY) */ +#endif + return 0; +} + +INT32 wmt_plat_wake_lock_ctrl(ENUM_WL_OP opId) +{ +#ifdef CFG_WMT_WAKELOCK_SUPPORT + static INT32 counter; + INT32 status; + INT32 ret = 0; + + ret = mutex_lock_killable(&gOsSLock); + if (ret) { + WMT_PLAT_ERR_FUNC("--->lock gOsSLock failed, ret=%d\n", ret); + return ret; + } + + if (WL_OP_GET == opId) + ++counter; + else if (WL_OP_PUT == opId) + --counter; + + mutex_unlock(&gOsSLock); + if (WL_OP_GET == opId && counter == 1) { + #ifdef CONFIG_PM_WAKELOCKS + __pm_stay_awake(&wmtWakeLock); + status = wmtWakeLock.active; + #else + wake_lock(&wmtWakeLock); + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_lock(%d), counter(%d)\n", status, counter); + + } else if (WL_OP_PUT == opId && counter == 0) { + #ifdef CONFIG_PM_WAKELOCKS + __pm_relax(&wmtWakeLock); + status = wmtWakeLock.active; + #else + wake_unlock(&wmtWakeLock); + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_DBG_FUNC("WMT-PLAT: after wake_unlock(%d), counter(%d)\n", status, counter); + } else { + #ifdef CONFIG_PM_WAKELOCKS + status = wmtWakeLock.active; + #else + status = wake_lock_active(&wmtWakeLock); + #endif + WMT_PLAT_WARN_FUNC("WMT-PLAT: wakelock status(%d), counter(%d)\n", status, counter); + } + return 0; +#else + WMT_PLAT_WARN_FUNC("WMT-PLAT: host awake function is not supported.\n"); + return 0; + +#endif +} +EXPORT_SYMBOL(wmt_plat_wake_lock_ctrl); + +INT32 wmt_plat_soc_paldo_ctrl(ENUM_PALDO_TYPE ePt, ENUM_PALDO_OP ePo) +{ + INT32 iRet = 0; + + switch (ePt) { + + case BT_PALDO: + iRet = mtk_wcn_consys_hw_bt_paldo_ctrl(ePo); + break; + case WIFI_PALDO: + iRet = mtk_wcn_consys_hw_wifi_paldo_ctrl(ePo); + break; + case FM_PALDO: + case GPS_PALDO: + iRet = mtk_wcn_consys_hw_vcn28_ctrl(ePo); + break; + default: + WMT_PLAT_WARN_FUNC("WMT-PLAT:Warnning, invalid type(%d) in palod_ctrl\n", ePt); + break; + } + return iRet; +} +EXPORT_SYMBOL(wmt_plat_soc_paldo_ctrl); + +UINT8 *wmt_plat_get_emi_virt_add(UINT32 offset) +{ + return mtk_wcn_consys_emi_virt_addr_get(offset); +} +EXPORT_SYMBOL(wmt_plat_get_emi_virt_add); + +P_CONSYS_EMI_ADDR_INFO wmt_plat_get_emi_phy_add(VOID) +{ + return &mtk_wcn_emi_addr_info; +} +EXPORT_SYMBOL(wmt_plat_get_emi_phy_add); + +#if CONSYS_ENALBE_SET_JTAG +UINT32 wmt_plat_jtag_flag_ctrl(UINT32 en) +{ + return 0; +} +EXPORT_SYMBOL(wmt_plat_jtag_flag_ctrl); +#endif + +#if CFG_WMT_DUMP_INT_STATUS +VOID wmt_plat_BGF_irq_dump_status(VOID) +{ + WMT_PLAT_INFO_FUNC("this function is null in MT8127\n"); +} +EXPORT_SYMBOL(wmt_plat_BGF_irq_dump_status); + +MTK_WCN_BOOL wmt_plat_dump_BGF_irq_status(VOID) +{ + return MTK_WCN_BOOL_FALSE; +} +EXPORT_SYMBOL(wmt_plat_dump_BGF_irq_status); +#endif + +UINT32 wmt_plat_read_cpupcr(void) +{ + return CONSYS_REG_READ(conn_reg.mcu_base + CONSYS_CPUPCR_OFFSET); +} +EXPORT_SYMBOL(wmt_plat_read_cpupcr); + +UINT32 wmt_plat_read_dmaregs(UINT32 type) +{ + return 0; +#if 0 + switch (type) { + case CONNSYS_CLK_GATE_STATUS: + return CONSYS_REG_READ(CONNSYS_CLK_GATE_STATUS_REG); + case CONSYS_EMI_STATUS: + return CONSYS_REG_READ(CONSYS_EMI_STATUS_REG); + case SYSRAM1: + return CONSYS_REG_READ(SYSRAM1_REG); + case SYSRAM2: + return CONSYS_REG_READ(SYSRAM2_REG); + case SYSRAM3: + return CONSYS_REG_READ(SYSRAM3_REG); + default: + return 0; + } +#endif +} + +INT32 wmt_plat_set_host_dump_state(ENUM_HOST_DUMP_STATE state) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_STATE); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, state); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_set_host_dump_state); + +UINT32 wmt_plat_force_trigger_assert(ENUM_FORCE_TRG_ASSERT_T type) +{ + PUINT8 p_virtual_addr = NULL; + + switch (type) { + case STP_FORCE_TRG_ASSERT_EMI: + + WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi -->\n"); + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_OUTBAND_ASSERT_W1); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + CONSYS_REG_WRITE(p_virtual_addr, EXP_APMEM_HOST_OUTBAND_ASSERT_MAGIC_W1); + WMT_PLAT_INFO_FUNC("[Force Assert] stp_trigger_firmware_assert_via_emi <--\n"); + break; + case STP_FORCE_TRG_ASSERT_DEBUG_PIN: + + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + + CONSYS_AP2CONN_OSC_EN_OFFSET) & ~CONSYS_AP2CONN_WAKEUP_BIT); + WMT_PLAT_INFO_FUNC("enable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); + usleep_range(64, 96); + CONSYS_REG_WRITE(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET, + CONSYS_REG_READ(conn_reg.topckgen_base + + CONSYS_AP2CONN_OSC_EN_OFFSET) | CONSYS_AP2CONN_WAKEUP_BIT); + WMT_PLAT_INFO_FUNC("disable:dump CONSYS_AP2CONN_OSC_EN_REG(0x%x)\n", + CONSYS_REG_READ(conn_reg.topckgen_base + CONSYS_AP2CONN_OSC_EN_OFFSET)); + + break; + default: + WMT_PLAT_ERR_FUNC("unknown force trigger assert type\n"); + break; + } + + return 0; +} +EXPORT_SYMBOL(wmt_plat_force_trigger_assert); + +INT32 wmt_plat_update_host_sync_num(VOID) +{ + PUINT8 p_virtual_addr = NULL; + UINT32 sync_num = 0; + + p_virtual_addr = wmt_plat_get_emi_virt_add(EXP_APMEM_CTRL_HOST_SYNC_NUM); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + + sync_num = CONSYS_REG_READ(p_virtual_addr); + CONSYS_REG_WRITE(p_virtual_addr, sync_num + 1); + + return 0; +} +EXPORT_SYMBOL(wmt_plat_update_host_sync_num); + +INT32 wmt_plat_get_dump_info(UINT32 offset) +{ + PUINT8 p_virtual_addr = NULL; + + p_virtual_addr = wmt_plat_get_emi_virt_add(offset); + if (!p_virtual_addr) { + WMT_PLAT_ERR_FUNC("get virtual address fail\n"); + return -1; + } + WMT_PLAT_INFO_FUNC("connsys_reg_read (0x%x), (0x%p), (0x%x)\n", CONSYS_REG_READ(p_virtual_addr), p_virtual_addr, + offset); + return CONSYS_REG_READ(p_virtual_addr); +} +EXPORT_SYMBOL(wmt_plat_get_dump_info); + +UINT32 wmt_plat_get_soc_chipid(void) +{ + UINT32 chipId = mtk_wcn_consys_soc_chipid(); + + WMT_PLAT_INFO_FUNC("current SOC chip:0x%x\n", chipId); + return chipId; +} +EXPORT_SYMBOL(wmt_plat_get_soc_chipid); + +#if CFG_WMT_LTE_COEX_HANDLING +INT32 wmt_plat_get_tdm_antsel_index(VOID) +{ + WMT_PLAT_INFO_FUNC("not support LTE in this platform\n"); + return 0; +} +EXPORT_SYMBOL(wmt_plat_get_tdm_antsel_index); +#endif +INT32 wmt_plat_set_dbg_mode(UINT32 flag) +{ + return -1; +} +VOID wmt_plat_set_dynamic_dumpmem(UINT32 *buf) +{ + mtk_wcn_consys_set_dynamic_dump(buf); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/Makefile b/drivers/misc/mediatek/connectivity/wlan/Makefile new file mode 100644 index 0000000000000..2961aeb073eaa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/Makefile @@ -0,0 +1,8 @@ +ifeq ($(CONFIG_MTK_COMBO_WIFI),y) + subdir-ccflags-y += -D MTK_WCN_BUILT_IN_DRIVER +endif + +ifneq ($(filter "CONSYS_%",$(CONFIG_MTK_COMBO_CHIP)),) +#$(warning include gen2) + obj-y += gen2/ +endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile b/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile new file mode 100644 index 0000000000000..b86ab49fce3a0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/Makefile @@ -0,0 +1,237 @@ +# --------------------------------------------------- +# Compile Options +# --------------------------------------------------- +ccflags-y += -DLINUX -DMT6628 + +ccflags-y += -DCFG_SUPPORT_AGPS_ASSIST=1 +ccflags-y += -DCFG_SUPPORT_TSF_USING_BOOTTIME=1 +ccflags-y += -DCFG_P2P_LEGACY_COEX_REVISE=1 +ccflags-y += -DARP_MONITER_ENABLE=1 + +ifeq ($(CONFIG_MTK_WAPI_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_WAPI=1 +else + ccflags-y += -DCFG_SUPPORT_WAPI=0 +endif + +ifeq ($(CONFIG_MTK_WIFI_MCC_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_MCC=1 +else + ccflags-y += -DCFG_SUPPORT_MCC=0 +endif + +ifeq ($(CONFIG_HAVE_XLOG_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_XLOG=1 +else + ccflags-y += -DCFG_SUPPORT_XLOG=0 +endif + +ifeq ($(CONFIG_MTK_AEE_FEATURE), y) + ccflags-y += -DCFG_SUPPORT_AEE=1 +else + ccflags-y += -DCFG_SUPPORT_AEE=0 +endif + +#ifeq ($(CONFIG_MTK_COMBO_WIFI_HIF_SDIO1), y) +# ccflags-y += -D_HIF_SDIO=1 +#endif + +ifeq ($(CONFIG_MTK_PASSPOINT_R1_SUPPORT), y) + ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=1 + ccflags-y += -DCFG_HS20_DEBUG=1 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=1 +else + ccflags-y += -DCFG_SUPPORT_HOTSPOT_2_0=0 + ccflags-y += -DCFG_HS20_DEBUG=0 + ccflags-y += -DCFG_ENABLE_GTK_FRAME_FILTER=0 +endif + +MTK_MET_PROFILING_SUPPORT = no +ifeq ($(MTK_MET_PROFILING_SUPPORT), yes) + ccflags-y += -DCFG_SUPPORT_MET_PROFILING=1 +else + ccflags-y += -DCFG_SUPPORT_MET_PROFILING=0 +endif + +ifeq ($(CONFIG_MTK_TC1_FEATURE), y) +ifeq ($(CONFIG_MTK_GPT_SCHEME_SUPPORT), y) + ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface/gpt +else + ccflags-y += -I$(srctree)/drivers/misc/mediatek/tc1_interface/pmt +endif + ccflags-y += -DCFG_TC1_FEATURE=1 + ccflags-y += -DCFG_SUPPORT_CFG_FILE=1 +else + ccflags-y += -DCFG_TC1_FEATURE=0 +endif + +MTK_SRAM_SIZE_OPTION=0 +ifeq ($(CONFIG_ARCH_MT6755), y) + MTK_SRAM_SIZE_OPTION=2 +endif +ifeq ($(CONFIG_ARCH_MT6735), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT6735M), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT6753), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT6580), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ifeq ($(CONFIG_ARCH_MT8163), y) + MTK_SRAM_SIZE_OPTION=1 +endif +ccflags-y += -DCFG_SRAM_SIZE_OPTION=$(MTK_SRAM_SIZE_OPTION) + +ifeq ($(strip $(TRUSTONIC_TEE_SUPPORT)),yes) +ifeq ($(strip $(MTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT)),yes) + ccflags-y += -DTRUSTONIC_TEE_SUPPORT + ccflags-y += -DMTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT +endif +endif + +ccflags-y += -D_HIF_SDIO=1 + +ccflags-y += -DDBG=0 +ccflags-y += -I$(src)/os -I$(src)/os/linux/include -I$(src)/os/linux/hif/ahb/include +ccflags-y += -I$(src)/include -I$(src)/include/nic -I$(src)/include/mgmt +ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include +ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/ + +MODULE_NAME := wlan_gen2 +obj-$(CONFIG_MTK_COMBO_WIFI) += $(MODULE_NAME).o +#obj-m += $(MODULE_NAME).o if CONFIG_MTK_COMBO_WIFI=m ==> obj-m means ko module, not build in obj-y + +# --------------------------------------------------- +# Directory List +# --------------------------------------------------- +COMMON_DIR := common/ +OS_DIR := os/linux/ +HIF_DIR := os/linux/hif/ahb/ +NIC_DIR := nic/ +MGMT_DIR := mgmt/ +DMA_DIR := ../../../../platform/$(call lc,$(MTK_PLATFORM))/kernel/drivers/wifi/ +PLAT_DIR := os/linux/plat/$(MTK_PLATFORM)/ +HIF_AHB_PDMA := $(HIF_DIR)$(MTK_PLATFORM)/ +#$(call lc,$(MTK_PLATFORM)) + + +# --------------------------------------------------- +# Objects List +# --------------------------------------------------- + +COMMON_OBJS := $(COMMON_DIR)dump.o \ + $(COMMON_DIR)wlan_lib.o \ + $(COMMON_DIR)wlan_oid.o \ + $(COMMON_DIR)wlan_bow.o \ + $(COMMON_DIR)debug.o + +NIC_OBJS := $(NIC_DIR)nic.o \ + $(NIC_DIR)nic_tx.o \ + $(NIC_DIR)nic_rx.o \ + $(NIC_DIR)nic_pwr_mgt.o \ + $(NIC_DIR)cmd_buf.o \ + $(NIC_DIR)que_mgt.o \ + $(NIC_DIR)nic_cmd_event.o + +OS_OBJS := $(OS_DIR)gl_init.o \ + $(OS_DIR)gl_kal.o \ + $(OS_DIR)gl_bow.o \ + $(OS_DIR)gl_wext.o \ + $(OS_DIR)gl_wext_priv.o \ + $(OS_DIR)gl_rst.o \ + $(OS_DIR)gl_cfg80211.o \ + $(OS_DIR)gl_vendor.o \ + $(OS_DIR)platform.o \ + $(OS_DIR)gl_proc.o + +MGMT_OBJS := $(MGMT_DIR)ais_fsm.o \ + $(MGMT_DIR)aaa_fsm.o \ + $(MGMT_DIR)assoc.o \ + $(MGMT_DIR)auth.o \ + $(MGMT_DIR)bss.o \ + $(MGMT_DIR)cnm.o \ + $(MGMT_DIR)cnm_timer.o \ + $(MGMT_DIR)cnm_mem.o \ + $(MGMT_DIR)hem_mbox.o \ + $(MGMT_DIR)mib.o \ + $(MGMT_DIR)privacy.o \ + $(MGMT_DIR)rate.o \ + $(MGMT_DIR)rlm.o \ + $(MGMT_DIR)rlm_domain.o \ + $(MGMT_DIR)rlm_obss.o \ + $(MGMT_DIR)rlm_protection.o \ + $(MGMT_DIR)rsn.o \ + $(MGMT_DIR)saa_fsm.o \ + $(MGMT_DIR)scan.o \ + $(MGMT_DIR)scan_fsm.o \ + $(MGMT_DIR)sec_fsm.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)swcr.o \ + $(MGMT_DIR)roaming_fsm.o \ + $(MGMT_DIR)hs20.o + +# --------------------------------------------------- +# TDLS Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)tdls.o \ + $(MGMT_DIR)tdls_com.o + +# --------------------------------------------------- +# STATS Objects List +# --------------------------------------------------- +MGMT_OBJS += $(MGMT_DIR)stats.o + +# --------------------------------------------------- +# P2P Objects List +# --------------------------------------------------- + +COMMON_OBJS += $(COMMON_DIR)wlan_p2p.o + +NIC_OBJS += $(NIC_DIR)p2p_nic.o + +OS_OBJS += $(OS_DIR)gl_p2p.o \ + $(OS_DIR)gl_p2p_cfg80211.o \ + $(OS_DIR)gl_p2p_init.o \ + $(OS_DIR)gl_p2p_kal.o + +MGMT_OBJS += $(MGMT_DIR)p2p_assoc.o \ + $(MGMT_DIR)p2p_bss.o \ + $(MGMT_DIR)p2p_fsm.o \ + $(MGMT_DIR)p2p_func.o \ + $(MGMT_DIR)p2p_rlm.o \ + $(MGMT_DIR)p2p_rlm_obss.o \ + $(MGMT_DIR)p2p_scan.o \ + $(MGMT_DIR)p2p_ie.o \ + $(MGMT_DIR)p2p_state.o + + +ifeq ($(CONFIG_MTK_WAPI_SUPPORT), y) +MGMT_OBJS += $(MGMT_DIR)wapi.o +endif + +ifeq ($(WLAN_PROC), y) +OS_OBJS += gl_proc.o +endif + +#$(warning $(CONFIG_MACH_MT7623)) + +ifeq ($(CONFIG_MACH_MT7623), y) +HIF_AHB_PDMA = $(HIF_DIR)mt8127/ +endif +HIF_OBJS := $(HIF_DIR)arm.o \ + $(HIF_DIR)ahb.o \ + $(HIF_AHB_PDMA)ahb_pdma.o +ifeq ($(CONFIG_ARCH_MT6755), y) +PLAT_OBJS := $(PLAT_DIR)plat_priv.o +$(MODULE_NAME)-objs += $(PLAT_OBJS) +endif +$(MODULE_NAME)-objs += $(COMMON_OBJS) +$(MODULE_NAME)-objs += $(NIC_OBJS) +$(MODULE_NAME)-objs += $(OS_OBJS) +$(MODULE_NAME)-objs += $(HIF_OBJS) +$(MODULE_NAME)-objs += $(MGMT_OBJS) + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c new file mode 100644 index 0000000000000..e31e0b86d231e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/debug.c @@ -0,0 +1,165 @@ +#include "precomp.h" +#include "gl_kal.h" + +struct COMMAND { + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + UINT_8 ucCmdSeqNum; +}; + +struct SECURITY_FRAME { + UINT_16 u2EthType; + UINT_16 u2Reserved; +}; + +struct MGMT_FRAME { + UINT_16 u2FrameCtl; + UINT_16 u2DurationID; +}; + +struct TC_RES_RELEASE_ENTRY { + UINT_64 u8RelaseTime; + UINT_32 u4RelCID; + UINT_8 ucTc4RelCnt; + UINT_8 ucAvailableTc4; +}; + +struct CMD_TRACE_ENTRY { + UINT_64 u8TxTime; + COMMAND_TYPE eCmdType; + union { + struct COMMAND rCmd; + struct SECURITY_FRAME rSecFrame; + struct MGMT_FRAME rMgmtFrame; + } u; +}; + +#define TC_RELEASE_TRACE_BUF_MAX_NUM 100 +#define TXED_CMD_TRACE_BUF_MAX_NUM 100 + +static struct TC_RES_RELEASE_ENTRY *gprTcReleaseTraceBuffer; +static struct CMD_TRACE_ENTRY *gprCmdTraceEntry; +VOID wlanDebugInit(VOID) +{ + /* debug for command/tc4 resource begin */ + gprTcReleaseTraceBuffer = + kalMemAlloc(TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprTcReleaseTraceBuffer, TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY)); + gprCmdTraceEntry = kalMemAlloc(TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY), PHY_MEM_TYPE); + kalMemZero(gprCmdTraceEntry, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +VOID wlanDebugUninit(VOID) +{ + /* debug for command/tc4 resource begin */ + kalMemFree(gprTcReleaseTraceBuffer, PHY_MEM_TYPE, + TC_RELEASE_TRACE_BUF_MAX_NUM * sizeof(struct TC_RES_RELEASE_ENTRY)); + kalMemFree(gprCmdTraceEntry, PHY_MEM_TYPE, TXED_CMD_TRACE_BUF_MAX_NUM * sizeof(struct CMD_TRACE_ENTRY)); + /* debug for command/tc4 resource end */ +} + +VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd) +{ + static UINT_16 u2CurEntry; + struct CMD_TRACE_ENTRY *prCurCmd = &gprCmdTraceEntry[u2CurEntry]; + + prCurCmd->u8TxTime = sched_clock(); + prCurCmd->eCmdType = prCmd->eCmdType; + if (prCmd->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + P_WLAN_MAC_MGMT_HEADER_T prMgmt = (P_WLAN_MAC_MGMT_HEADER_T)((P_MSDU_INFO_T)prCmd->prPacket)->prPacket; + + prCurCmd->u.rMgmtFrame.u2FrameCtl = prMgmt->u2FrameCtrl; + prCurCmd->u.rMgmtFrame.u2DurationID = prMgmt->u2Duration; + } else if (prCmd->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + PUINT_8 pucPkt = (PUINT_8)((struct sk_buff *)prCmd->prPacket)->data; + + prCurCmd->u.rSecFrame.u2EthType = + (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + } else { + prCurCmd->u.rCmd.ucCID = prCmd->ucCID; + prCurCmd->u.rCmd.ucCmdSeqNum = prCmd->ucCmdSeqNum; + prCurCmd->u.rCmd.fgNeedResp = prCmd->fgNeedResp; + prCurCmd->u.rCmd.fgSetQuery = prCmd->fgSetQuery; + } + u2CurEntry++; + if (u2CurEntry == TC_RELEASE_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable) +{ + static UINT_16 u2CurEntry; + struct TC_RES_RELEASE_ENTRY *prCurBuf = &gprTcReleaseTraceBuffer[u2CurEntry]; + + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &prCurBuf->u4RelCID); + prCurBuf->u8RelaseTime = sched_clock(); + prCurBuf->ucTc4RelCnt = aucTxRlsCnt[TC4_INDEX]; + prCurBuf->ucAvailableTc4 = ucAvailable; + u2CurEntry++; + if (u2CurEntry == TXED_CMD_TRACE_BUF_MAX_NUM) + u2CurEntry = 0; +} + +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen) +{ + UINT_16 i = 0; + struct CMD_TRACE_ENTRY *prCmd = gprCmdTraceEntry; + struct TC_RES_RELEASE_ENTRY *prTcRel = gprTcReleaseTraceBuffer; + + if (pucBuf) { + int bufLen = 0; + + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i*2, prCmd[i*2].u8TxTime, prCmd[i*2].eCmdType, *(PUINT_32)(&prCmd[i*2].u.rCmd.ucCID), + i*2+1, prCmd[i*2+1].u8TxTime, prCmd[i*2+1].eCmdType, + *(PUINT_32)(&prCmd[i*2+1].u.rCmd.ucCID)); + if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/2; i++) { + bufLen = snprintf(pucBuf, maxLen, + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d CID %08x\n", + i*2, prTcRel[i*2].u8RelaseTime, prTcRel[i*2].ucTc4RelCnt, prTcRel[i*2].ucAvailableTc4, + prTcRel[i*2].u4RelCID, + i*2+1, prTcRel[i*2+1].u8RelaseTime, prTcRel[i*2+1].ucTc4RelCnt, + prTcRel[i*2+1].ucAvailableTc4, prTcRel[i*2+1].u4RelCID); + if (bufLen <= 0 || (UINT_32)bufLen >= maxLen) + break; + pucBuf += bufLen; + maxLen -= bufLen; + } + return; + } + for (; i < TXED_CMD_TRACE_BUF_MAX_NUM/4; i++) { + LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x; ", + i*4, prCmd[i*4].u8TxTime, prCmd[i*4].eCmdType, + *(PUINT_32)(&prCmd[i*4].u.rCmd.ucCID), + i*4+1, prCmd[i*4+1].u8TxTime, prCmd[i*4+1].eCmdType, + *(PUINT_32)(&prCmd[i*4+1].u.rCmd.ucCID)); + LOG_FUNC("%d: Time %llu, Type %d, Content %08x; %d: Time %llu, Type %d, Content %08x\n", + i*4+2, prCmd[i*4+2].u8TxTime, prCmd[i*4+2].eCmdType, + *(PUINT_32)(&prCmd[i*4+2].u.rCmd.ucCID), + i*4+3, prCmd[i*4+3].u8TxTime, prCmd[i*4+3].eCmdType, + *(PUINT_32)(&prCmd[i*4+3].u.rCmd.ucCID)); + } + for (i = 0; i < TC_RELEASE_TRACE_BUF_MAX_NUM/4; i++) { + LOG_FUNC( + "%d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x;", + i*4, prTcRel[i*4].u8RelaseTime, prTcRel[i*4].ucTc4RelCnt, + prTcRel[i*4].ucAvailableTc4, prTcRel[i*4].u4RelCID, + i*4+1, prTcRel[i*4+1].u8RelaseTime, prTcRel[i*4+1].ucTc4RelCnt, + prTcRel[i*4+1].ucAvailableTc4, prTcRel[i*4+1].u4RelCID); + LOG_FUNC( + " %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x; %d: Time %llu, Tc4Cnt %d, Free %d, CID %08x\n", + i*4+2, prTcRel[i*4+2].u8RelaseTime, prTcRel[i*4+2].ucTc4RelCnt, + prTcRel[i*4+2].ucAvailableTc4, prTcRel[i*4+2].u4RelCID, + i*4+3, prTcRel[i*4+3].u8RelaseTime, prTcRel[i*4+3].ucTc4RelCnt, + prTcRel[i*4+3].ucAvailableTc4, prTcRel[i*4+3].u4RelCID); + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c new file mode 100644 index 0000000000000..486ba239f16a5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/dump.c @@ -0,0 +1,345 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/dump.c#1 +*/ + +/*! \file "dump.c" + \brief Provide memory dump function for debugging. + + Provide memory dump function for debugging. +*/ + +/* +** Log: dump.c + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 19:58:51 GMT mtk01426 +** Init develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in bytes. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length) +{ + ASSERT(pucStartAddr); + + LOG_FUNC("DUMP8 ADDRESS: %p, Length: %u\n", pucStartAddr, u4Length); + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], pucStartAddr[8], + pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], pucStartAddr[12], pucStartAddr[13], + pucStartAddr[14], pucStartAddr[15]); + u4Length -= 16; + pucStartAddr += 16; + } else { + switch (u4Length) { + case 1: + LOG_FUNC("(%p) %02x\n", pucStartAddr, pucStartAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x %02x\n", pucStartAddr, pucStartAddr[0], pucStartAddr[1]); + break; + case 3: + LOG_FUNC("(%p) %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2]); + break; + case 4: + LOG_FUNC("(%p) %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3]); + break; + case 5: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4]); + break; + case 6: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5]); + break; + case 7: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6]); + break; + case 8: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7]); + break; + case 9: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8]); + break; + case 10: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9]); + break; + case 11: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10]); + break; + case 12: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11]); + break; + case 13: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x\n", + pucStartAddr, + pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12]); + break; + case 14: + LOG_FUNC("(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13]); + break; + case 15: + LOG_FUNC( + "(%p) %02x %02x %02x %02x %02x %02x %02x %02x - %02x %02x %02x %02x %02x %02x %02x\n", + pucStartAddr, pucStartAddr[0], pucStartAddr[1], pucStartAddr[2], pucStartAddr[3], + pucStartAddr[4], pucStartAddr[5], pucStartAddr[6], pucStartAddr[7], + pucStartAddr[8], pucStartAddr[9], pucStartAddr[10], pucStartAddr[11], + pucStartAddr[12], pucStartAddr[13], pucStartAddr[14]); + break; + /* + default: + break; + */ + } + u4Length = 0; + } + } + + LOG_FUNC("\n"); + +} /* end of dumpMemory8() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump a segment of memory in double words. +* +* \param[in] pucStartAddr Pointer to the starting address of the memory to be dumped. +* \param[in] u4Length Length of the memory to be dumped. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length) +{ + PUINT_8 pucAddr; + + ASSERT(pu4StartAddr); + + LOG_FUNC("DUMP32 ADDRESS: %p, Length: %u\n", pu4StartAddr, u4Length); + + if (IS_NOT_ALIGN_4((ULONG) pu4StartAddr)) { + UINT_32 u4ProtrudeLen = sizeof(UINT_32) - ((ULONG) pu4StartAddr % 4); + + u4ProtrudeLen = ((u4Length < u4ProtrudeLen) ? u4Length : u4ProtrudeLen); + LOG_FUNC("pu4StartAddr is not at DW boundary.\n"); + pucAddr = (PUINT_8) &pu4StartAddr[0]; + + switch (u4ProtrudeLen) { + case 1: + LOG_FUNC("(%p) %02x------\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + LOG_FUNC("(%p) %02x%02x----\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + LOG_FUNC("(%p) %02x%02x%02x--\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + default: + break; + } + + u4Length -= u4ProtrudeLen; + pu4StartAddr = (PUINT_32) ((ULONG) pu4StartAddr + u4ProtrudeLen); + } + + while (u4Length > 0) { + if (u4Length >= 16) { + LOG_FUNC("(%p) %08x %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pu4StartAddr[3]); + pu4StartAddr += 4; + u4Length -= 16; + } else { + switch (u4Length) { + case 1: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ------%02x\n", pu4StartAddr, pucAddr[0]); + break; + case 2: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) ----%02x%02x\n", pu4StartAddr, pucAddr[1], pucAddr[0]); + break; + case 3: + pucAddr = (PUINT_8) &pu4StartAddr[0]; + LOG_FUNC("(%p) --%02x%02x%02x\n", pu4StartAddr, pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 4: + LOG_FUNC("(%p) %08x\n", pu4StartAddr, pu4StartAddr[0]); + break; + case 5: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ------%02x\n", pu4StartAddr, pu4StartAddr[0], pucAddr[0]); + break; + case 6: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[1], pucAddr[0]); + break; + case 7: + pucAddr = (PUINT_8) &pu4StartAddr[1]; + LOG_FUNC("(%p) %08x --%02x%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 8: + LOG_FUNC("(%p) %08x %08x\n", pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1]); + break; + case 9: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[0]); + break; + case 10: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x ----%02x%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pucAddr[1], pucAddr[0]); + break; + case 11: + pucAddr = (PUINT_8) &pu4StartAddr[2]; + LOG_FUNC("(%p) %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pucAddr[2], pucAddr[1], pucAddr[0]); + break; + case 12: + LOG_FUNC("(%p) %08x %08x %08x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2]); + break; + case 13: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ------%02x\n", + pu4StartAddr, pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[0]); + break; + case 14: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x ----%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], pucAddr[1], pucAddr[0]); + break; + case 15: + pucAddr = (PUINT_8) &pu4StartAddr[3]; + LOG_FUNC("(%p) %08x %08x %08x --%02x%02x%02x\n", + pu4StartAddr, + pu4StartAddr[0], pu4StartAddr[1], pu4StartAddr[2], + pucAddr[2], pucAddr[1], pucAddr[0]); + break; + /* + default: + break; + */ + } + u4Length = 0; + } + } + +} /* end of dumpMemory32() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c new file mode 100644 index 0000000000000..21bd849827e17 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_bow.c @@ -0,0 +1,3442 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_bow.c#1 +*/ + +/*! \file wlan_bow.c + \brief This file contains the 802.11 PAL commands processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_bow.c + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 01 09 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00110632] [Rose][LCA42][Cross Feature][Bluetooth]The "KE" pops up after the device reboots automatically.(once) + * + * Fix bow link disconnected event dereference. + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 07 06 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Improve BoW connection establishment speed. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 21 2011 terry.wu + * NULL + * Fix BoW KE. + * + * 06 20 2011 terry.wu + * NULL + * Add BoW Rate Limitation. + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 07 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * aware more compile options. + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 23 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add some BoW error handling. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * . + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Only reply probe response to its peer or mached SSID for BoW AP. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW SAA retry and disable disconnect event when AAA fail . + * + * 05 21 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Protect BoW connection establishment. + * + * 05 17 2011 terry.wu + * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting + * Send deauth while disconnecting BoW link. + * + * 05 17 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix wrong StaRec state of BoW . + * + * 05 06 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix BoW Multiple Physical Link connect/disconnect issue. + * + * 05 03 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix prAssocRspSwRfb casting. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 12 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add WMM IE for BOW initiator data. + * + * 04 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 28 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Simplify link disconnected routine, remove link disconnected other routine. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add new feature - multiple physical link support. + * + * 02 22 2011 wh.su + * [WCXRP00000486] [MT6620 Wi-Fi][BOW] Fixed the bow send frame but not encrypted issue + * fixed the BOW packet sending without encrypted issue. + * + * 02 21 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BOW link disconnection bug. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting. + * + * 02 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW channel granted function. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW Activity Report structure and bug fix. + * + * 01 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW to support multiple physical link. + * + * 12 08 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support concurrent networks. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 11 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BoW timer assert issue. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix for event returnning Band. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix wrong BoW event size. + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced + * by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 chinghwa.yu + * NULL + * Fix bowResponderScanDone error when prBssDesc is NULL. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 09 14 2010 cp.wu + * NULL + * indicate correct AIS network information for PAL. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 24 2010 chinghwa.yu + * NULL + * Initialize nicActivateNetwork(prAdapter as soon as bow is starting.. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * 2) command sequence number is now increased atomically + * * 3) private data could be hold and taken use for other purpose +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +static UINT_32 g_u4LinkCount; +static UINT_32 g_u4Beaconing; +static BOW_TABLE_T arBowTable[CFG_BOW_PHYSICAL_LINK_NUM]; + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +const BOW_CMD_T arBowCmdTable[] = { + {BOW_CMD_ID_GET_MAC_STATUS, bowCmdGetMacStatus}, + {BOW_CMD_ID_SETUP_CONNECTION, bowCmdSetupConnection}, + {BOW_CMD_ID_DESTROY_CONNECTION, bowCmdDestroyConnection}, + {BOW_CMD_ID_SET_PTK, bowCmdSetPTK}, + {BOW_CMD_ID_READ_RSSI, bowCmdReadRSSI}, + {BOW_CMD_ID_READ_LINK_QUALITY, bowCmdReadLinkQuality}, + {BOW_CMD_ID_SHORT_RANGE_MODE, bowCmdShortRangeMode}, + {BOW_CMD_ID_GET_CHANNEL_LIST, bowCmdGetChannelList}, +}; + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCID, + IN BOOLEAN fgSetQuery, + IN BOOLEAN fgNeedResp, + IN PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + IN PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + IN UINT_32 u4SetQueryInfoLen, IN PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_BOW_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + prCmdInfo->u4PrivateData = (UINT_32) ucSeqNumber; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dispatch command coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + WLAN_STATUS retval = WLAN_STATUS_FAILURE; + UINT_16 i; + + ASSERT(prAdapter); + + for (i = 0; i < sizeof(arBowCmdTable) / sizeof(BOW_CMD_T); i++) { + if ((arBowCmdTable[i].uCmdID == prCmd->rHeader.ucCommandId) && arBowCmdTable[i].pfCmdHandle) { + retval = arBowCmdTable[i].pfCmdHandle(prAdapter, prCmd); + break; + } + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_MAC_STATUS +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_AMPC_EVENT prEvent; + P_BOW_MAC_STATUS prMacStatus; + UINT_8 idx = 0; + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eBssSCO; + UINT_8 ucNumOfChannel = 0; /* MAX_BOW_NUMBER_OF_CHANNEL; */ + + RF_CHANNEL_INFO_T aucChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; + + ASSERT(prAdapter); + + /* 3 <1> If LinkCount != 0 -> OK (optional) */ + + eBand = BAND_2G4; + eBssSCO = CHNL_EXT_SCN; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return WLAN_STATUS_FAILURE; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_MAC_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_MAC_STATUS); + + /* fill event body */ + prMacStatus = (P_BOW_MAC_STATUS) (prEvent->aucPayload); + kalMemZero(prMacStatus, sizeof(BOW_MAC_STATUS)); + + /* 3 <2> Call CNM to decide if BOW available. */ + if (cnmBowIsPermitted(prAdapter)) + prMacStatus->ucAvailability = TRUE; + else + prMacStatus->ucAvailability = FALSE; + + memcpy(prMacStatus->aucMacAddr, prAdapter->rWifiVar.aucDeviceAddress, PARAM_MAC_ADDR_LEN); + + if (cnmPreferredChannel(prAdapter, &eBand, &ucPrimaryChannel, &eBssSCO)) { +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "bowCmdGetMacStatus, Get preferred channel.\n"); +#endif + + prMacStatus->ucNumOfChannel = 1; + prMacStatus->arChannelList[0].ucChannelBand = eBand; + prMacStatus->arChannelList[0].ucChannelNum = ucPrimaryChannel; + } else { +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, + "bowCmdGetMacStatus, Get channel list. Current number of channel, %d.\n", ucNumOfChannel); +#endif + + rlmDomainGetChnlList(prAdapter, BAND_2G4, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_2G4, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[idx].ucChannelBand = aucChannelList[idx].eBand; + prMacStatus->arChannelList[idx].ucChannelNum = aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = ucNumOfChannel; + } + + rlmDomainGetChnlList(prAdapter, BAND_5G, FALSE, MAX_BOW_NUMBER_OF_CHANNEL_5G, + &ucNumOfChannel, aucChannelList); + + if (ucNumOfChannel > 0) { + for (idx = 0; idx < ucNumOfChannel; idx++) { + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelBand = + aucChannelList[idx].eBand; + prMacStatus->arChannelList[prMacStatus->ucNumOfChannel + idx].ucChannelNum = + aucChannelList[idx].ucChannelNum; + } + + prMacStatus->ucNumOfChannel = prMacStatus->ucNumOfChannel + ucNumOfChannel; + + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, + "ucNumOfChannel,eBand,aucChannelList,%x,%x,%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + ucNumOfChannel, aucChannelList[0].eBand, aucChannelList[0].ucChannelNum, aucChannelList[1].ucChannelNum, + aucChannelList[2].ucChannelNum, aucChannelList[3].ucChannelNum, aucChannelList[4].ucChannelNum, + aucChannelList[5].ucChannelNum, aucChannelList[6].ucChannelNum, aucChannelList[7].ucChannelNum, + aucChannelList[8].ucChannelNum, aucChannelList[9].ucChannelNum, aucChannelList[10].ucChannelNum, + aucChannelList[11].ucChannelNum, aucChannelList[12].ucChannelNum, aucChannelList[13].ucChannelNum, + aucChannelList[14].ucChannelNum, aucChannelList[15].ucChannelNum, aucChannelList[16].ucChannelNum, + aucChannelList[17].ucChannelNum)); + + DBGLOG(BOW, TRACE, + "prMacStatus->ucNumOfChannel, eBand, %x, %x.\n", + prMacStatus->ucNumOfChannel, prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prMacStatus->arChannelList[0].ucChannelNum, prMacStatus->arChannelList[1].ucChannelNum, + prMacStatus->arChannelList[2].ucChannelNum, prMacStatus->arChannelList[3].ucChannelNum, + prMacStatus->arChannelList[4].ucChannelNum, prMacStatus->arChannelList[5].ucChannelNum, + prMacStatus->arChannelList[6].ucChannelNum, prMacStatus->arChannelList[7].ucChannelNum, + prMacStatus->arChannelList[8].ucChannelNum, prMacStatus->arChannelList[9].ucChannelNum, + prMacStatus->arChannelList[10].ucChannelNum, prMacStatus->arChannelList[11].ucChannelNum, + prMacStatus->arChannelList[12].ucChannelNum, prMacStatus->arChannelList[13].ucChannelNum, + prMacStatus->arChannelList[14].ucChannelNum, prMacStatus->arChannelList[15].ucChannelNum, + prMacStatus->arChannelList[16].ucChannelNum, prMacStatus->arChannelList[17].ucChannelNum)); + + DBGLOG(BOW, TRACE, "prMacStatus->ucNumOfChannel, %x.\n", prMacStatus->ucNumOfChannel); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList[0].ucChannelBand, %x.\n", prMacStatus->arChannelList[0].ucChannelBand); + DBGLOG(BOW, TRACE, + "prMacStatus->arChannelList[0].ucChannelNum, %x.\n", prMacStatus->arChannelList[0].ucChannelNum); + DBGLOG(BOW, TRACE, "prMacStatus->ucAvailability, %x.\n", prMacStatus->ucAvailability); + DBGLOG(BOW, TRACE, "prMacStatus->aucMacAddr, %x:%x:%x:%x:%x:%x.\n", + prMacStatus->aucMacAddr[0], + prMacStatus->aucMacAddr[1], + prMacStatus->aucMacAddr[2], + prMacStatus->aucMacAddr[3], prMacStatus->aucMacAddr[4], prMacStatus->aucMacAddr[5])); +#endif + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_MAC_STATUS))); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SETUP_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SETUP_CONNECTION prBowSetupConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + + UINT_8 ucBowTableIdx = 0; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowSetupConnection = (P_BOW_SETUP_CONNECTION) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SETUP_CONNECTION)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_INVALID_LENGTH; + } + /* 3 <1> If ucLinkCount >= 4 -> Fail. */ + if (g_u4LinkCount >= CFG_BOW_PHYSICAL_LINK_NUM) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* 3 <2> Call CNM, check if BOW is available. */ + if (!cnmBowIsPermitted(prAdapter)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* 3 <3> Lookup BOW Table, if Peer MAC address exist and valid -> Fail. */ + if (bowCheckBowTableIfVaild(prAdapter, prBowSetupConnection->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (EQUAL_MAC_ADDR(prBowSetupConnection->aucPeerAddress, prAdapter->rWifiVar.aucDeviceAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_INVALID); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = BOW_SETUP_CMD; + rCmdBtOverWifi.ucChannelNum = prBowSetupConnection->ucChannelNum; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowSetupConnection->aucPeerAddress); + rCmdBtOverWifi.u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + rCmdBtOverWifi.ucTimeoutDiscovery = prBowSetupConnection->ucTimeoutDiscovery; + rCmdBtOverWifi.ucTimeoutInactivity = prBowSetupConnection->ucTimeoutInactivity; + rCmdBtOverWifi.ucRole = prBowSetupConnection->ucRole; + rCmdBtOverWifi.PAL_Capabilities = prBowSetupConnection->ucPAL_Capabilities; + rCmdBtOverWifi.cMaxTxPower = prBowSetupConnection->cMaxTxPower; + + if (prBowSetupConnection->ucChannelNum > 14) + rCmdBtOverWifi.ucChannelBand = BAND_5G; + else + rCmdBtOverWifi.ucChannelBand = BAND_2G4; + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowSetupConnection->aucPeerAddress); + +#if CFG_BOW_PHYSICAL_LINK_NUM > 1 + /*Channel check for supporting multiple physical link */ + if (g_u4LinkCount > 0) { + if (prBowSetupConnection->ucChannelNum != prBowFsmInfo->ucPrimaryChannel) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + } +#endif + + prBowFsmInfo->ucPrimaryChannel = prBowSetupConnection->ucChannelNum; + prBowFsmInfo->eBand = rCmdBtOverWifi.ucChannelBand; + prBowFsmInfo->u2BeaconInterval = prBowSetupConnection->u2BeaconInterval; + prBowFsmInfo->ucRole = prBowSetupConnection->ucRole; + + if (prBowSetupConnection->ucPAL_Capabilities > 0) + prBowFsmInfo->fgSupportQoS = TRUE; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdSetupConnection.\n"); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Channel Number - 0x%x.\n", rCmdBtOverWifi.ucChannelNum); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Peer address - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], + rCmdBtOverWifi.rPeerAddr[2], + rCmdBtOverWifi.rPeerAddr[3], rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Beacon interval - 0x%x.\n", rCmdBtOverWifi.u2BeaconInterval); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout activity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutDiscovery); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Timeout inactivity - 0x%x.\n", rCmdBtOverWifi.ucTimeoutInactivity); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Role - 0x%x.\n", rCmdBtOverWifi.ucRole); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi PAL capability - 0x%x.\n", rCmdBtOverWifi.PAL_Capabilities); + DBGLOG(BOW, EVENT, "rCmdBtOverWifi Max Tx power - 0x%x.\n", rCmdBtOverWifi.cMaxTxPower); +#endif + + /* 3 <4> Get a free BOW entry, mark as Valid, fill in Peer MAC address, LinkCount += 1, state == Starting. */ + if (!bowGetBowTableFreeEntry(prAdapter, &ucBowTableIdx)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + prBowFsmInfo->prTargetBssDesc = NULL; + + kalMemZero(&rBowTable, sizeof(BOW_TABLE_T)); + + COPY_MAC_ADDR(rBowTable.aucPeerAddress, prBowSetupConnection->aucPeerAddress); + /* owTable.eState = BOW_DEVICE_STATE_ACQUIRING_CHANNEL; */ + rBowTable.fgIsValid = TRUE; + rBowTable.ucAcquireID = prBowFsmInfo->ucSeqNumOfChReq; + /* rBowTable.ucRole = prBowSetupConnection->ucRole; */ + /* rBowTable.ucChannelNum = prBowSetupConnection->ucChannelNum; */ + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + kalSetBowRole(prAdapter->prGlueInfo, rCmdBtOverWifi.ucRole, prBowSetupConnection->aucPeerAddress); + + GLUE_INC_REF_CNT(g_u4LinkCount); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + if (g_u4LinkCount == 1) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting, cnmTimerInitTimer.\n"); + DBGLOG(BOW, EVENT, "prBowFsmInfo->u2BeaconInterval, %d.\n", prBowFsmInfo->u2BeaconInterval); +#endif + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rStartingBeaconTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowSendBeacon, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + (PFN_MGMT_TIMEOUT_FUNC) bowChGrantedTimeout, (ULONG) NULL); + + /* Reset Global Variable */ + g_u4Beaconing = 0; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdSetupConnection, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "kalInitBowDevice, bow0\n"); +#endif +#if CFG_BOW_SEPARATE_DATA_PATH + kalInitBowDevice(prAdapter->prGlueInfo, BOWDEVNAME); +#endif + + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + + if (rCmdBtOverWifi.ucRole == BOW_INITIATOR) { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } else { + bowSetBowTableState(prAdapter, prBowSetupConnection->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + bowResponderScan(prAdapter); + } + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_DESTROY_CONNECTION +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_DESTROY_CONNECTION prBowDestroyConnection; + CMD_BT_OVER_WIFI rCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; +#if CFG_BOW_TEST + UINT_8 ucIdx; +#endif + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* 3 <1> If LinkCount == 0 ->Fail (Optional) */ + if (g_u4LinkCount == 0) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_DESTROY_CONNECTION)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + /* 3 <2> Lookup BOW table, check if is not exist (Valid and Peer MAC address) -> Fail */ + prBowDestroyConnection = (P_BOW_DESTROY_CONNECTION) &(prCmd->aucPayload[0]); + + if (!bowCheckBowTableIfVaild(prAdapter, prBowDestroyConnection->aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdDestroyConnection, bowCheckIfVaild, not accepted.\n"); +#endif + return WLAN_STATUS_NOT_ACCEPTED; + } +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowCmdDestroyConnection, destroy Peer address - %x:%x:%x:%x:%x:%x.\n", + prBowDestroyConnection->aucPeerAddress[0], prBowDestroyConnection->aucPeerAddress[1], + prBowDestroyConnection->aucPeerAddress[2], prBowDestroyConnection->aucPeerAddress[3], + prBowDestroyConnection->aucPeerAddress[4], prBowDestroyConnection->aucPeerAddress[5])); +#endif + + /* fill CMD_BT_OVER_WIFI */ + rCmdBtOverWifi.ucAction = 2; + COPY_MAC_ADDR(rCmdBtOverWifi.rPeerAddr, prBowDestroyConnection->aucPeerAddress); + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prBowDestroyConnection->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowCmdDestroyConnection, rCmdBtOverWifi.rPeerAddr - %x:%x:%x:%x:%x:%x.\n", rCmdBtOverWifi.rPeerAddr[0], + rCmdBtOverWifi.rPeerAddr[1], rCmdBtOverWifi.rPeerAddr[2], rCmdBtOverWifi.rPeerAddr[3], + rCmdBtOverWifi.rPeerAddr[4], rCmdBtOverWifi.rPeerAddr[5]); +#endif + +#if CFG_BOW_TEST + for (ucIdx = 0; ucIdx < 11; ucIdx++) { + DBGLOG(BOW, EVENT, + "BoW receiving PAL packet delta time vs packet number -- %d ms vs %x.\n", ucIdx, + g_arBowRevPalPacketTime[ucIdx]); + } +#endif + + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, + sizeof(CMD_BT_OVER_WIFI), + (PUINT_8)&rCmdBtOverWifi, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SET_PTK +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SET_PTK prBowSetPTK; + CMD_802_11_KEY rCmdKey; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SET_PTK)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowSetPTK = (P_BOW_SET_PTK) &(prCmd->aucPayload[0]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowSetPTK->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucPeerAddress[0], + prBowSetPTK->aucPeerAddress[1], + prBowSetPTK->aucPeerAddress[2], + prBowSetPTK->aucPeerAddress[3], + prBowSetPTK->aucPeerAddress[4], prBowSetPTK->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "rCmdKey.ucIsAuthenticator, %x.\n", kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress)); +#endif + + if (!bowCheckBowTableIfVaild(prAdapter, prBowSetPTK->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowSetPTK->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + + return WLAN_STATUS_NOT_ACCEPTED; + } + /* fill CMD_802_11_KEY */ + rCmdKey.ucAddRemove = 1; /* add */ + rCmdKey.ucTxKey = 1; + rCmdKey.ucKeyType = 1; + rCmdKey.ucIsAuthenticator = kalGetBowRole(prAdapter->prGlueInfo, prBowSetPTK->aucPeerAddress); + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prBowSetPTK->aucPeerAddress); + rCmdKey.ucNetType = NETWORK_TYPE_BOW_INDEX; /* BT Over Wi-Fi */ + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + rCmdKey.ucKeyId = 0; + rCmdKey.ucKeyLen = 16; /* AES = 128bit */ + kalMemCopy(rCmdKey.aucKeyMaterial, prBowSetPTK->aucTemporalKey, 16); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowSetPTK->aucTemporalKey, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + prBowSetPTK->aucTemporalKey[0], + prBowSetPTK->aucTemporalKey[1], + prBowSetPTK->aucTemporalKey[2], + prBowSetPTK->aucTemporalKey[3], + prBowSetPTK->aucTemporalKey[4], + prBowSetPTK->aucTemporalKey[5], + prBowSetPTK->aucTemporalKey[6], + prBowSetPTK->aucTemporalKey[7], + prBowSetPTK->aucTemporalKey[8], + prBowSetPTK->aucTemporalKey[9], + prBowSetPTK->aucTemporalKey[10], + prBowSetPTK->aucTemporalKey[11], + prBowSetPTK->aucTemporalKey[12], + prBowSetPTK->aucTemporalKey[13], + prBowSetPTK->aucTemporalKey[14], prBowSetPTK->aucTemporalKey[15])); + + DBGLOG(BOW, EVENT, "rCmdKey.aucKeyMaterial, %x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x:%x.\n", + rCmdKey.aucKeyMaterial[0], + rCmdKey.aucKeyMaterial[1], + rCmdKey.aucKeyMaterial[2], + rCmdKey.aucKeyMaterial[3], + rCmdKey.aucKeyMaterial[4], + rCmdKey.aucKeyMaterial[5], + rCmdKey.aucKeyMaterial[6], + rCmdKey.aucKeyMaterial[7], + rCmdKey.aucKeyMaterial[8], + rCmdKey.aucKeyMaterial[9], + rCmdKey.aucKeyMaterial[10], + rCmdKey.aucKeyMaterial[11], + rCmdKey.aucKeyMaterial[12], + rCmdKey.aucKeyMaterial[13], rCmdKey.aucKeyMaterial[14], rCmdKey.aucKeyMaterial[15])); +#endif + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + wlanbowCmdEventSetCommon, + wlanbowCmdTimeoutHandler, + sizeof(CMD_802_11_KEY), (PUINT_8)&rCmdKey, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_RSSI +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_READ_RSSI prBowReadRSSI; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_READ_RSSI)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadRSSI = (P_BOW_READ_RSSI) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadRssi, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_READ_LINK_QUALITY +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_READ_LINK_QUALITY prBowReadLinkQuality; + + ASSERT(prAdapter); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(P_BOW_READ_LINK_QUALITY)) + return WLAN_STATUS_INVALID_LENGTH; + + prBowReadLinkQuality = (P_BOW_READ_LINK_QUALITY) &(prCmd->aucPayload[0]); + + return wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + wlanbowCmdEventReadLinkQuality, + wlanbowCmdTimeoutHandler, 0, NULL, prCmd->rHeader.ucSeqNumber); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_SHORT_RANGE_MODE +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + P_BOW_SHORT_RANGE_MODE prBowShortRangeMode; + CMD_TX_PWR_T rTxPwrParam; + + ASSERT(prAdapter); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode.\n"); +#endif + + prBowShortRangeMode = (P_BOW_SHORT_RANGE_MODE) &(prCmd->aucPayload[0]); + + /* parameter size check */ + if (prCmd->rHeader.u2PayloadLength != sizeof(BOW_SHORT_RANGE_MODE)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (!bowCheckBowTableIfVaild(prAdapter, prBowShortRangeMode->aucPeerAddress)) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_UNACCEPTED); + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (bowGetBowTableState(prAdapter, prBowShortRangeMode->aucPeerAddress) != BOW_DEVICE_STATE_CONNECTED) { + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_NOT_ACCEPTED; + } +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prBowShortRangeMode->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowShortRangeMode->aucPeerAddress[0], + prBowShortRangeMode->aucPeerAddress[1], + prBowShortRangeMode->aucPeerAddress[2], + prBowShortRangeMode->aucPeerAddress[3], + prBowShortRangeMode->aucPeerAddress[4], prBowShortRangeMode->aucPeerAddress[5])); +#endif + + rTxPwrParam.cTxPwr2G4Cck = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4OFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4OFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr2G4HT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr2G4HT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GOFDM_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_48Mbps = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GOFDM_54Mbps = (prBowShortRangeMode->cTxPower << 1); + + rTxPwrParam.cTxPwr5GHT20_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT20_MCS7 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_BPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_QPSK = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_16QAM = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS5 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS6 = (prBowShortRangeMode->cTxPower << 1); + rTxPwrParam.cTxPwr5GHT40_MCS7 = (prBowShortRangeMode->cTxPower << 1); + + if (nicUpdateTxPower(prAdapter, &rTxPwrParam) == WLAN_STATUS_SUCCESS) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowCmdShortRangeMode, %x.\n", WLAN_STATUS_SUCCESS); +#endif + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_SUCCESS); + return WLAN_STATUS_SUCCESS; + } + wlanbowCmdEventSetStatus(prAdapter, prCmd, BOWCMD_STATUS_FAILURE); + return WLAN_STATUS_FAILURE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is command handler for BOW_CMD_ID_GET_CHANNEL_LIST +* coming from 802.11 PAL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmd Pointer to the buffer that holds the command +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd) +{ + ASSERT(prAdapter); + + /* not supported yet */ + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = prCmd->rHeader.ucSeqNumber; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = ucEventBuf; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is generic command done handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkConnected, sizeof(BOW_LINK_CONNECTED)); + prBowLinkConnected->rChannel.ucChannelNum = prBssInfo->ucPrimaryChannel; + prBowLinkConnected->rChannel.ucChannelBand = prBssInfo->eBand; + COPY_MAC_ADDR(prBowLinkConnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); + DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); + DBGLOG(BOW, EVENT, + "prBowLinkConnected->rChannel.ucChannelNum, 0x%x\n", prBowLinkConnected->rChannel.ucChannelNum); + DBGLOG(BOW, EVENT, + "prBowLinkConnected->rChannel.ucChannelBand, 0x%x\n", prBowLinkConnected->rChannel.ucChannelBand); + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkConnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5]); + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkConnected, prBowLinkConnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkConnected->aucPeerAddress[0], prBowLinkConnected->aucPeerAddress[1], + prBowLinkConnected->aucPeerAddress[2], prBowLinkConnected->aucPeerAddress[3], + prBowLinkConnected->aucPeerAddress[4], prBowLinkConnected->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkConnected, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Indicate Event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_CONNECTED))); + + /*Release channel if granted */ + if (prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + /* bowReleaseCh(prAdapter); */ + /*Requested, not granted yet */ + } else if (prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + } + + /* set to connected status */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTED); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + P_BOW_FSM_INFO_T prBowFsmInfo; + BOW_TABLE_T rBowTable; + UINT_8 ucBowTableIdx; + ENUM_BOW_DEVICE_STATE eFsmState; + BOOLEAN fgSendDeauth = FALSE; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing */ + return; + } + /*Cancel scan */ + else if (eFsmState == BOW_DEVICE_STATE_SCANNING && !(prBowFsmInfo->fgIsChannelRequested)) { + bowResponderCancelScan(prAdapter, FALSE); + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_DISCONNECTING); + return; + } + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + if ((prCmdInfo->u4PrivateData)) + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + else + prEvent->rHeader.ucSeqNumber = 0; + + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prEvent->aucPayload); + kalMemZero(prBowLinkDisconnected, sizeof(BOW_LINK_DISCONNECTED)); + prBowLinkDisconnected->ucReason = 0x0; + COPY_MAC_ADDR(prBowLinkDisconnected->aucPeerAddress, prBowFsmInfo->aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucEventId, 0x%x\n", prEvent->rHeader.ucEventId); + DBGLOG(BOW, EVENT, "prEvent->rHeader.ucSeqNumber, 0x%x\n", prEvent->rHeader.ucSeqNumber); + DBGLOG(BOW, EVENT, "prEvent->rHeader.u2PayloadLength, 0x%x\n", prEvent->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, prBowLinkDisconnected->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowLinkDisconnected->aucPeerAddress[0], prBowLinkDisconnected->aucPeerAddress[1], + prBowLinkDisconnected->aucPeerAddress[2], prBowLinkDisconnected->aucPeerAddress[3], + prBowLinkDisconnected->aucPeerAddress[4], prBowLinkDisconnected->aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, "wlanbowCmdEventLinkDisconnected, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Indicate BoW event to PAL */ +#if 0 + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); +#endif + + /* set to disconnected status */ + prBowFsmInfo->prTargetStaRec = + cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_BOW_INDEX, prBowLinkDisconnected->aucPeerAddress); + if (!(prBowFsmInfo->prTargetStaRec)) { + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + ASSERT(FALSE); + return; + } + + /*Release channel if granted */ + if (prBowFsmInfo->fgIsChannelGranted) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + /*Requested, not granted yet */ + } else if (prBowFsmInfo->fgIsChannelRequested) { + prBowFsmInfo->fgIsChannelRequested = FALSE; + /* bowReleaseCh(prAdapter); */ + } +#if 1 + /*Send Deauth to connected peer */ + if (eFsmState == BOW_DEVICE_STATE_CONNECTED && (prBowFsmInfo->prTargetStaRec->ucStaState == STA_STATE_3)) { + fgSendDeauth = TRUE; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "wlanbowCmdEventLinkDisconnected, bowGetBowTableState, %x.\n", + bowGetBowTableState(prAdapter, prBowLinkDisconnected->aucPeerAddress)); +#endif + authSendDeauthFrame(prAdapter, + prBowFsmInfo->prTargetStaRec, + (P_SW_RFB_T) NULL, + REASON_CODE_DEAUTH_LEAVING_BSS, (PFN_TX_DONE_HANDLER) bowDisconnectLink); + } +#endif + +#if 0 + /* 3 <3>Stop this link; flush Tx; + * send deAuthentication -> abort. SAA, AAA. need to check BOW table state == Connected. + */ + if (prAdapter->prGlueInfo->i4TxPendingFrameNum > 0) + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* flush pending security frames */ + if (prAdapter->prGlueInfo->i4TxPendingSecurityFrameNum > 0) + kalClearSecurityFrames(prAdapter->prGlueInfo); +#endif + + /*Update BoW table */ + bowGetBowTableEntryByPeerAddress(prAdapter, prBowLinkDisconnected->aucPeerAddress, &ucBowTableIdx); + rBowTable.fgIsValid = FALSE; + rBowTable.eState = BOW_DEVICE_STATE_DISCONNECTED; + kalMemZero(rBowTable.aucPeerAddress, sizeof(rBowTable.aucPeerAddress)); + bowSetBowTableContent(prAdapter, ucBowTableIdx, &rBowTable); + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED))); + + /*Decrease link count */ + GLUE_DEC_REF_CNT(g_u4LinkCount); + + /*If no need to send deauth, DO disconnect now */ + /*If need to send deauth, DO disconnect at deauth Tx done */ + if (!fgSendDeauth) + bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command done handler for CMD_ID_CMD_BT_OVER_WIFI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BT_OVER_WIFI prCmdBtOverWifi; + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* restore original command for rPeerAddr */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prCmdBtOverWifi = (P_CMD_BT_OVER_WIFI) (prWifiCmd->aucBuffer); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + prBowCmdStatus->ucStatus = BOWCMD_STATUS_SUCCESS; + + /*Indicate BoW event to PAL */ + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + + /* set to starting status */ + kalSetBowState(prAdapter->prGlueInfo, BOW_DEVICE_STATE_STARTING, prCmdBtOverWifi->rPeerAddr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_LINK_QUALITY +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_LINK_QUALITY prBowLinkQuality; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_QUALITY; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_QUALITY); + + /* fill event body */ + prBowLinkQuality = (P_BOW_LINK_QUALITY) (prEvent->aucPayload); + kalMemZero(prBowLinkQuality, sizeof(BOW_LINK_QUALITY)); + prBowLinkQuality->ucLinkQuality = (UINT_8) prLinkQuality->cLinkQuality; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the command done handler for BOW_CMD_ID_READ_RSSI +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* \param[in] pucEventBuf Pointer to the set buffer OR event buffer +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_AMPC_EVENT prEvent; + P_BOW_RSSI prBowRssi; + + ASSERT(prAdapter); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_RSSI; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_RSSI); + + /* fill event body */ + prBowRssi = (P_BOW_RSSI) (prEvent->aucPayload); + kalMemZero(prBowRssi, sizeof(BOW_RSSI)); + prBowRssi->cRssi = (INT_8) prLinkQuality->cRssi; + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_LINK_QUALITY))); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is the default command timeout handler +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] prCmdInfo Pointer to the buffer that holds the command info +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_AMPC_EVENT prEvent; + P_BOW_COMMAND_STATUS prBowCmdStatus; + + ASSERT(prAdapter); + + /* fill event header */ + prEvent = (P_AMPC_EVENT) kalMemAlloc((sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS)), VIR_MEM_TYPE); + if (!prEvent) { + ASSERT(FALSE); + return; + } + prEvent->rHeader.ucEventId = BOW_EVENT_ID_COMMAND_STATUS; + prEvent->rHeader.ucSeqNumber = (UINT_8) prCmdInfo->u4PrivateData; + prEvent->rHeader.u2PayloadLength = sizeof(BOW_COMMAND_STATUS); + + /* fill event body */ + prBowCmdStatus = (P_BOW_COMMAND_STATUS) (prEvent->aucPayload); + kalMemZero(prBowCmdStatus, sizeof(BOW_COMMAND_STATUS)); + + prBowCmdStatus->ucStatus = BOWCMD_STATUS_TIMEOUT; /* timeout */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prEvent); + + kalMemFree(prEvent, VIR_MEM_TYPE, (sizeof(AMPC_EVENT) + sizeof(BOW_COMMAND_STATUS))); + +} + +VOID bowStopping(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBowBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStoping.\n"); + DBGLOG(BOW, EVENT, "bowStoping, SSID %s.\n", prBowBssInfo->aucSSID); + DBGLOG(BOW, EVENT, "bowStoping, prBowBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucBSSID[0], + prBowBssInfo->aucBSSID[1], + prBowBssInfo->aucBSSID[2], + prBowBssInfo->aucBSSID[3], prBowBssInfo->aucBSSID[4], prBowBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, "bowStoping, prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBowBssInfo->aucOwnMacAddr[0], + prBowBssInfo->aucOwnMacAddr[1], + prBowBssInfo->aucOwnMacAddr[2], + prBowBssInfo->aucOwnMacAddr[3], + prBowBssInfo->aucOwnMacAddr[4], prBowBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, "bowStoping, prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); + DBGLOG(BOW, EVENT, "bowStopping, g_u4LinkCount, %x.\n", g_u4LinkCount); + DBGLOG(BOW, EVENT, "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + kalPrint("BoW Stoping,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); +#endif + + if (g_u4LinkCount == 0) { + /*Stop beaconing */ + GLUE_DEC_REF_CNT(g_u4Beaconing); + + /*Deactive BoW network */ + /* prBowBssInfo->fgIsNetActive = FALSE; */ + /* prBowBssInfo->fgIsBeaconActivated = FALSE; */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + /*temp solution for FW hal_pwr_mgt.c#3037 ASSERT */ + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_BOW_INDEX); + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + + } + +} + +VOID bowStarting(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (g_u4LinkCount == 1) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "BoW Starting.\n"); + DBGLOG(BOW, EVENT, "BoW channel granted.\n"); +#endif + +#if 0 + /*Active BoW Network */ + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBssInfo->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prBssInfo->eCurrentOPMode = OP_MODE_BOW; + + /* 4 <1.2> Setup SSID */ + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + prBssInfo->ucSSIDLen = BOW_SSID_LEN; + bowAssignSsid(prBssInfo->aucSSID, prBssInfo->aucOwnMacAddr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "SSID %s.\n", prBssInfo->aucSSID); + DBGLOG(BOW, EVENT, "prBssInfo->aucBSSID, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucBSSID[0], + prBssInfo->aucBSSID[1], + prBssInfo->aucBSSID[2], + prBssInfo->aucBSSID[3], prBssInfo->aucBSSID[4], prBssInfo->aucBSSID[5])); + DBGLOG(BOW, EVENT, "prBssInfo->aucOwnMacAddr, %x:%x:%x:%x:%x:%x.\n", + prBssInfo->aucOwnMacAddr[0], + prBssInfo->aucOwnMacAddr[1], + prBssInfo->aucOwnMacAddr[2], + prBssInfo->aucOwnMacAddr[3], + prBssInfo->aucOwnMacAddr[4], prBssInfo->aucOwnMacAddr[5])); + DBGLOG(BOW, EVENT, "prAdapter->rWifiVar.aucDeviceAddress, %x:%x:%x:%x:%x:%x.\n", + prAdapter->rWifiVar.aucDeviceAddress[0], + prAdapter->rWifiVar.aucDeviceAddress[1], + prAdapter->rWifiVar.aucDeviceAddress[2], + prAdapter->rWifiVar.aucDeviceAddress[3], + prAdapter->rWifiVar.aucDeviceAddress[4], prAdapter->rWifiVar.aucDeviceAddress[5])); +#endif + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + if (prBowFsmInfo->eBand == BAND_2G4) + prBssInfo->eBand = BAND_2G4; + else + prBssInfo->eBand = BAND_5G; + +#if CFG_BOW_SUPPORT_11N + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + +#else + if (prBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_ERP; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else { + /* Depend on eBand */ + /* prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; */ + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + /* prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; */ + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11A; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + + /* RATE_SET_ERP; */ + /* prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_ERP; */ + /* prBssInfo->u2OperationalRateSet = RATE_SET_ERP; */ + + /* RATE_SET_ERP; */ + prBssInfo->u2BSSBasicRateSet = BASIC_RATE_SET_OFDM; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } + +#endif + prBssInfo->fgErpProtectMode = FALSE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = prBowFsmInfo->u2BeaconInterval; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + if (prBowFsmInfo->fgSupportQoS) { + prAdapter->rWifiVar.fgSupportQoS = TRUE; + prBssInfo->fgIsQBSS = TRUE; + } + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + bssInitForAP(prAdapter, prBssInfo, TRUE); + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_BOW_INDEX); +#endif /* CFG_SUPPORT_AAA */ + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->fgIsBeaconActivated = TRUE; + + /* 3 <3> Set MAC HW */ + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BOW_BSS_INFO_INIT(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], prBowFsmInfo->aucPeerAddress[4], + prBowFsmInfo->aucPeerAddress[5])); +#endif + + /* 4 <3.1> use command packets to inform firmware */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /* 4 <3.2> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /* 4 <3.1> Reset HW TSF Update Mode and Beacon Mode */ + + /* 4 <3.2> Setup BSSID */ + /* TODO: rxmSetRxFilterBSSID0 */ +/* rxmSetRxFilterBSSID0(prBssInfo->ucHwBssidId, prBssInfo->aucBSSID); */ + + /* 4 <3.3> Setup RX Filter to accept Probe Request */ + /* TODO: f get/set RX filter. */ + +#if 0 + { + UINT_32 u4RxFilter; + + if (halMacRxGetRxFilters(&u4RxFilter) == HAL_STATUS_SUCCESS) { + + u4RxFilter &= ~BIT(RXFILTER_DROP_PROBE_REQ); + + halMacRxSetRxFilters(u4RxFilter); + } + } +#endif + } + + /*Update BoW Table */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_STARTING); + +#if CFG_BOW_TEST + kalPrint("BoW Starting,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); + DBGLOG(BOW, EVENT, "bowStarting, g_u4LinkCount, %x.\n", g_u4LinkCount); +#endif + + /*Start beaconing */ + if (g_u4Beaconing < 1) { + GLUE_INC_REF_CNT(g_u4Beaconing); + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if 0 + /*Responder: Start to scan Initiator */ + if (prBowFsmInfo->ucRole == BOW_RESPONDER) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowStarting responder, start scan result searching.\n"); +#endif + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rChGrantedTimer); + bowReleaseCh(prAdapter); + bowResponderScan(prAdapter); + } + /*Initiator: Request channel, wait for responder */ + else { + /* Todo:: Nothing*/ + /* bowRequestCh(prAdapter); */ + } +#endif + +} + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 puOwnMacAddr) +{ + UINT_8 i; + UINT_8 aucSSID[] = BOW_WILDCARD_SSID; + + kalMemCopy(pucSsid, aucSSID, BOW_WILDCARD_SSID_LEN); + + for (i = 0; i < 6; i++) { + pucSsid[(3 * i) + 3] = 0x2D; + if ((*(puOwnMacAddr + i) >> 4) < 0xA) + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x30; + else + *(pucSsid + (3 * i) + 4) = (*(puOwnMacAddr + i) >> 4) + 0x57; + + if ((*(puOwnMacAddr + i) & 0x0F) < 0xA) + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x30; + else + pucSsid[(3 * i) + 5] = (*(puOwnMacAddr + i) & 0x0F) + 0x57; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if 0 /* CFG_BOW_TEST */ + DBGLOG(BOW, EVENT, "bowValidateProbeReq.\n"); +#endif + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (P_IE_SSID_T) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (P_IE_SSID_T) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + /* 4 <2> Check network conditions */ + /*If BoW AP is beaconing */ + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW && g_u4Beaconing > 0) { + + /*Check the probe requset sender is our peer */ + if (bowCheckBowTableIfVaild(prAdapter, prMgtHdr->aucSrcAddr)) + fgReplyProbeResp = TRUE; + /*Check the probe request target SSID is our SSID */ + else if ((prIeSsid) && + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prIeSsid->aucSSID, prIeSsid->ucLength)) + fgReplyProbeResp = TRUE; + else + fgReplyProbeResp = FALSE; + } + + return fgReplyProbeResp; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if ((g_u4Beaconing != 0) && (g_u4LinkCount > 0) && (g_u4LinkCount < CFG_BOW_PHYSICAL_LINK_NUM)) { + /* Send beacon */ + bssSendBeaconProbeResponse(prAdapter, NETWORK_TYPE_BOW_INDEX, NULL, 0); + cnmTimerStartTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer, prBowFsmInfo->u2BeaconInterval); + } +#if CFG_BOW_TEST + else + kalPrint("BoW Send Beacon,[%d,%d]\n", g_u4LinkCount, g_u4Beaconing); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScan(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderScan.\n"); + kalPrint("BOW SCAN [REQ:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq + 1); +#endif + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + /*Fill scan message */ + prScanReqMsg->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_BOW_INDEX; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + prScanReqMsg->ucSSIDLength = BOW_SSID_LEN; + bowAssignSsid(prScanReqMsg->aucSSID, prBowFsmInfo->aucPeerAddress); + prScanReqMsg->ucChannelListNum = 1; + + if (prBowFsmInfo->eBand == BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_2G4; + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + prScanReqMsg->arChnlInfoList[0].eBand = BAND_5G; + } + + prScanReqMsg->arChnlInfoList[0].ucChannelNum = prBowFsmInfo->ucPrimaryChannel; + prScanReqMsg->u2IELen = 0; + + /*Send scan message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + + /*Change state to SCANNING */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_SCANNING); + + /* prBowFsmInfo->fgTryScan = FALSE; */ /* Will enable background sleep for infrastructure */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_DESC_T prBssDesc; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_BOW_DEVICE_STATE eFsmState; + ENUM_SCAN_STATUS eScanStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + ASSERT(prScanDoneMsg->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + eScanStatus = prScanDoneMsg->eScanStatus; + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderScanDone.\n"); + kalPrint("BOW SCAN [DONE:%d]\n", ucSeqNumOfCompMsg); +#endif + + if (eScanStatus == SCAN_STATUS_CANCELLED) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCELLED:%d]\n", ucSeqNumOfCompMsg); +#endif + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTING) { + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + return; + } else if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /* bowDisconnectLink(prAdapter, NULL, TX_RESULT_SUCCESS); */ + return; + } else if (ucSeqNumOfCompMsg != prBowFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(BOW, EVENT, "Sequence no. of BOW Responder scan done is not matched.\n"); + return; + } + prConnSettings->fgIsScanReqIssued = FALSE; + prBssDesc = scanSearchBssDescByBssid(prAdapter, prBowFsmInfo->aucPeerAddress); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "End scan result searching.\n"); +#endif + + /* Initiator is FOUND */ + if (prBssDesc != NULL) { + /* (prBssDesc->aucBSSID != NULL)) */ +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Search Bow Peer address - %x:%x:%x:%x:%x:%x.\n", prBssDesc->aucBSSID[0], + prBssDesc->aucBSSID[1], + prBssDesc->aucBSSID[2], + prBssDesc->aucBSSID[3], prBssDesc->aucBSSID[4], prBssDesc->aucBSSID[5]); + DBGLOG(BOW, EVENT, "Starting to join initiator.\n"); +#endif + /*Set target BssDesc */ + prBowFsmInfo->prTargetBssDesc = prBssDesc; + /*Request channel to do JOIN */ + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL); + bowRequestCh(prAdapter); + } + /*Initiator is NOT FOUND */ + else { + /*Scan again, until PAL timeout */ + bowResponderScan(prAdapter); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#endif + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for cancelling scan request. There is another option to extend channel privilige +* for another purpose. +* +* @param fgIsChannelExtention - Keep the channel previlege, but can cancel scan timer. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention) +{ + + P_MSG_SCN_SCAN_CANCEL prScanCancel = (P_MSG_SCN_SCAN_CANCEL) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo = (P_BOW_FSM_INFO_T) NULL; + + DEBUGFUNC("bowResponderCancelScan()"); + + do { + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (TRUE) { +#if CFG_BOW_TEST + kalPrint("BOW SCAN [CANCEL:%d]\n", prBowFsmInfo->ucSeqNumOfScanReq); +#endif + /* There is a channel privilege on hand. */ + + DBGLOG(P2P, TRACE, "BOW Cancel Scan\n"); + + prScanCancel = + (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancel) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancel->rMsgHdr.eMsgId = MID_BOW_SCN_SCAN_CANCEL; + prScanCancel->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prScanCancel->ucSeqNum = prBowFsmInfo->ucSeqNumOfScanReq; +#if CFG_ENABLE_WIFI_DIRECT + prScanCancel->fgIsChannelExt = fgIsChannelExtention; +#endif + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancel, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); + +} /* bowResponderCancelScan */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + ASSERT(prBssDesc); + ASSERT(prAdapter); + + DBGLOG(BOW, EVENT, "Starting bowResponderJoin.\n"); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> We are going to connect to this BSS. */ + prBssDesc->fgIsConnecting = TRUE; + bowSetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress, BOW_DEVICE_STATE_CONNECTING); + + /* 4 <2> Setup corresponding STA_RECORD_T */ + /*Support First JOIN and retry */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_BOW_AP, NETWORK_TYPE_BOW_INDEX, prBssDesc); + if (!prStaRec) + return; + + prBowFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + prStaRec->fgIsReAssoc = FALSE; + prBowFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ + if (prBowFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(BOW, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prBowFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + ASSERT(0); + } + + /* 4 <4.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy */ + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prBssDesc->aucSSID); + DBGLOG(BOW, EVENT, "bowResponderJoin, SSID %s.\n", prConnSettings->aucSSID); +#endif + } + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_BOW_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prBowFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + prBssInfo->prStaRecOfAP = prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, INFO, "BoW trigger SAA [%pM]\n", prStaRec->aucMacAddr); +#endif + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for BOW FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + P_BSS_INFO_T prBssInfo; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete.\n"); + DBGLOG(BOW, EVENT, "bowfsmRunEventJoinComplete ptr check\n"); + DBGLOG(BOW, EVENT, "prMsgHdr %x\n", prMsgHdr); + DBGLOG(BOW, EVENT, "prAdapter %x\n", prAdapter); + DBGLOG(BOW, EVENT, "prBowFsmInfo %x\n", prBowFsmInfo); + DBGLOG(BOW, EVENT, "prStaRec %x\n", prStaRec); +#endif + + ASSERT(prStaRec); + ASSERT(prBowFsmInfo); + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prBowFsmInfo->ucSeqNumOfReqMsg) { + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - + WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + prStaRec->eStaType = STA_TYPE_BOW_AP; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; +#if CFG_BOW_RATE_LIMITATION + /* 4 <1.2>Update Rate Set */ + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet + (prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) { + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + } + } +#endif + + /* 4 <1.1> Change FW's Media State immediately. */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <1.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ +#if CFG_BOW_SUPPORT_11N + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); +#endif + + /* 4 <1.3> Update BSS_INFO_T */ + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Finish bowUpdateBssInfoForJOIN.\n"); +#endif + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowFsmRunEventJoinComplete, qmActivateStaRec.\n"); +#endif + + /* 4 <1.7> Set the Next State of BOW FSM */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + } + /* 4 <2> JOIN was not successful */ + else { + /*Retry */ + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); +#if 0 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#endif +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Start bowfsmRunEventJoinComplete -- Join failed.\n"); + DBGLOG(BOW, INFO, "BoW trigger SAA REJOIN\n"); +#endif + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN BOOLEAN fgDelayIndication) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /* NOTE(Kevin): Move following line to bowChangeMediaState() macro per CM's request. */ + /* prBowBssInfo->eConnectionState = eConnectionState; */ + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + if (prBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rIndicationOfDisconnectTimer); + + /* 4 <1> Fill EVENT_CONNECTION_STATUS */ + rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prBssInfo->eCurrentOPMode == OP_MODE_BOW) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; + rEventConnStatus.u2AID = prBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = prBssInfo->u2ATIMWindow; + } else { + ASSERT(0); + } + + COPY_SSID(rEventConnStatus.aucSsid, + rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + COPY_MAC_ADDR(rEventConnStatus.aucBssid, prBssInfo->aucBSSID); + + rEventConnStatus.u2BeaconPeriod = prBssInfo->u2BeaconInterval; + rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prBssInfo->ucPrimaryChannel); + + switch (prBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_HR_DSSS_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + } + } else { +#if CFG_PRIVACY_MIGRATION + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); +#endif + + rEventConnStatus.ucReasonOfDisconnect = prBssInfo->ucReasonOfDisconnect; + + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, NETWORK_TYPE_BOW_INDEX, &rEventConnStatus); + prBssInfo->eConnectionStateIndicated = eConnectionState; + } else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(BOW, INFO, "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowRunEventAAATxFail , bssRemoveStaRecFromClientList.\n"); + DBGLOG(BOW, INFO, "BoW AAA TxFail, target state %d\n", prStaRec->ucStaState + 1); +#endif + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + + ASSERT(prStaRec); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowRunEventAAAComplete, cnmStaRecChangeState, STA_STATE_3.\n"); + DBGLOG(BOW, INFO, "BoW AAA complete [%pM]\n", prStaRec->aucMacAddr); +#endif + + /*Update BssInfo to connected */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*Update StaRec to State3 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /*Connected */ + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, FALSE, wlanbowCmdEventLinkConnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle RxDeauth +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if (!IS_STA_IN_BOW(prStaRec)) + return WLAN_STATUS_NOT_ACCEPTED; + + eFsmState = bowGetBowTableState(prAdapter, prStaRec->aucMacAddr); + + if (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) { + /*do nothing */ + return WLAN_STATUS_NOT_ACCEPTED; + } + + if (prStaRec->ucStaState > STA_STATE_1) { + + if (STA_STATE_3 == prStaRec->ucStaState) { + /* P_MSG_AIS_ABORT_T prAisAbortMsg; */ + + /* NOTE(Kevin): Change state immediately to avoid starvation of + * MSG buffer because of too many deauth frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + COPY_MAC_ADDR(prBowFsmInfo->aucPeerAddress, prStaRec->aucMacAddr); + + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, wlanbowCmdEventLinkDisconnected, wlanbowCmdTimeoutHandler, 0, NULL, 0); + + return WLAN_STATUS_SUCCESS; + } + + return WLAN_STATUS_NOT_ACCEPTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle BoW Link disconnect. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + /*Free target StaRec */ + if (prMsduInfo) + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + else + prStaRec = prBowFsmInfo->prTargetStaRec; + + if (prStaRec) + /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + kalPrint("bowDisconnectLink\n"); + /*No one connected */ + if (g_u4LinkCount == 0 && g_u4Beaconing != 0) { + cnmTimerStopTimer(prAdapter, &prBowFsmInfo->rStartingBeaconTimer); + bowStopping(prAdapter); + kalPrint("bowStopping\n"); + /*Restore TxPower from Short range mode */ +#if CFG_SUPPORT_NVRAM && 0 + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + /*Uninit BoW Interface */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prAdapter->prGlueInfo); +#endif + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAssocResp = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAssocTime; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAssocReq, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowValidateAssocReq, prAssocReqFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAssocReqFrame->aucSrcAddr[0], + prAssocReqFrame->aucSrcAddr[1], + prAssocReqFrame->aucSrcAddr[2], + prAssocReqFrame->aucSrcAddr[3], + prAssocReqFrame->aucSrcAddr[4], prAssocReqFrame->aucSrcAddr[5])); +#endif + + /*Assoc Accept */ + while (EQUAL_MAC_ADDR(prAssocReqFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAssocReq, return wlanbowCmdEventLinkConnected.\n"); +#endif + /*Update StaRec */ + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_BOW_INDEX, prAssocReqFrame->aucSrcAddr); + if (!prStaRec) + break; + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->u2DesiredNonHTRateSet &= prBowBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prBowBssInfo->ucPhyTypeSet; + +#if CFG_BOW_RATE_LIMITATION + /*Limit Rate Set to 24M, 48M, 54M */ + prStaRec->u2DesiredNonHTRateSet &= (RATE_SET_BIT_24M | RATE_SET_BIT_48M | RATE_SET_BIT_54M); + /*If peer cannot support the above rate set, fix on the available highest rate */ + if (prStaRec->u2DesiredNonHTRateSet == 0) { + UINT_8 ucHighestRateIndex; + + if (rateGetHighestRateIndexFromRateSet(prBowBssInfo->u2OperationalRateSet, &ucHighestRateIndex)) + prStaRec->u2DesiredNonHTRateSet = BIT(ucHighestRateIndex); + else { + /*If no available rate is found, DECLINE the association */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + } +#endif + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + + /*Undpate BssInfo to FW */ + bowChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + + /*reply successful */ + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAssocResp = TRUE; + break; + } + + /*Reject Assoc */ + if (*pu2StatusCode != STATUS_CODE_SUCCESSFUL) { + /*Reply Assoc with reject every 5s */ + rCurrentTime = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAssocTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAssocTime == 0) { + fgReplyAssocResp = TRUE; + rLastRejectAssocTime = rCurrentTime; + } + } + + return fgReplyAssocResp; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAuth = FALSE; + P_BSS_INFO_T prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + OS_SYSTIME rCurrentTime; + static OS_SYSTIME rLastRejectAuthTime; + + /* TODO(Kevin): Call BoW functions to check .. + 1. Check we are BoW now. + 2. Check we can accept connection from thsi peer + 3. Check Black List here. + */ + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prBowFsmInfo->aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + prBowFsmInfo->aucPeerAddress[0], + prBowFsmInfo->aucPeerAddress[1], + prBowFsmInfo->aucPeerAddress[2], + prBowFsmInfo->aucPeerAddress[3], + prBowFsmInfo->aucPeerAddress[4], prBowFsmInfo->aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowValidateAuth, prAuthFrame->aucSrcAddr, %x:%x:%x:%x:%x:%x.\n", + prAuthFrame->aucSrcAddr[0], + prAuthFrame->aucSrcAddr[1], + prAuthFrame->aucSrcAddr[2], + prAuthFrame->aucSrcAddr[3], prAuthFrame->aucSrcAddr[4], prAuthFrame->aucSrcAddr[5])); +#endif + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX, prAuthFrame->aucSrcAddr); + if (!prStaRec) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecAlloc.\n"); +#endif + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_BOW_INDEX); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + if (!prStaRec) + return fgReplyAuth; + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + prBowBssInfo->prStaRecOfAP = prStaRec; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, cnmStaRecChangeState.\n"); +#endif + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucIndex, %x.\n", prStaRec->ucIndex); +#endif + bssRemoveStaRecFromClientList(prAdapter, prBowBssInfo, prStaRec); + } + + if (EQUAL_MAC_ADDR(prAuthFrame->aucSrcAddr, prBowFsmInfo->aucPeerAddress)) { + + prStaRec->eStaType = STA_TYPE_BOW_CLIENT; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->eStaType, %x.\n", prStaRec->eStaType); + DBGLOG(BOW, EVENT, "bowValidateAuth, prStaRec->ucNetTypeIndex, %x.\n", prStaRec->ucNetTypeIndex); +#endif + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->ucJoinFailureCount = 0; + *pprStaRec = prStaRec; + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + fgReplyAuth = TRUE; + } else { + cnmStaRecFree(prAdapter, prStaRec, FALSE); + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + /*Reply auth with reject every 5s */ + rCurrentTime = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(rCurrentTime, rLastRejectAuthTime, MSEC_TO_SYSTIME(5000)) || + rLastRejectAuthTime == 0) { + fgReplyAuth = TRUE; + rLastRejectAuthTime = rCurrentTime; + } + } + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowValidateAuth, fgReplyAuth, %x.\n", fgReplyAuth); +#endif + return fgReplyAuth; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prBowBssInfo; + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_GRANT_T prMsgChGrant; + UINT_8 ucTokenID; + UINT_32 u4GrantInterval; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prBowBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + prBowFsmInfo->fgIsChannelGranted = TRUE; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Entering bowRunEventChGrant.\n"); +#endif + + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*Release channel */ + if ((!prBowFsmInfo->fgIsChannelRequested) || + (prBowFsmInfo->ucSeqNumOfChReq != ucTokenID) || + (eFsmState == BOW_DEVICE_STATE_DISCONNECTED) || (eFsmState == BOW_DEVICE_STATE_DISCONNECTING)) { +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [GIVE UP:%d]\n", ucTokenID); + DBGLOG(BOW, INFO, "[Requested:%d][ucSeqNumOfChReq:%d][eFsmState:%d]\n", + prBowFsmInfo->fgIsChannelRequested, prBowFsmInfo->ucSeqNumOfChReq, eFsmState); +#endif + bowReleaseCh(prAdapter); + return; + } + + /* 2. channel privilege has been approved */ + prBowFsmInfo->u4ChGrantedInterval = u4GrantInterval; + +#if 0 + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, + prBowFsmInfo->u4ChGrantedInterval - BOW_JOIN_CH_GRANT_THRESHOLD); +#else + cnmTimerStartTimer(prAdapter, + &prBowFsmInfo->rChGrantedTimer, BOW_JOIN_CH_REQUEST_INTERVAL - BOW_JOIN_CH_GRANT_THRESHOLD); +#endif + + /* 3.2 set local variable to indicate join timer is ticking */ + prBowFsmInfo->fgIsInfraChannelFinished = FALSE; + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [GRANTED:%d].\n", ucTokenID); +#endif + + if (eFsmState == BOW_DEVICE_STATE_ACQUIRING_CHANNEL) { + bowStarting(prAdapter); + bowReleaseCh(prAdapter); + if (prBowFsmInfo->ucRole == BOW_RESPONDER) + bowResponderJoin(prAdapter, prBowFsmInfo->prTargetBssDesc); + } else { + /*update bssinfo */ + nicUpdateBss(prAdapter, NETWORK_TYPE_BOW_INDEX); + bowReleaseCh(prAdapter); + } + +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM for channel privilege requesting +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowRequestCh(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_REQ_T prMsgChReq; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted == FALSE) { + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW channel [REQUEST:%d], %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq + 1, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChReq->ucTokenID = ++prBowFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; +#if 0 + prMsgChReq->u4MaxInterval = BOW_JOIN_CH_REQUEST_INTERVAL; +#else + prMsgChReq->u4MaxInterval = 1; +#endif + /* prBowFsmInfo->prTargetBssDesc->ucChannelNum; */ + prMsgChReq->ucPrimaryChannel = prBowFsmInfo->ucPrimaryChannel; + /* prBowFsmInfo->prTargetBssDesc->eSco; */ + prMsgChReq->eRfSco = CHNL_EXT_SCN; + /* prBowFsmInfo->prTargetBssDesc->eBand; */ + prMsgChReq->eRfBand = prBowFsmInfo->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prBowFsmInfo->aucPeerAddress); + + prBowFsmInfo->fgIsChannelRequested = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform BOW that channel privilege is granted +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + + if (prBowFsmInfo->fgIsChannelGranted != FALSE || prBowFsmInfo->fgIsChannelRequested != FALSE) { +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW channel [RELEASE:%d] %d, %d.\n", prBowFsmInfo->ucSeqNumOfChReq, + prBowFsmInfo->ucPrimaryChannel, prBowFsmInfo->eBand); +#endif + + prBowFsmInfo->fgIsChannelRequested = FALSE; + prBowFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + prMsgChAbort->ucTokenID = prBowFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_BOW_FSM_INFO_T prBowFsmInfo; + ENUM_BOW_DEVICE_STATE eFsmState; + + ASSERT(prAdapter); + + prBowFsmInfo = &(prAdapter->rWifiVar.rBowFsmInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "BoW Channel [TIMEOUT]\n"); +#endif +#if 1 + /* bowReleaseCh(prAdapter); */ + eFsmState = bowGetBowTableState(prAdapter, prBowFsmInfo->aucPeerAddress); + + /*If connecting is not completed, request CH again */ + if ((eFsmState == BOW_DEVICE_STATE_CONNECTING) || (eFsmState == BOW_DEVICE_STATE_STARTING)) + bowRequestCh(prAdapter); +#endif +} + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucBowTableIdx = 0; + CMD_INFO_T rCmdInfo; + + ASSERT(prAdapter); + + kalMemZero(&rCmdInfo, sizeof(CMD_INFO_T)); + + while (ucBowTableIdx < CFG_BOW_PHYSICAL_LINK_NUM) { + if (arBowTable[ucBowTableIdx].fgIsValid) { + COPY_MAC_ADDR(prAdapter->rWifiVar.rBowFsmInfo.aucPeerAddress, + arBowTable[ucBowTableIdx].aucPeerAddress); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowNotifyAllLinkDisconnected, arBowTable[%x].aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + ucBowTableIdx, arBowTable[ucBowTableIdx].aucPeerAddress[0], + arBowTable[ucBowTableIdx].aucPeerAddress[1], + arBowTable[ucBowTableIdx].aucPeerAddress[2], + arBowTable[ucBowTableIdx].aucPeerAddress[3], + arBowTable[ucBowTableIdx].aucPeerAddress[4], + arBowTable[ucBowTableIdx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "bowNotifyAllLinkDisconnected, arBowTable[%x].fgIsValid, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); +#endif +#if 1 + wlanoidSendSetQueryBowCmd(prAdapter, + CMD_ID_CMD_BT_OVER_WIFI, + TRUE, + FALSE, + wlanbowCmdEventLinkDisconnected, + wlanbowCmdTimeoutHandler, 0, NULL, 0); +#else + wlanbowCmdEventLinkDisconnected(prAdapter, &rCmdInfo, NULL); +#endif + } + + ucBowTableIdx += 1; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ + +BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); + +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + return FALSE; +} + +BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + if (arBowTable[ucBowTableIdx].fgIsValid) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowGetBowTableContent, arBowTable[idx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); + DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[ucBowTableIdx].eState); +#endif + prBowTable = &(arBowTable[ucBowTableIdx]); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable) +{ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + COPY_MAC_ADDR(arBowTable[ucBowTableIdx].aucPeerAddress, prBowTable->aucPeerAddress); + arBowTable[ucBowTableIdx].eState = prBowTable->eState; + arBowTable[ucBowTableIdx].fgIsValid = prBowTable->fgIsValid; + arBowTable[ucBowTableIdx].ucAcquireID = prBowTable->ucAcquireID; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, prBowTable->eState, prBowTable->aucPeerAddress); + /* kalSetBowRole(prAdapter->prGlueInfo, prBowTable->ucRole, prBowTable->aucPeerAddress); */ + +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "SET State [%d]\n", arBowTable[ucBowTableIdx].eState); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[ucBowTableIdx].fgIsValid, %x, %x.\n", ucBowTableIdx, + arBowTable[ucBowTableIdx].fgIsValid); +#endif + + return TRUE; + +} + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalCheckBowifVaild, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "kalCheckBowifVaild, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + *pucBowTableIdx = idx; + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (!arBowTable[idx].fgIsValid) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, + "bowGetBowTableFreeEntry, arBowTable[idx].fgIsValid, %x, %x.\n", idx, + arBowTable[idx].fgIsValid); +#endif + *pucBowTableIdx = idx; + arBowTable[idx].fgIsValid = TRUE; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return TRUE; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return FALSE; +} + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 idx; + + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + for (idx = 0; idx < CFG_BOW_PHYSICAL_LINK_NUM; idx++) { + if (arBowTable[idx].fgIsValid && EQUAL_MAC_ADDR(arBowTable[idx].aucPeerAddress, aucPeerAddress)) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "bowGetState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + DBGLOG(BOW, EVENT, "bowGetState, arBowTable[idx].aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", idx, + arBowTable[idx].aucPeerAddress[0], + arBowTable[idx].aucPeerAddress[1], + arBowTable[idx].aucPeerAddress[2], + arBowTable[idx].aucPeerAddress[3], + arBowTable[idx].aucPeerAddress[4], arBowTable[idx].aucPeerAddress[5])); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].fgIsValid, %x, %x.\n", idx, arBowTable[idx].fgIsValid); + DBGLOG(BOW, EVENT, + "bowGetState, arBowTable[idx].eState;, %x, %x.\n", idx, arBowTable[idx].eState); + DBGLOG(BOW, INFO, "GET State [%d]\n", arBowTable[idx].eState); +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return arBowTable[idx].eState; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState) +{ + UINT_8 ucBowTableIdx; + + if (bowGetBowTableEntryByPeerAddress(prAdapter, aucPeerAddress, &ucBowTableIdx)) { + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + arBowTable[ucBowTableIdx].eState = eState; +#if CFG_BOW_TEST + DBGLOG(BOW, INFO, "SET State [%d]\n", eState); +#endif + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_BOW_TABLE); + + kalSetBowState(prAdapter->prGlueInfo, eState, aucPeerAddress); + return TRUE; + } + return FALSE; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c new file mode 100644 index 0000000000000..1c59f861047e6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_lib.c @@ -0,0 +1,6240 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_lib.c#2 +*/ +/*! \file wlan_lib.c + \brief Internal driver stack will export the required procedures here for GLUE Layer. + + This file contains all routines which are exported from MediaTek 802.11 Wireless + LAN driver stack to GLUE Layer. +*/ + +/* +** Log: wlan_lib.c +** +** 08 15 2012 eason.tsai +** [ALPS00338170] [Need Patch] [Volunteer Patch] modify build warning +** fix build waring for codechange + * + * 07 13 2012 cp.wu + * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for termination + * after SDIO error has happened + * [driver domain] add force reset by host-to-device interrupt mechanism + * + * 06 11 2012 cp.wu + * [WCXRP00001252] [MT6620 Wi-Fi][Driver] Add debug message while encountering firmware response timeout + * output message while timeout event occurs + * + * 06 11 2012 eason.tsai + * NULL + * change from binay to hex code + * + * 06 08 2012 eason.tsai + * NULL + * Nvram context covert from 6620 to 6628 for old 6620 meta tool + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 04 2012 eason.tsai + * NULL + * modify the cal fail report code. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band + * configuration with corresponding network configuration correct scan result removing policy. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with + * corresponding network configuration add wlanSetPreferBandByNetwork() for glue layer to invoke + * for setting preferred band configuration corresponding to network type. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment + * when returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 11 14 2011 cm.chang + * [WCXRP00001104] [All Wi-Fi][FW] Show init process by HW mail-box register + * Show FW initial ID when timeout to wait for ready bit + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 10 18 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * when powering off, always clear pending interrupts, then wait for RDY to be de-asserted + * + * 10 14 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * shorten the packet length for firmware download if no more than 2048 bytes. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 20 2011 cp.wu + * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized + * 1. always show error message for SDIO bus errors. + * 2. reset bus error flag when re-initialization + * + * 08 26 2011 cm.chang + * [WCXRP00000952] [MT5931 Wi-Fi][FW] Handshake with BWCS before DPD/TX power calibration + * Fix compiling error for WinXP MT5931 driver + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS Sync ready for WinXP. + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 19 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * escape from normal path if any error is occurred. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a + * disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 24 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * if there is no valid address in chip, generate a new one from driver domain instead of firmware domain + * due to sufficient randomness + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 06 20 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * disable whole-chip resetting mechanism due to the need of further ECO to work as expected. + * + * 05 31 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * changed to use non-zero checking for valid bit in NVRAM content + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 18 2011 cp.wu + * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain + * pass PHY_PARAM in NVRAM from driver to firmware. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * correct assertion. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 05 11 2011 cm.chang + * [WCXRP00000717] [MT5931 Wi-Fi][Driver] Handle wrong NVRAM content about AP bandwidth setting + * . + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * change delay from 100ms to 120ms upon DE's suggestion. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 22 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space + * process for RESET_START and RESET_END events skip power-off handshaking when RESET indication is received. + * + * 04 22 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * . + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 04 15 2011 cp.wu + * [WCXRP00000654] [MT6620 Wi-Fi][Driver] Add loop termination criterion for wlanAdapterStop(). + * add loop termination criteria for wlanAdapterStop(). + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing + * frame dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 04 06 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure + * happend inside wlanAdapterStart invoke nicReleaseAdapterMemory() as failure handling in case + * wlanAdapterStart() failed unexpectedly + * + * 03 29 2011 wh.su + * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error + * fixed the kclocwork error. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically + * continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 02 25 2011 cp.wu + * [WCXRP00000496] [MT5931][Driver] Apply host-triggered chip reset before initializing firmware download procedures + * apply host-triggered chip reset mechanism before initializing firmware download procedures. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Change GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 01 2011 george.huang + * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers + * init variable for CTIA. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer when the + * corresponding BSS is disconnected due to beacon timeout remove from scanning result when the BSS + * is disconnected due to beacon timeout. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to + * ease physically continuous memory demands separate kalMemAlloc() into virtually-continuous + * and physically-continuous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * while being unloaded, clear all pending interrupt then set LP-own to firmware + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay + * to avoid blocking to system scheduling change to use msleep() and shorten waiting interval + * to reduce blocking to other task while Wi-Fi driver is being loaded + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 22 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Remove controling auto rate from initial setting. The initial setting is defined by FW code. + * + * 12 15 2010 cp.wu + * NULL + * sync. with ALPS code by enabling interrupt just before leaving wlanAdapterStart() + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * Change Param name for invitation connection. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 03 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) use 8 buffers for MT5931 which is equipped with less memory + * 2) modify MT5931 debug level to TRACE when download is successful + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * for MT5931, adapter initialization is done *after* firmware is downloaded. + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * correct MT5931 firmware download procedure: + * MT5931 will download firmware first then acquire LP-OWN + * + * 11 02 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) update MT5931 firmware encryption tool. (using 64-bytes unit) + * 2) update MT5931 firmware download procedure + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying + * current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function + * for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 25 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add option for enable/disable TX PWR gain adjustment (default: off) + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 15 2010 cp.wu + * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A + * bugfix: always reset pointer to IEbuf to zero when keeping scanning result for the connected AP + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced + * by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with + * AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 13 2010 cp.wu + * NULL + * acquire & release power control in oid handing wrapper. + * + * 09 09 2010 cp.wu + * NULL + * move IE to buffer head when the IE pointer is not pointed at head. + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 09 01 2010 cp.wu + * NULL + * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 13 2010 cp.wu + * NULL + * correction issue: desired phy type not initialized as ABGN mode. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 10 2010 cm.chang + * NULL + * Support EEPROM read/write in RF test mode + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 13 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Reduce unnecessary type casting + * + * 07 13 2010 cp.wu + * + * use multiple queues to keep 1x/MMPDU/CMD's strict order even when there is incoming 1x frames. + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent + * network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * initialize mbox & ais_fsm in wlanAdapterStart() + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * simplify timer usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable interrupt then send power control command packet. + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when stopping adapter, wait til RDY bit has been cleaerd. + * 2) set TASK_OFFLOAD as driver-core OIDs + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * roll-back to rev.60. + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove redundant firmware image unloading + * 2) use compile-time macros to separate logic related to accquiring own + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always set fw-own before driver is unloaded. + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * 2) command sequence number is now increased atomically + * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * 2) add 2 kal API for later integration + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) eliminate unused definitions + * 2) ready bit will be polled for limited iteration + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * kalOidComplete is not necessary in linux + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use pass-in prRegInfo instead of accessing prGlueInfo directly + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding none-glue code portability + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding non-glue code portability + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve non-glue code portability + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load address & start address are now configured from config.h + * due to the different configurations on FPGA and ASIC + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * only send CMD_NIC_POWER_CTRL in wlanAdapterStop() when card is not removed and is not in D3 state + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * +* 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when starting adapter, read local adminsitrated address from registry and send to firmware via CMD_BASIC_CONFIG. + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 03 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add command/event definitions for initial states + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for QM_TEST_MODE + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct function name .. + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * separate wlanProcesQueuePacket() into 2 APIs upon request + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct wlanAdapterStart + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * 2) firmware image length is now retrieved via NdisFileOpen + * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * 4) nicRxWaitResponse() revised + * 5) another set of TQ counter default value is added for fw-download state + * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * 2. follow MSDN defined behavior when associates to another AP + * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * wlanoidSetFrequency is now implemented by RF test command. + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * QueryRssi is no longer w/o hardware access, it is now implemented by command/event handling loop + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. clear prPendingCmdInfo properly + * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. + * + * 01 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * allow MCR read/write OIDs in RF test mode + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * 2. block TX/ordinary OID when RF test mode is engaged + * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * 4. correct some HAL implementation + * + * 01 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-12-10 16:54:36 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-12-09 20:04:59 GMT mtk02752 +** only report as connected when CFG_HIF_EMULATION_TEST is set to 1 +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-12-08 17:39:41 GMT mtk02752 +** wlanoidRftestQueryAutoTest could be executed without touching hardware +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-12-03 16:10:26 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-02 22:05:33 GMT mtk02752 +** kalOidComplete() will decrease i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-01 23:02:36 GMT mtk02752 +** remove unnecessary spinlock +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-01 22:50:38 GMT mtk02752 +** use TC4 for command, maintein i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-27 12:45:34 GMT mtk02752 +** prCmdInfo should be freed when invoking wlanReleasePendingOid() to clear pending oid +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-24 19:55:51 GMT mtk02752 +** wlanSendPacket & wlanRetransmitOfPendingFrames is only used in old data path +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-23 17:59:55 GMT mtk02752 +** clear prPendingOID inside wlanSendCommand() when the OID didn't need to be replied. +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-23 14:45:29 GMT mtk02752 +** add another version of wlanSendCommand() for command-sending only without blocking for response +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-17 22:40:44 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 10:14:56 GMT mtk01084 +** modify place to invoke wlanIst +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-10-30 18:17:07 GMT mtk01084 +** fix compiler warning +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-10-29 19:46:15 GMT mtk01084 +** invoke interrupt process routine +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-10-13 21:58:24 GMT mtk01084 +** modify for new HW architecture +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-09-09 17:26:01 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-05-20 12:21:27 GMT mtk01461 +** Add SeqNum check when process Event Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-05-19 10:38:44 GMT mtk01461 +** Add wlanReleasePendingOid() for mpReset() if there is a pending OID and no available TX resource to send it. +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-04-29 15:41:34 GMT mtk01461 +** Add handle of EVENT of CMD Result in wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-04-22 09:11:23 GMT mtk01461 +** Fix wlanSendCommand() for Driver Domain CR +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-04-21 09:33:56 GMT mtk01461 +** Update wlanSendCommand() for Driver Domain Response and handle Event Packet, +** wlanQuery/SetInformation() for enqueue CMD_INFO_T +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-17 20:00:08 GMT mtk01461 +** Update wlanImageSectionDownload for optimized CMD process +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-14 20:50:51 GMT mtk01426 +** Fixed compile error +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-13 16:38:40 GMT mtk01084 +** add wifi start function +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-13 14:26:44 GMT mtk01084 +** modify a parameter about FW download length +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-10 21:53:42 GMT mtk01461 +** Update wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-08 16:51:04 GMT mtk01084 +** Update for the image download part +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-01 10:32:47 GMT mtk01461 +** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-03-23 21:44:13 GMT mtk01461 +** Refine TC assignment for WmmAssoc flag +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 16:51:57 GMT mtk01084 +** modify the input argument of caller to RECLAIM_POWER_CONTROL_TO_PM() +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:27:13 GMT mtk01461 +** Add reference code of FW Image Download +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:37 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:08 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 16:28:45 GMT mtk01426 +** Init develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "mgmt/ais_fsm.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 6.1.1.2 Interpretation of priority parameter in MAC service primitives */ +/* Static convert the Priority Parameter/TID(User Priority/TS Identifier) to Traffic Class */ +const UINT_8 aucPriorityParam2TC[] = { + TC1_INDEX, + TC0_INDEX, + TC0_INDEX, + TC1_INDEX, + TC2_INDEX, + TC2_INDEX, + TC3_INDEX, + TC3_INDEX +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _CODE_MAPPING_T { + UINT_32 u4RegisterValue; + INT_32 i4TxpowerOffset; +} CODE_MAPPING_T, *P_CODE_MAPPING_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +BOOLEAN fgIsBusAccessFailed = FALSE; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SIGNED_EXTEND(n, _sValue) \ + (((_sValue) & BIT((n)-1)) ? ((_sValue) | BITS(n, 31)) : \ + ((_sValue) & ~BITS(n, 31))) + +/* TODO: Check */ +/* OID set handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerWOHwAccess[] = { + wlanoidSetChannel, + wlanoidSetBeaconInterval, + wlanoidSetAtimWindow, + wlanoidSetFrequency, +}; + +/* TODO: Check */ +/* OID query handlers without the need to access HW register */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerWOHwAccess[] = { + wlanoidQueryBssid, + wlanoidQuerySsid, + wlanoidQueryInfrastructureMode, + wlanoidQueryAuthMode, + wlanoidQueryEncryptionStatus, + wlanoidQueryPmkid, + wlanoidQueryNetworkTypeInUse, + wlanoidQueryBssidList, + wlanoidQueryAcpiDevicePowerState, + wlanoidQuerySupportedRates, + wlanoidQueryDesiredRates, + wlanoidQuery802dot11PowerSaveProfile, + wlanoidQueryBeaconInterval, + wlanoidQueryAtimWindow, + wlanoidQueryFrequency, +}; + +/* OID set handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidSetHandlerAllowedInRFTest[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidRftestSetAutoTest, + wlanoidSetMcrWrite, + wlanoidSetEepromWrite +}; + +/* OID query handlers allowed in RF test mode */ +PFN_OID_HANDLER_FUNC apfnOidQueryHandlerAllowedInRFTest[] = { + wlanoidRftestQueryAutoTest, + wlanoidQueryMcrRead, + wlanoidQueryEepromRead +} + +; + +PFN_OID_HANDLER_FUNC apfnOidWOTimeoutCheck[] = { + wlanoidRftestSetTestMode, + wlanoidRftestSetAbortTestMode, + wlanoidSetAcpiDevicePowerState, +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 /* no use */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is a private routine, which is used to check if HW access is needed +* for the OID query/ set handlers. +* +* \param[IN] pfnOidHandler Pointer to the OID handler. +* \param[IN] fgSetInfo It is a Set information handler. +* +* \retval TRUE This function needs HW access +* \retval FALSE This function does not need HW access +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOHwAccess; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerWOHwAccess = apfnOidSetHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidSetHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } else { + apfnOidHandlerWOHwAccess = apfnOidQueryHandlerWOHwAccess; + u4NumOfElem = sizeof(apfnOidQueryHandlerWOHwAccess) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOHwAccess[i] == pfnOidHandler) + return FALSE; + } + + return TRUE; +} /* wlanIsHandlerNeedHwAccess */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set flag for later handling card +* ejected event. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +* +* \note When surprised removal happens, Glue layer should invoke this +* function to notify WPDD not to do any hw access. +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanCardEjected(IN P_ADAPTER_T prAdapter) +{ + DEBUGFUNC("wlanCardEjected"); + /* INITLOG(("\n")); */ + + ASSERT(prAdapter); + + /* mark that the card is being ejected, NDIS will shut us down soon */ + nicTxRelease(prAdapter); + +} /* wlanCardEjected */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Create adapter object +* +* \param prAdapter This routine is call to allocate the driver software objects. +* If fails, return NULL. +* \retval NULL If it fails, NULL is returned. +* \retval NOT NULL If the adapter was initialized successfully. +*/ +/*----------------------------------------------------------------------------*/ +P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdpater = (P_ADAPTER_T) NULL; + + DEBUGFUNC("wlanAdapterCreate"); + + do { + prAdpater = (P_ADAPTER_T) kalMemAlloc(sizeof(ADAPTER_T), VIR_MEM_TYPE); + + if (!prAdpater) { + DBGLOG(INIT, ERROR, "Allocate ADAPTER memory ==> FAILED\n"); + break; + } + + kalMemZero(prAdpater, sizeof(ADAPTER_T)); + prAdpater->prGlueInfo = prGlueInfo; + + } while (FALSE); + + return prAdpater; +} /* wlanAdapterCreate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroy adapter object +* +* \param prAdapter This routine is call to destroy the driver software objects. +* If fails, return NULL. +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter) +{ + + if (!prAdapter) + return; + + kalMemFree(prAdapter, VIR_MEM_TYPE, sizeof(ADAPTER_T)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize the adapter. The sequence is +* 1. Disable interrupt +* 2. Read adapter configuration from EEPROM and registry, verify chip ID. +* 3. Create NIC Tx/Rx resource. +* 4. Initialize the chip +* 5. Initialize the protocol +* 6. Enable Interrupt +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanAdapterStart(IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 i, u4Value = 0; + UINT_32 u4WHISR = 0; + UINT_8 aucTxCount[8]; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwLoadAddr, u4ImgSecSize; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + enum Adapter_Start_Fail_Reason { + ALLOC_ADAPTER_MEM_FAIL, + DRIVER_OWN_FAIL, + INIT_ADAPTER_FAIL, + RAM_CODE_DOWNLOAD_FAIL, + WAIT_FIRMWARE_READY_FAIL, + FAIL_REASON_MAX + } eFailReason; + ASSERT(prAdapter); + + DEBUGFUNC("wlanAdapterStart"); + + eFailReason = FAIL_REASON_MAX; + /* 4 <0> Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + QUEUE_INITIALIZE(&(prAdapter->rPendingCmdQueue)); + + /* Initialize rWlanInfo */ + kalMemSet(&(prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + /* 4 <0.1> reset fgIsBusAccessFailed */ + fgIsBusAccessFailed = FALSE; + prAdapter->ulSuspendFlag = 0; + + do { + u4Status = nicAllocateAdapterMemory(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicAllocateAdapterMemory Error!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = ALLOC_ADAPTER_MEM_FAIL; + break; + } + + prAdapter->u4OsPacketFilter = PARAM_PACKET_FILTER_SUPPORTED; + + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Acquiring LP-OWN %d\n", fgIsResetting); + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + if (prAdapter->fgIsFwOwn == TRUE) { + DBGLOG(INIT, ERROR, "nicpmSetDriverOwn() failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = DRIVER_OWN_FAIL; + break; + } + /* 4 <1> Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = INIT_ADAPTER_FAIL; + break; + } + + /* init wake lock before interrupt enable and tx thread */ + KAL_WAKE_LOCK_INIT(prAdapter, &prAdapter->rTxThreadWakeLock, "WLAN TX THREAD"); + + /* 4 <2> Initialize System Service (MGMT Memory pool and STA_REC) */ + nicInitSystemService(prAdapter); + + /* 4 <3> Initialize Tx */ + nicTxInitialize(prAdapter); + wlanDefTxPowerCfg(prAdapter); + + /* 4 <4> Initialize Rx */ + nicRxInitialize(prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD + if (pvFwImageMapFile == NULL) { + DBGLOG(INIT, ERROR, "No Firmware found!\n"); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } + + /* 1. disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 2. Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3. FW download here */ + u4FwLoadAddr = prRegInfo->u4LoadAddress; + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + /* 3a. parse file header for decision of divided firmware download or not */ + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; + + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, + u4FwImageFileLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } + + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + DBGLOG(INIT, TRACE, "wlanAdapterStart(): fgValidHead == TRUE\n"); + + for (i = 0; i < prFwHead->u4NumOfEntries; i++) { + +#if CFG_START_ADDRESS_IS_1ST_SECTION_ADDR + if (i == 0) { + prRegInfo->u4StartAddress = prFwHead->arSection[i].u4DestAddr; + DBGLOG(INIT, TRACE, + "wlanAdapterStart(): FW start address 0x%08x\n", + prRegInfo->u4StartAddress); + } +#endif + +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + if (wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset + j) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, + "Firmware scatter download failed %d!\n", (int)i); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } else +#endif +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + u4FwLoadAddr, + u4FwImageFileLength, + (PUINT_8) pvFwImageMapFile) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (i = 0; i < u4FwImageFileLength; i += CMD_PKT_SIZE_FOR_IMAGE) { + if (i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImageFileLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImageFileLength - i; + + if (wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + i) != + WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = RAM_CODE_DOWNLOAD_FAIL; + break; + } +#if !CFG_ENABLE_FW_DOWNLOAD_ACK + /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ + if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Firmware download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + + /* 4. send Wi-Fi Start command */ + DBGLOG(INIT, INFO, " send Wi-Fi Start command\n"); +#if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, TRUE, prRegInfo->u4StartAddress); +#else + wlanConfigWifiFunc(prAdapter, FALSE, 0); +#endif +#endif + + DBGLOG(INIT, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); + /* 4 <5> check Wi-Fi FW asserts ready bit */ + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(INIT, TRACE, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(INIT, ERROR, "Waiting for Ready bit: Timeout, ID=%u\n", + (u4MailBox0 & 0x0000FFFF)); + u4Status = WLAN_STATUS_FAILURE; + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 1. reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + + /* 2. reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 3. query for permanent address by polling */ + wlanQueryPermanentAddress(prAdapter); + +#if (CFG_SUPPORT_NIC_CAPABILITY == 1) + /* 4. query for NIC capability */ + wlanQueryNicCapability(prAdapter); +#endif + /* 4.1 query for compiler flags */ + wlanQueryCompileFlags(prAdapter); + + /* 5. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6. indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) { + eFailReason = WAIT_FIRMWARE_READY_FAIL; + break; + } + + /* OID timeout timer initialize */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rOidTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReleasePendingOid, (ULONG) NULL); + + /* Return Indicated Rfb list timer */ + cnmTimerInitTimer(prAdapter, + &prAdapter->rReturnIndicatedRfbListTimer, + (PFN_MGMT_TIMEOUT_FUNC) wlanReturnIndicatedPacketsTimeOut, (ULONG) NULL); + + /* Power state initialization */ + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + + /* Online scan option */ + if (prRegInfo->fgDisOnlineScan == 0) + prAdapter->fgEnOnlineScan = TRUE; + else + prAdapter->fgEnOnlineScan = FALSE; + + /* Beacon lost detection option */ + if (prRegInfo->fgDisBcnLostDetection != 0) + prAdapter->fgDisBcnLostDetection = TRUE; + + /* Load compile time constant */ + prAdapter->rWlanInfo.u2BeaconPeriod = CFG_INIT_ADHOC_BEACON_INTERVAL; + prAdapter->rWlanInfo.u2AtimWindow = CFG_INIT_ADHOC_ATIM_WINDOW; + +#if 1 /* set PM parameters */ + prAdapter->fgEnArpFilter = prRegInfo->fgEnArpFilter; + prAdapter->u4PsCurrentMeasureEn = prRegInfo->u4PsCurrentMeasureEn; + + prAdapter->u4UapsdAcBmp = prRegInfo->u4UapsdAcBmp; + + prAdapter->u4MaxSpLen = prRegInfo->u4MaxSpLen; + + DBGLOG(INIT, TRACE, "[1] fgEnArpFilter:0x%x, u4UapsdAcBmp:0x%x, u4MaxSpLen:0x%x", + prAdapter->fgEnArpFilter, prAdapter->u4UapsdAcBmp, prAdapter->u4MaxSpLen); + + prAdapter->fgEnCtiaPowerMode = FALSE; + +#if CFG_SUPPORT_DBG_POWERMODE + prAdapter->fgEnDbgPowerMode = FALSE; +#endif + +#endif + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, prRegInfo); + + /* Enable WZC Disassociation */ + prAdapter->rWifiVar.fgSupportWZCDisassociation = TRUE; + + /* Apply Rate Setting */ + if ((ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate) < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prRegInfo->u4FixedRate); + else + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + + if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) { + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + } else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) { + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + } else { + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + } + + /* Disable Hidden SSID Join */ + prAdapter->rWifiVar.fgEnableJoinToHiddenSSID = FALSE; + + /* Enable Short Slot Time */ + prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable = TRUE; + + /* configure available PHY type set */ + nicSetAvailablePhyTypeSet(prAdapter); + +#if 1 /* set PM parameters */ + { +#if CFG_SUPPORT_PWR_MGT + prAdapter->u4PowerMode = prRegInfo->u4PowerMode; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucNetTypeIndex = + NETWORK_TYPE_P2P_INDEX; + prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile = ENUM_PSP_FAST_SWITCH; +#else + prAdapter->u4PowerMode = ENUM_PSP_CONTINUOUS_ACTIVE; +#endif + + nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, /* FIXIT */ + prAdapter->u4PowerMode, FALSE); + } + +#endif + +#if CFG_SUPPORT_NVRAM + /* load manufacture data */ + wlanLoadManufactureData(prAdapter, prRegInfo); +#endif + +#ifdef CONFIG_MTK_TC1_FEATURE /* 1 //keep alive packet time change from default 30secs to 20secs. //TC01// */ + { + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + rCmdSwCtrl.u4Id = 0x90100000; + rCmdSwCtrl.u4Data = 30; + DBGLOG(INIT, TRACE, "wlanAdapterStart Keepaliveapcket 0x%x, %d\n", + rCmdSwCtrl.u4Id, rCmdSwCtrl.u4Data); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8) (&rCmdSwCtrl), NULL, 0); + } +#endif + +#if 0 + /* Update Auto rate parameters in FW */ + nicRlmArUpdateParms(prAdapter, + prRegInfo->u4ArSysParam0, + prRegInfo->u4ArSysParam1, prRegInfo->u4ArSysParam2, prRegInfo->u4ArSysParam3); +#endif + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + /* clock gating workaround */ + prAdapter->fgIsClockGatingEnabled = FALSE; +#endif + + } while (FALSE); + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* restore to hardware default */ + HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter); + HAL_SET_MAILBOX_READ_CLEAR(prAdapter, FALSE); + + /* Enable interrupt */ + nicEnableInterrupt(prAdapter); + + } else { + /* release allocated memory */ + switch (eFailReason) { + case WAIT_FIRMWARE_READY_FAIL: + DBGLOG(INIT, ERROR, "Wait firmware ready fail, FailReason: %d\n", + eFailReason); + g_IsNeedDoChipReset = 1; + kalSendAeeWarning("[Wait firmware ready fail!]", __func__); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + break; + case RAM_CODE_DOWNLOAD_FAIL: + DBGLOG(INIT, ERROR, "Ram code download fail, FailReason: %d\n", + eFailReason); + g_IsNeedDoChipReset = 1; + kalSendAeeWarning("[Ram code download fail!]", __func__); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); + nicRxUninitialize(prAdapter); + nicTxRelease(prAdapter); + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + nicReleaseAdapterMemory(prAdapter); + break; + case INIT_ADAPTER_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case DRIVER_OWN_FAIL: + nicReleaseAdapterMemory(prAdapter); + break; + case ALLOC_ADAPTER_MEM_FAIL: + break; + default: + break; + } + } + + return u4Status; +} /* wlanAdapterStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Uninitialize the adapter +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4Value = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + /* MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + if (prAdapter->rAcpiState == ACPI_STATE_D0 && +#if (CFG_CHIP_RESET_SUPPORT == 1) + kalIsResetting() == FALSE && +#endif + kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + + /* 0. Disable interrupt, this can be done without Driver own */ + nicDisableInterrupt(prAdapter); + + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* 1. Set CMD to FW to tell WIFI to stop (enter power off state) */ + /* the command must be issue to firmware even in wlanRemove() */ + if (prAdapter->fgIsFwOwn == FALSE && wlanSendNicPowerCtrlCmd(prAdapter, 1) == WLAN_STATUS_SUCCESS) { + /* 2. Clear pending interrupt */ + i = 0; + while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 3. Wait til RDY bit has been cleaerd */ + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if ((u4Value & WCIR_WLAN_READY) == 0) + break; + else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE || i >= CFG_RESPONSE_POLLING_TIMEOUT) { + g_IsNeedDoChipReset = 1; + kalSendAeeWarning("[Read WCIR_WLAN_READY fail!]", __func__); + break; + } + i++; + kalMsleep(10); + } + } + + /* 4. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + +#if CFG_FORCE_RESET_UNDER_BUS_ERROR + if (HAL_TEST_FLAG(prAdapter, ADAPTER_FLAG_HW_ERR) == TRUE) { + /* force acquire firmware own */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + + /* delay for 10ms */ + kalMdelay(10); + + /* force firmware reset via software interrupt */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WSICR, WSICR_H2D_SW_INT_SET); + + /* force release firmware own */ + kalDevRegWrite(prAdapter->prGlueInfo, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + } +#endif + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } + + nicRxUninitialize(prAdapter); + + nicTxRelease(prAdapter); + + /* System Service Uninitialization */ + nicUninitSystemService(prAdapter); + + nicReleaseAdapterMemory(prAdapter); + +#if defined(_HIF_SPI) + /* Note: restore the SPI Mode Select from 32 bit to default */ + nicRestoreSpiDefMode(prAdapter); +#endif + + return u4Status; +} /* wlanAdapterStop */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by ISR (interrupt). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \retval TRUE: NIC's interrupt +* \retval FALSE: Not NIC's interrupt +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl) +{ + ASSERT(prAdapter); + + if (fgGlobalIntrCtrl) { + nicDisableInterrupt(prAdapter); + + /* wlanIST(prAdapter); */ + } + + return TRUE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by IST (task_let). +* +* \param prAdapter Pointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanIST(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* wake up CONNSYS */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* handle interrupts */ + nicProcessIST(prAdapter); + + /* re-enable HIF interrupts */ + nicEnableInterrupt(prAdapter); + + /* CONNSYS can decide to sleep */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check command queue to find out if any could be dequeued +* and/or send to HIF to MT6620 +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdQue Pointer of Command Queue (in Glue Layer) +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue) +{ + WLAN_STATUS rStatus; + QUE_T rTempCmdQue, rMergeCmdQue, rStandInCmdQue; + P_QUE_T prTempCmdQue, prMergeCmdQue, prStandInCmdQue; + P_QUE_ENTRY_T prQueueEntry; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + ENUM_FRAME_ACTION_T eFrameAction = FRAME_ACTION_DROP_PKT; + + KAL_SPIN_LOCK_DECLARATION(); + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(prCmdQue); + + /* init */ + prTempCmdQue = &rTempCmdQue; + prMergeCmdQue = &rMergeCmdQue; + prStandInCmdQue = &rStandInCmdQue; + + QUEUE_INITIALIZE(prTempCmdQue); + QUEUE_INITIALIZE(prMergeCmdQue); + QUEUE_INITIALIZE(prStandInCmdQue); + + /* 4 <1> Move whole list of CMD_INFO to the temp queue */ + /* copy all commands to prTempCmdQue and empty prCmdQue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + /* 4 <2> Dequeue from head and check it is able to be sent */ + /* remove the first one */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + /* check how to handle the command: drop, queue, or tx */ + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + /* command packet will be always sent */ + eFrameAction = FRAME_ACTION_TX_PKT; + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* inquire with QM */ + eFrameAction = qmGetFrameAction(prAdapter, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, NULL, FRAME_TYPE_802_1X); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + /* inquire with QM */ + prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); + + eFrameAction = qmGetFrameAction(prAdapter, + prMsduInfo->ucNetworkType, + prMsduInfo->ucStaRecIndex, prMsduInfo, FRAME_TYPE_MMPDU); + break; + + default: + ASSERT(0); + break; + } + + /* 4 <3> handling upon dequeue result */ + if (eFrameAction == FRAME_ACTION_DROP_PKT) { + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) + DBGLOG(TX, WARN, "Drop Security frame seqNo=%d\n", + prCmdInfo->ucCmdSeqNum); + wlanReleaseCommand(prAdapter, prCmdInfo); + } else if (eFrameAction == FRAME_ACTION_QUEUE_PKT) { + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) + DBGLOG(TX, INFO, "Queue Security frame seqNo=%d\n", + prCmdInfo->ucCmdSeqNum); + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + } else if (eFrameAction == FRAME_ACTION_TX_PKT) { + /* 4 <4> Send the command */ + rStatus = wlanSendCommand(prAdapter, prCmdInfo); + + if (rStatus == WLAN_STATUS_RESOURCES) { + /* no more TC4 resource for further transmission */ + QUEUE_INSERT_TAIL(prMergeCmdQue, prQueueEntry); + DBGLOG(TX, EVENT, "No TC4 resource to send cmd, CID=%d, SEQ=%d, CMD type=%d, OID=%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, prCmdInfo->fgIsOid); + break; + } else if (rStatus == WLAN_STATUS_PENDING) { + /* command packet which needs further handling upon response */ + /* i.e. we need to wait for FW's response */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + QUEUE_INSERT_TAIL(&(prAdapter->rPendingCmdQueue), prQueueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + } else { + /* send success or fail */ + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* send success */ + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, + prCmdInfo->pucInfoBuffer); + } + } else { + /* send fail */ + if (prCmdInfo->fgIsOid) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, rStatus); + } + DBGLOG(TX, WARN, "Send CMD, status=%u, CID=%d, SEQ=%d, CMD type=%d, OID=%d\n", + rStatus, prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, + prCmdInfo->eCmdType, prCmdInfo->fgIsOid); + } + + /* free the command memory */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + } else { + + /* impossible, wrong eFrameAction */ + ASSERT(0); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + /* 4 <3> Merge back to original queue */ + /* 4 <3.1> Merge prMergeCmdQue & prTempCmdQue */ + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prTempCmdQue); + + /* 4 <3.2> Move prCmdQue to prStandInQue, due to prCmdQue might differ due to incoming 802.1X frames */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + /* ??? here, prCmdQue shall be empty, why QUEUE_MOVE_ALL ??? */ + QUEUE_MOVE_ALL(prStandInCmdQue, prCmdQue); + + /* 4 <3.3> concatenate prStandInQue to prMergeCmdQue */ + QUEUE_CONCATENATE_QUEUES(prMergeCmdQue, prStandInCmdQue); + + /* 4 <3.4> then move prMergeCmdQue to prCmdQue */ + QUEUE_MOVE_ALL(prCmdQue, prMergeCmdQue); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_QUE); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanProcessCommandQueue() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will take CMD_INFO_T which carry some information of +* incoming OID and notify the NIC_TX to send CMD. +* +* \param prAdapter Pointer of Adapter Data Structure +* \param prCmdInfo Pointer of P_CMD_INFO_T +* +* \retval WLAN_STATUS_SUCCESS : CMD was written to HIF and be freed(CMD Done) immediately. +* \retval WLAN_STATUS_RESOURCE : No resource for current command, need to wait for previous +* frame finishing their transmission. +* \retval WLAN_STATUS_FAILURE : Get failure while access HIF or been rejected. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_TX_CTRL_T prTxCtrl; + UINT_8 ucTC; /* "Traffic Class" SW(Driver) resource classification */ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + BOOLEAN pfgIsSecOrMgmt = FALSE; + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* init */ + prTxCtrl = &prAdapter->rTxCtrl; + + /* DbgPrint("wlanSendCommand()\n"); */ + /* */ + /* */ +#if DBG && 0 + LOG_FUNC("wlanSendCommand()\n"); + LOG_FUNC("CmdType %u NetworkType %u StaRecIndex %u Oid %u CID 0x%x SetQuery %u NeedResp %u CmdSeqNum %u\n", + prCmdInfo->eCmdType, + prCmdInfo->eNetworkType, + prCmdInfo->ucStaRecIndex, + prCmdInfo->fgIsOid, + prCmdInfo->ucCID, prCmdInfo->fgSetQuery, prCmdInfo->fgNeedResp, prCmdInfo->ucCmdSeqNum); +#endif + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + do { + /* <0> card removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + rStatus = WLAN_STATUS_FAILURE; + break; + } + /* <1> Normal case of sending CMD Packet */ + if (!prCmdInfo->fgDriverDomainMCR) { + /* <1.1> Assign Traffic Class(TC) = TC4. */ + ucTC = TC4_INDEX; + + if ((prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) || + (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME)) + pfgIsSecOrMgmt = TRUE; + + /* <1.2> Check if pending packet or resource was exhausted */ + rStatus = nicTxAcquireResource(prAdapter, ucTC, pfgIsSecOrMgmt); + if (rStatus == WLAN_STATUS_RESOURCES) { + DbgPrint("NO Resource:%d\n", ucTC); + break; + } + /* <1.3> Forward CMD_INFO_T to NIC Layer */ + rStatus = nicTxCmd(prAdapter, prCmdInfo, ucTC); + + /* <1.4> Set Pending in response to Query Command/Need Response */ + if (rStatus == WLAN_STATUS_SUCCESS) { + if ((!prCmdInfo->fgSetQuery) || (prCmdInfo->fgNeedResp)) + rStatus = WLAN_STATUS_PENDING; + } + } + /* <2> "Special case" for access Driver Domain MCR */ + else { + + P_CMD_ACCESS_REG prCmdAccessReg; + + prCmdAccessReg = (P_CMD_ACCESS_REG) (prCmdInfo->pucInfoBuffer + CMD_HDR_SIZE); + + if (prCmdInfo->fgSetQuery) { + /* address is in DWORD unit */ + HAL_MCR_WR(prAdapter, (prCmdAccessReg->u4Address & BITS(2, 31)), + prCmdAccessReg->u4Data); + } else { + P_CMD_ACCESS_REG prEventAccessReg; + UINT_32 u4Address; + + u4Address = prCmdAccessReg->u4Address; + prEventAccessReg = (P_CMD_ACCESS_REG) prCmdInfo->pucInfoBuffer; + prEventAccessReg->u4Address = u4Address; + /* address is in DWORD unit */ + HAL_MCR_RD(prAdapter, prEventAccessReg->u4Address & BITS(2, 31), + &prEventAccessReg->u4Data); + } + } + + } while (FALSE); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return rStatus; +} /* end of wlanSendCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function will release thd CMD_INFO upon its attribution + * + * \param prAdapter Pointer of Adapter Data Structure + * \param prCmdInfo Pointer of CMD_INFO_T + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + + switch (prCmdInfo->eCmdType) { + case COMMAND_TYPE_GENERAL_IOCTL: + case COMMAND_TYPE_NETWORK_IOCTL: + if (prCmdInfo->fgIsOid) { + /* for OID command, we need to do complete() to wake up kalIoctl() */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_FAILURE); + } + break; + + case COMMAND_TYPE_SECURITY_FRAME: + /* free packets in kalSecurityFrameSendComplete() */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); + break; + + case COMMAND_TYPE_MANAGEMENT_FRAME: + prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; + + /* invoke callbacks */ + if (prMsduInfo->pfTxDoneHandler != NULL) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + cnmMgtPktFree(prAdapter, prMsduInfo); + break; + + default: + /* impossible, shall not be here */ + ASSERT(0); + break; + } + + /* free command buffer and return the command header to command pool */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + +} /* end of wlanReleaseCommand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending OID and +* compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReleasePendingOid"); + + ASSERT(prAdapter); + + DBGLOG(OID, ERROR, "OID Timeout! Releasing pending OIDs ..\n"); + + do { + /* 1: Handle OID commands in pending queue */ + /* Clear Pending OID in prAdapter->rPendingCmdQueue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* move all pending commands to prTempCmdQue and empty prCmdQue */ + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + /* get first pending command */ + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->fgIsOid) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else { + /* send complete() to wake up kalIoctl() */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + } + + /* free command memory */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + /* nothing to do so re-queue it to prCmdQue */ + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + /* 2: Clear pending OID staying in command queue */ + kalOidCmdClearance(prAdapter->prGlueInfo); + + /* 3: Do complete(), do we need this? because we have completed in kalOidComplete */ + kalOidClearance(prAdapter->prGlueInfo); + + } while (FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will search the CMD Queue to look for the pending CMD/OID for specific +* NETWORK TYPE and compelete it immediately when system request a reset. +* +* \param prAdapter ointer of Adapter Data Structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* only free commands from the network interface, AIS, P2P, or BOW */ + + do { + /* 1: Clear Pending OID in prAdapter->rPendingCmdQueue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + DBGLOG(P2P, TRACE, "Pending CMD for Network Type:%d\n", prCmdInfo->eNetworkType); + + if (prCmdInfo->eNetworkType == eNetworkType) { + if (prCmdInfo->pfCmdTimeoutHandler) { + prCmdInfo->pfCmdTimeoutHandler(prAdapter, prCmdInfo); + } else + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); + + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + } while (FALSE); + +} /* wlanReleasePendingCMDbyNetwork */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("wlanReturnPacket"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* free the packet */ + if (pvPacket) { + kalPacketFree(prAdapter->prGlueInfo, pvPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT, 1); +#if CFG_NATIVE_802_11 + if (GLUE_TEST_FLAG(prAdapter->prGlueInfo, GLUE_FLAG_HALT)) { + /*Todo:: nothing*/ + /*Todo:: nothing*/ + } +#endif + } + + /* free the packet control block */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (!prSwRfb) { + ASSERT(0); + return; + } + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + ASSERT(0); + /* return; // Don't return here or it would lost SwRfb --kc */ + if (!timerPendingTimer(&prAdapter->rReturnIndicatedRfbListTimer)) { + DBGLOG(RX, WARN, + "wlanReturnPacket, Start ReturnIndicatedRfbList Timer (%ds)\n", + RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + cnmTimerStartTimer(prAdapter, &prAdapter->rReturnIndicatedRfbListTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } + } + nicRxReturnRFB(prAdapter, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the indicated packet buffer and reallocate one to the RFB +* +* \param prAdapter Pointer of Adapter Data Structure +* \param pvPacket Pointer of returned packet +* +* \retval WLAN_STATUS_SUCCESS: Success +* \retval WLAN_STATUS_FAILURE: Failed +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = NULL; + + KAL_SPIN_LOCK_DECLARATION(); + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_QUE_T prQueList; + + DEBUGFUNC("wlanReturnIndicatedPacketsTimeOut"); + DBGLOG(RX, WARN, "wlanReturnIndicatedPacketsTimeOut"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prQueList = &prRxCtrl->rIndicatedRfbList; + DBGLOG(RX, WARN, "IndicatedRfbList num = %u\n", (unsigned int)prQueList->u4NumElem); + + while (QUEUE_IS_NOT_EMPTY(&prRxCtrl->rIndicatedRfbList)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rIndicatedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (nicRxSetupRFB(prAdapter, prSwRfb)) { + status = WLAN_STATUS_RESOURCES; + ASSERT(0); + } + nicRxReturnRFB(prAdapter, prSwRfb); + if (status == WLAN_STATUS_RESOURCES) + break; + } + if (status == WLAN_STATUS_RESOURCES) { + DBGLOG(RX, WARN, "Start ReturnIndicatedRfbList Timer (%ds)\n", RX_RETURN_INDICATED_RFB_TIMEOUT_SEC); + /* restart timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rReturnIndicatedRfbListTimer, + SEC_TO_MSEC(RX_RETURN_INDICATED_RFB_TIMEOUT_SEC)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that returns information about +* the capabilities and status of the driver and/or its network adapter. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] pfnOidQryHandler Function pointer for the OID query handler. +* \param[IN] pvInfoBuf Points to a buffer for return the query information. +* \param[IN] u4QueryBufferLen Specifies the number of bytes at pvInfoBuf. +* \param[OUT] pu4QueryInfoLen Points to the number of bytes it written or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanQueryInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidQryHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4QryInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for + * blocking OIDs during current measurement + */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) + return WLAN_STATUS_SUCCESS; +#if 1 + /* most OID handler will just queue a command packet */ + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidQryHandler, FALSE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else + status = pfnOidQryHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4QryInfoLen); +#endif + + return status; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a required function that allows bound protocol drivers, +* or NDIS, to request changes in the state information that the miniport +* maintains for particular object identifiers, such as changes in multicast +* addresses. +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* \param[IN] pfnOidSetHandler Points to the OID set handlers. +* \param[IN] pvInfoBuf Points to a buffer containing the OID-specific data for the set. +* \param[IN] u4InfoBufLen Specifies the number of bytes at prSetBuffer. +* \param[OUT] pu4SetInfoLen Points to the number of bytes it read or is needed. +* +* \retval WLAN_STATUS_xxx Different WLAN_STATUS code returned by different handlers. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfnOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_FAILURE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* ignore any OID request after connected, under PS current measurement mode */ + /* note: return WLAN_STATUS_FAILURE or WLAN_STATUS_SUCCESS for blocking + * OIDs during current measurement + */ + if (prAdapter->u4PsCurrentMeasureEn && + (prAdapter->prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED)) + return WLAN_STATUS_SUCCESS; +#if 1 + /* most OID handler will just queue a command packet + * for power state transition OIDs, handler will acquire power control by itself + */ + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); +#else + if (wlanIsHandlerNeedHwAccess(pfnOidSetHandler, TRUE)) { + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + } else { + status = pfnOidSetHandler(prAdapter, pvInfoBuf, u4InfoBufLen, pu4SetInfoLen); + } +#endif + + return status; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a used to query driver's config wapi mode or not +* +* \param[IN] prAdapter Pointer to the Glue info structure. +* +* \retval TRUE for use wapi mode +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rWifiVar.rConnSettings.fgWapiMode; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to Promiscuous Mode. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnablePromiscuousMode Enable/ disable RX Promiscuous Mode. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode) +{ + ASSERT(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to set RX filter to allow to receive +* broadcast address packets. +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to send out CMD_NIC_POWER_CTRL command packet +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] ucPowerMode refer to CMD/EVENT document +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + /* 1. Prepare CMD */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL))); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + /* 2.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* 2.2 Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_NIC_POWER_CTRL)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_NIC_POWER_CTRL; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_NIC_POWER_CTRL); + + /* 2.3 Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + kalMemZero(prWifiCmd->aucBuffer, sizeof(CMD_NIC_POWER_CTRL)); + ((P_CMD_NIC_POWER_CTRL) (prWifiCmd->aucBuffer))->ucPowerMode = ucPowerMode; + + /* 3. Issue CMD for entering specific power mode */ + ucTC = TC4_INDEX; + + while (1) { + /* 3.0 Removal check */ + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + status = WLAN_STATUS_FAILURE; + break; + } + /* 3.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + + /* wait and poll tx resource */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + status = WLAN_STATUS_FAILURE; + break; + } + continue; + } + /* 3.2 Send CMD Info Packet */ + if (nicTxCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Fail to transmit CMD_NIC_POWER_CTRL command\n"); + status = WLAN_STATUS_FAILURE; + } + + break; + }; + + /* 4. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* 5. Add flag */ + if (ucPowerMode == 1) + prAdapter->fgIsEnterD3ReqIssued = TRUE; + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to check if it is RF test mode and +* the OID is allowed to be called or not +* +* \param[IN] prAdapter Pointer to the Adapter structure. +* \param[IN] fgEnableBroadcast Enable/ disable broadcast packet to be received. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerAllowedInRFTest; + UINT_32 i; + UINT_32 u4NumOfElem; + + if (fgSetInfo) { + apfnOidHandlerAllowedInRFTest = apfnOidSetHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidSetHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } else { + apfnOidHandlerAllowedInRFTest = apfnOidQueryHandlerAllowedInRFTest; + u4NumOfElem = sizeof(apfnOidQueryHandlerAllowedInRFTest) / sizeof(PFN_OID_HANDLER_FUNC); + } + + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerAllowedInRFTest[i] == pfnOidHandler) + return TRUE; + } + + return FALSE; +} + +#if CFG_ENABLE_FW_DOWNLOAD +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image in an aggregated way +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ +#if defined(MT6620) || defined(MT6628) + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4PktCnt, u4Offset, u4Length; + UINT_32 u4TotalLength; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + + pucOutputBuf = prAdapter->rTxCtrl.pucTxCoalescingBufPtr; + + DEBUGFUNC("wlanImageSectionDownloadAggregated"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and Pre-fill Headers */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + + CMD_PKT_SIZE_FOR_IMAGE); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + CMD_PKT_SIZE_FOR_IMAGE; + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->ucEtherTypeOffset = 0; + prInitHifTxHeader->ucCSflags = 0; + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + + /* 4. Setup CMD_DOWNLOAD_BUF */ + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4DataMode = 0 +#if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE +#endif + ; + + /* 5.0 reset loop control variable */ + u4TotalLength = 0; + u4Offset = u4PktCnt = 0; + + /* 5.1 main loop for maximize transmission count per access */ + while (u4Offset < u4ImgSecSize) { + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_SUCCESS) { + /* 5.1.1 calculate u4Length */ + if (u4Offset + CMD_PKT_SIZE_FOR_IMAGE < u4ImgSecSize) + u4Length = CMD_PKT_SIZE_FOR_IMAGE; + else + u4Length = u4ImgSecSize - u4Offset; + + /* 5.1.1 increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5.1.2 update HIF TX hardware header */ + prInitHifTxHeader->u2TxByteCount = + ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4Length); + + /* 5.1.3 fill command header */ + prInitCmdDownloadBuf->u4Address = u4DestAddr + u4Offset; + prInitCmdDownloadBuf->u4Length = u4Length; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf + u4Offset, u4Length); + + /* 5.1.4.1 copy header to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength, + (PVOID) prCmdInfo->pucInfoBuffer, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF)); + + /* 5.1.4.2 copy payload to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength + sizeof(INIT_HIF_TX_HEADER_T) + + sizeof(INIT_CMD_DOWNLOAD_BUF), pucImgSecBuf + u4Offset, u4Length); + + /* 5.1.4.3 update length and other variables */ + u4TotalLength += + ALIGN_4(sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4Length); + u4Offset += u4Length; + u4PktCnt++; + + if (u4Offset < u4ImgSecSize) + continue; + } else if (u4PktCnt == 0) { + /* no resource, so get some back */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + } + + if (u4PktCnt != 0) { + /* start transmission */ + HAL_WRITE_TX_PORT(prAdapter, + 0, + u4TotalLength, (PUINT_8) pucOutputBuf, prAdapter->u4CoalescingBufCachedSize); + + /* reset varaibles */ + u4PktCnt = 0; + u4TotalLength = 0; + } + } + + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; + +#else +#error "Only MT6620/MT6628/MT6582 supports firmware download in an aggregated way" + + return WLAN_STATUS_FAILURE; + +#endif +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to download FW image. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_DOWNLOAD_BUF prInitCmdDownloadBuf; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pucImgSecBuf); + ASSERT(u4ImgSecSize <= CMD_PKT_SIZE_FOR_IMAGE); + + DEBUGFUNC("wlanImageSectionDownload"); + + if (u4ImgSecSize == 0) + return WLAN_STATUS_SUCCESS; + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, + sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + u4ImgSecSize); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_DOWNLOAD_BUF) + (UINT_16) u4ImgSecSize; + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_DOWNLOAD_BUF; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Setup CMD_DOWNLOAD_BUF */ + prInitCmdDownloadBuf = (P_INIT_CMD_DOWNLOAD_BUF) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdDownloadBuf->u4Address = u4DestAddr; + prInitCmdDownloadBuf->u4Length = u4ImgSecSize; + prInitCmdDownloadBuf->u4CRC32 = wlanCRC32(pucImgSecBuf, u4ImgSecSize); + + prInitCmdDownloadBuf->u4DataMode = 0 +#if CFG_ENABLE_FW_DOWNLOAD_ACK + | DOWNLOAD_BUF_ACK_OPTION /* ACK needed */ +#endif +#if CFG_ENABLE_FW_ENCRYPTION + | DOWNLOAD_BUF_ENCRYPTION_MODE +#endif + ; + + kalMemCopy(prInitCmdDownloadBuf->aucBuffer, pucImgSecBuf, u4ImgSecSize); + + /* 6. Send FW_Download command */ + while (1) { + /* 6.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 6.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + + break; + }; + +#if CFG_ENABLE_FW_DOWNLOAD_ACK + /* 7. Wait for INIT_EVENT_ID_CMD_RESULT */ + u4Status = wlanImageSectionDownloadStatus(prAdapter, ucCmdSeqNum); +#endif + + /* 8. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm previously firmware download is done without error +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR)]; + UINT_32 u4RxPktLength; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_PENDING_ERROR prEventPendingError; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_8 ucTC, ucCmdSeqNum; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanImageQueryStatus"); + + /* 1. Allocate CMD Info Packet and it Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo, sizeof(INIT_HIF_TX_HEADER_T)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T); + + /* 2. Use TC0's resource to download image. (only TC0 is allowed) */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_QUERY_PENDING_ERROR; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + /* 5. Send command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit image download command\n"); + } + + break; + }; + + /* 6. Wait for INIT_EVENT_ID_PENDING_ERROR */ + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_PENDING_ERROR), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_PENDING_ERROR) { + u4Status = WLAN_STATUS_FAILURE; + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + u4Status = WLAN_STATUS_FAILURE; + } else { + prEventPendingError = + (P_INIT_EVENT_PENDING_ERROR) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventPendingError->ucStatus != 0) { /* 0 for download success */ + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + /* 7. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to confirm the status of +* previously downloaded firmware scatter +* +* @param prAdapter Pointer to the Adapter structure. +* ucCmdSeqNum Sequence number of previous firmware scatter +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum) +{ + UINT_8 aucBuffer[sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT)]; + P_INIT_HIF_RX_HEADER_T prInitHifRxHeader; + P_INIT_EVENT_CMD_RESULT prEventCmdResult; + UINT_32 u4RxPktLength; + WLAN_STATUS u4Status; + + ASSERT(prAdapter); + + do { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + DBGLOG(INIT, ERROR, "kalIsCardRemoved or fgIsBusAccessFailed\n"); + u4Status = WLAN_STATUS_FAILURE; + } else if (nicRxWaitResponse(prAdapter, + 0, + aucBuffer, + sizeof(INIT_HIF_RX_HEADER_T) + sizeof(INIT_EVENT_CMD_RESULT),/* 4B + 4B */ + &u4RxPktLength) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "nicRxWaitResponse fail\n"); + u4Status = WLAN_STATUS_FAILURE; + } else { + prInitHifRxHeader = (P_INIT_HIF_RX_HEADER_T) aucBuffer; + + /* EID / SeqNum check */ + if (prInitHifRxHeader->rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT) { + DBGLOG(INIT, ERROR, "rInitWifiEvent.ucEID != INIT_EVENT_ID_CMD_RESULT\n"); + u4Status = WLAN_STATUS_FAILURE; + g_IsNeedDoChipReset = 1; + kalSendAeeWarning("[Check EID error!]", __func__); + } else if (prInitHifRxHeader->rInitWifiEvent.ucSeqNum != ucCmdSeqNum) { + DBGLOG(INIT, ERROR, "rInitWifiEvent.ucSeqNum != ucCmdSeqNum\n"); + u4Status = WLAN_STATUS_FAILURE; + g_IsNeedDoChipReset = 1; + kalSendAeeWarning("[Check SeqNum error!]", __func__); + } else { + prEventCmdResult = + (P_INIT_EVENT_CMD_RESULT) (prInitHifRxHeader->rInitWifiEvent.aucBuffer); + if (prEventCmdResult->ucStatus != 0) { /* 0 for download success */ + /* + 0: success + 1: rejected by invalid param + 2: rejected by incorrect CRC + 3: rejected by decryption failure + 4: unknown CMD + */ + DBGLOG(INIT, ERROR, "Read Response status error = %d\n", + prEventCmdResult->ucStatus); + u4Status = WLAN_STATUS_FAILURE; + } else { + u4Status = WLAN_STATUS_SUCCESS; + } + } + } + } while (FALSE); + + return u4Status; +} + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to start FW normal operation. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress) +{ + P_CMD_INFO_T prCmdInfo; + P_INIT_HIF_TX_HEADER_T prInitHifTxHeader; + P_INIT_CMD_WIFI_START prInitCmdWifiStart; + UINT_8 ucTC, ucCmdSeqNum; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanConfigWifiFunc"); + + /* 1. Allocate CMD Info Packet and its Buffer. */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + + kalMemZero(prCmdInfo->pucInfoBuffer, sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START)); + prCmdInfo->u2InfoBufLen = sizeof(INIT_HIF_TX_HEADER_T) + sizeof(INIT_CMD_WIFI_START); + + /* 2. Always use TC0 */ + ucTC = TC0_INDEX; + + /* 3. increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* 4. Setup common CMD Info Packet */ + prInitHifTxHeader = (P_INIT_HIF_TX_HEADER_T) (prCmdInfo->pucInfoBuffer); + prInitHifTxHeader->rInitWifiCmd.ucCID = INIT_CMD_ID_WIFI_START; + prInitHifTxHeader->rInitWifiCmd.ucSeqNum = ucCmdSeqNum; + + prInitCmdWifiStart = (P_INIT_CMD_WIFI_START) (prInitHifTxHeader->rInitWifiCmd.aucBuffer); + prInitCmdWifiStart->u4Override = (fgEnable == TRUE ? 1 : 0); + prInitCmdWifiStart->u4Address = u4StartAddress; + + /* 5. Seend WIFI start command */ + while (1) { + /* 5.1 Acquire TX Resource */ + if (nicTxAcquireResource(prAdapter, ucTC, FALSE) == WLAN_STATUS_RESOURCES) { + + /* wait and poll tx resource */ + if (nicTxPollingResource(prAdapter, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to get TX resource return within timeout\n"); + break; + } + + continue; + } + /* 5.2 Send CMD Info Packet */ + if (nicTxInitCmd(prAdapter, prCmdInfo, ucTC) != WLAN_STATUS_SUCCESS) { + u4Status = WLAN_STATUS_FAILURE; + DBGLOG(INIT, ERROR, "Fail to transmit WIFI start command\n"); + } + + break; + }; + + /* 6. Free CMD Info Packet. */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate CRC32 checksum +* +* @param buf Pointer to the data. +* @param len data length +* +* @return crc32 value +*/ +/*----------------------------------------------------------------------------*/ +static const UINT_32 crc32_ccitt_table[256] = { + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d + }; + +UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len) +{ + UINT_32 i, crc32 = 0xFFFFFFFF; + + for (i = 0; i < len; i++) + crc32 = crc32_ccitt_table[(crc32 ^ buf[i]) & 0xff] ^ (crc32 >> 8); + + return ~crc32; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to process queued RX packets +* +* @param prAdapter Pointer to the Adapter structure. +* prSwRfbListHead Pointer to head of RX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + P_SW_RFB_T prSwRfb, prNextSwRfb; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + ASSERT(prSwRfbListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prSwRfb = prSwRfbListHead; + + do { + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + switch (prSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: + /* to host */ + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_FORWARD: + /* need ot forward */ + nicRxProcessForwardPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_HOST_WITH_FORWARD: + /* to host and forward */ + nicRxProcessGOBroadcastPkt(prAdapter, prSwRfb); + break; + + case RX_PKT_DESTINATION_NULL: + /* free it */ + nicRxReturnRFB(prAdapter, prSwRfb); + break; + + default: + break; + } + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4DequeuedCnt++; +#endif + + /* check next queued packet */ + prSwRfb = prNextSwRfb; + } while (prSwRfb); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to purge queued TX packets +* by indicating failure to OS and returned to free list +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfoListHead Pointer to head of TX packets link list +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the OID handler needs timeout +* +* @param prAdapter Pointer to the Adapter structure. +* pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler) +{ + PFN_OID_HANDLER_FUNC *apfnOidHandlerWOTimeoutCheck; + UINT_32 i; + UINT_32 u4NumOfElem; + + apfnOidHandlerWOTimeoutCheck = apfnOidWOTimeoutCheck; + u4NumOfElem = sizeof(apfnOidWOTimeoutCheck) / sizeof(PFN_OID_HANDLER_FUNC); + + /* skip some OID timeout checks ? */ + for (i = 0; i < u4NumOfElem; i++) { + if (apfnOidHandlerWOTimeoutCheck[i] == pfnOidHandler) + return FALSE; + } + + /* set timer if need timeout check */ + /* cnmTimerStartTimer(prAdapter, */ + /* &(prAdapter->rOidTimeoutTimer), */ + /* 1000); */ + cnmTimerStartTimer(prAdapter, &(prAdapter->rOidTimeoutTimer), 2000); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to clear any pending OID timeout check +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rOidTimeoutTimer)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update network address in firmware domain +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_FAILURE The request could not be processed +* WLAN_STATUS_PENDING The request has been queued for later processing +* WLAN_STATUS_SUCCESS The request has been processed +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter) +{ + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + PARAM_MAC_ADDRESS rMacAddr = {0}; + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_BASIC_CONFIG prCmdBasicConfig; + UINT_32 u4SysTime; + + DEBUGFUNC("wlanUpdateNetworkAddress"); + + ASSERT(prAdapter); + + if (kalRetrieveNetworkAddress(prAdapter->prGlueInfo, &rMacAddr) == FALSE || IS_BMCAST_MAC_ADDR(rMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, rMacAddr)) { + /* eFUSE has a valid address, don't do anything */ + if (prAdapter->fgIsEmbbededMacAddrValid == TRUE) { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using embedded MAC address"); +#endif + return WLAN_STATUS_SUCCESS; + } +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, TRACE, "Using dynamically generated MAC address"); +#endif + /* dynamic generate */ + u4SysTime = kalGetTimeTick(); + + rMacAddr[0] = 0x00; + rMacAddr[1] = 0x08; + rMacAddr[2] = 0x22; + + kalMemCopy(&rMacAddr[3], &u4SysTime, 3); + } else { +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "Using host-supplied MAC address"); +#endif + } + + /* allocate command memory */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* configure CMD_BASIC_CONFIG */ + prCmdBasicConfig = (P_CMD_BASIC_CONFIG) (prWifiCmd->aucBuffer); + kalMemCopy(&(prCmdBasicConfig->rMyMacAddr), &rMacAddr, PARAM_MAC_ADDR_LEN); + prCmdBasicConfig->ucNative80211 = 0; + prCmdBasicConfig->rCsumOffload.u2RxChecksum = 0; + prCmdBasicConfig->rCsumOffload.u2TxChecksum = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(2); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(1); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + prCmdBasicConfig->rCsumOffload.u2TxChecksum |= BIT(0); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(2); + + if (prAdapter->u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(1); + + if (prAdapter->u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + prCmdBasicConfig->rCsumOffload.u2RxChecksum |= BIT(0); +#endif + + /* send the command to FW */ + if (wlanSendCommand(prAdapter, prCmdInfo) == WLAN_STATUS_RESOURCES) { + + /* backup the command to wait response */ + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryAddress; + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + return WLAN_STATUS_PENDING; + } + /* send ok without response */ + nicCmdEventQueryAddress(prAdapter, prCmdInfo, (PUINT_8) prCmdBasicConfig); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if the device is in RF test mode +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->fgTestMode; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to identify 802.1x and Bluetooth-over-Wi-Fi +* security frames, and queued into command queue for strict ordering +* due to 802.1x frames before add-key OIDs are not to be encrypted +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prPacket Pointer of native packet +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket) +{ + UINT_8 ucPriorityParam; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen; + ULONG u4SysTime; + UINT_8 ucNetworkType; + P_CMD_INFO_T prCmdInfo; + UINT_8 ucCmdSeqNo = 0; + + /* 1x data packets */ + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prPacket); + + /* retrieve some information for packet classification */ + if (kalQoSFrameClassifierAndPacketInfo(prAdapter->prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, + &fgIsPAL, + &ucNetworkType, + &ucCmdSeqNo) == TRUE) { + /* almost TRUE except frame length < 14B */ + + if (fgIs1x == FALSE) + return FALSE; + + /* get a free command entry */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + P_STA_RECORD_T prStaRec; + + /* fill arrival time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_SECURITY_FRAME; + prCmdInfo->u2InfoBufLen = (UINT_16) u4PacketLen; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = prPacket; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNo; +#if 0 + prCmdInfo->ucStaRecIndex = qmGetStaRecIdx(prAdapter, + aucEthDestAddr, + (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType); +#endif + prStaRec = cnmGetStaRecByAddress(prAdapter, + (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType, + aucEthDestAddr); + if (prStaRec) + prCmdInfo->ucStaRecIndex = prStaRec->ucIndex; + else + prCmdInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + + prCmdInfo->eNetworkType = (ENUM_NETWORK_TYPE_INDEX_T) ucNetworkType; + prCmdInfo->pfCmdDoneHandler = wlanSecurityFrameTxDone; + prCmdInfo->pfCmdTimeoutHandler = wlanSecurityFrameTxTimeout; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + /* + queue the 1x packet and we will send the packet to CONNSYS by + using command queue + */ + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* TRUE: means we have already handled it in the function */ + return TRUE; + } + + /* no memory, why assert ? can skip the packet ? */ + ASSERT(0); + return FALSE; + } + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has been sent to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* @param pucEventBuf meaningless, only for API compatibility +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->eNetworkType == NETWORK_TYPE_AIS_INDEX && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure) { + + /* AIS counter measure so change RSN FSM to SEND_DEAUTH state */ + P_STA_RECORD_T prSta = cnmGetStaRecByIndex(prAdapter, prCmdInfo->ucStaRecIndex); + + if (prSta) { + kalMsleep(10); + secFsmEventEapolTxDone(prAdapter, prSta, TX_RESULT_SUCCESS); + } + } + + /* free the packet */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_SUCCESS); + DBGLOG(TX, INFO, "Security frame tx done, SeqNum: %d\n", prCmdInfo->ucCmdSeqNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when 802.1x or Bluetooth-over-Wi-Fi +* security frames has failed sending to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prCmdInfo Pointer of CMD_INFO_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* free the packet */ + kalSecurityFrameSendComplete(prAdapter->prGlueInfo, prCmdInfo->prPacket, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called before AIS is starting a new scan +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgKeepCurrOne = FALSE; + UINT_32 i; + + ASSERT(prAdapter); + + /* clear scanning result except current one */ + /* copy current one to prAdapter->rWlanInfo.arScanResult[0] */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + fgKeepCurrOne = TRUE; + + if (i != 0) { + /* copy structure */ + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[0]), + &(prAdapter->rWlanInfo.arScanResult[i]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + } + + if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] != + &(prAdapter->rWlanInfo.aucScanIEBuf[0])) { + /* move IEs to head */ + kalMemCopy(prAdapter->rWlanInfo.aucScanIEBuf, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + /* modify IE pointer */ + prAdapter->rWlanInfo.apucScanResultIEs[0] = + &(prAdapter->rWlanInfo.aucScanIEBuf[0]); + } else { + prAdapter->rWlanInfo.apucScanResultIEs[0] = NULL; + } + + break; + } + } + } + + if (fgKeepCurrOne == TRUE) { + prAdapter->rWlanInfo.u4ScanResultNum = 1; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = ALIGN_4(prAdapter->rWlanInfo.arScanResult[0].u4IELength); + } else { + prAdapter->rWlanInfo.u4ScanResultNum = 0; + prAdapter->rWlanInfo.u4ScanIEBufferUsage = 0; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when AIS received a beacon timeout event +* +* @param prAdapter Pointer of Adapter Data Structure +* @param arBSSID MAC address of the specified BSS +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID) +{ + UINT_32 i, j, u4IELength = 0, u4IEMoveLength; + PUINT_8 pucIEPtr; + + ASSERT(prAdapter); + + /* clear the scanning result for arBSSID */ + i = 0; + while (1) { + if (i >= prAdapter->rWlanInfo.u4ScanResultNum) + break; + + if (EQUAL_MAC_ADDR(arBSSID, prAdapter->rWlanInfo.arScanResult[i].arMacAddress)) { + + /* backup current IE length */ + u4IELength = ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4IELength); + pucIEPtr = prAdapter->rWlanInfo.apucScanResultIEs[i]; + + /* removed from middle */ + for (j = i + 1; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[j - 1]), + &(prAdapter->rWlanInfo.arScanResult[j]), + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + prAdapter->rWlanInfo.apucScanResultIEs[j - 1] = + prAdapter->rWlanInfo.apucScanResultIEs[j]; + } + + prAdapter->rWlanInfo.u4ScanResultNum--; + + /* remove IE buffer if needed := move rest of IE buffer */ + if (u4IELength > 0) { + u4IEMoveLength = prAdapter->rWlanInfo.u4ScanIEBufferUsage - + (((ULONG) pucIEPtr) + (ULONG) u4IELength - + ((ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])))); + + kalMemCopy(pucIEPtr, pucIEPtr + u4IELength, u4IEMoveLength); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4IELength; + + /* correction of pointers to IE buffer */ + for (j = 0; j < prAdapter->rWlanInfo.u4ScanResultNum; j++) { + if (prAdapter->rWlanInfo.apucScanResultIEs[j] > pucIEPtr) { + prAdapter->rWlanInfo.apucScanResultIEs[j] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[j]) - + u4IELength); + } + } + } + } + + i++; + } + +} + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter) +{ +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; + + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(FALSE); + return; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prMsgFuncSwitch->fgIsFuncOn = TRUE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + +} + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter) +{ + + P_MSG_P2P_CONNECTION_REQUEST_T prMsgConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; + + prMsgConnReq = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + if (!prMsgConnReq) { + ASSERT(FALSE); + return; + } + + prMsgConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + /*=====Param Modified for test=====*/ + COPY_MAC_ADDR(prMsgConnReq->aucDeviceID, aucTargetDeviceID); + prMsgConnReq->fgIsTobeGO = TRUE; + prMsgConnReq->fgIsPersistentGroup = FALSE; + + /*=====Param Modified for test=====*/ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgConnReq, MSG_SEND_METHOD_BUF); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve permanent address from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryPermanentAddress"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_BASIC_CONFIG); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_BASIC_CONFIG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_BASIC_CONFIG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* wait for response */ + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_BASIC_CONFIG), /* 8B + 12B */ + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_BASIC_CONFIG) + return WLAN_STATUS_FAILURE; + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (prEvent->aucBuffer); + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucPermanentAddress, &(prEventBasicConfig->rMyMacAddr)); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, &(prEventBasicConfig->rMyMacAddr)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_32 u4FwIDVersion = 0; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_EVENT_NIC_CAPABILITY prEventNicCapability; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryNicCapability"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(EVENT_NIC_CAPABILITY); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_NIC_CAPABILITY; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + /* wait for FW response */ + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(EVENT_NIC_CAPABILITY), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_NIC_CAPABILITY) + return WLAN_STATUS_FAILURE; + + prEventNicCapability = (P_EVENT_NIC_CAPABILITY) (prEvent->aucBuffer); + + prAdapter->rVerInfo.u2FwProductID = prEventNicCapability->u2ProductID; + prAdapter->rVerInfo.u2FwOwnVersion = prEventNicCapability->u2FwVersion; + prAdapter->rVerInfo.u2FwPeerVersion = prEventNicCapability->u2DriverVersion; + prAdapter->fgIsHw5GBandDisabled = (BOOLEAN) prEventNicCapability->ucHw5GBandDisabled; + prAdapter->fgIsEepromUsed = (BOOLEAN) prEventNicCapability->ucEepromUsed; + prAdapter->fgIsEfuseValid = (BOOLEAN) prEventNicCapability->ucEfuseValid; + prAdapter->fgIsEmbbededMacAddrValid = (BOOLEAN) prEventNicCapability->ucMacAddrValid; + + u4FwIDVersion = (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); + mtk_wcn_wmt_set_wifi_ver(u4FwIDVersion); +#if (CFG_SUPPORT_TDLS == 1) + if (prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_TDLS)) + prAdapter->fgTdlsIsSup = TRUE; + DBGLOG(TDLS, TRACE, " support flag: 0x%x\n", prEventNicCapability->ucFeatureSet); +#else + prAdapter->fgTdlsIsSup = 0; +#endif /* CFG_SUPPORT_TDLS */ + + if (!(prEventNicCapability->ucFeatureSet & (1 << FEATURE_SET_OFFSET_5G_SUPPORT))) + prAdapter->fgEnable5GBand = FALSE; /* firmware does not support */ + +#if CFG_ENABLE_CAL_LOG + DBGLOG(INIT, LOUD, " RF CAL FAIL = (%d),BB CAL FAIL = (%d)\n", + prEventNicCapability->ucRfCalFail, prEventNicCapability->ucBbCalFail); +#endif + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve NIC capability from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + + ASSERT(prAdapter); + + DEBUGFUNC("wlanQueryDebugCode"); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_GET_DEBUG_CODE; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* send the command */ + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to retrieve compiler flag from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryCompileFlag(IN P_ADAPTER_T prAdapter, IN UINT_32 u4QueryID, OUT PUINT_32 pu4CompilerFlag) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_CMD_SW_DBG_CTRL_T prCmdNicCompileFlag, prEventNicCompileFlag; + + ASSERT(prAdapter); + + DEBUGFUNC(__func__); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T)); + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_SW_DBG_CTRL_T); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_SW_DBG_CTRL; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = 0; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + /* Fill up SW CR */ + prCmdNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prWifiCmd->aucBuffer); + + prCmdNicCompileFlag->u4Id = u4QueryID; + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(CMD_SW_DBG_CTRL_T), + &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + if (prEvent->ucEID != EVENT_ID_SW_DBG_CTRL) + return WLAN_STATUS_FAILURE; + + prEventNicCompileFlag = (P_CMD_SW_DBG_CTRL_T) (prEvent->aucBuffer); + + *pu4CompilerFlag = prEventNicCompileFlag->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter) +{ + wlanQueryCompileFlag(prAdapter, 0xA0240000, &prAdapter->u4FwCompileFlag0); + wlanQueryCompileFlag(prAdapter, 0xA0240001, &prAdapter->u4FwCompileFlag1); + + DBGLOG(INIT, TRACE, + "Compile Flags: 0x%08x 0x%08x\n", prAdapter->u4FwCompileFlag0, prAdapter->u4FwCompileFlag1); + + return WLAN_STATUS_SUCCESS; +} + +#if defined(MT6628) +static INT_32 wlanChangeCodeWord(INT_32 au4Input) +{ + + UINT_16 i; +#if TXPWR_USE_PDSLOPE + CODE_MAPPING_T arCodeTable[] = { + {0X100, -40}, + {0X104, -35}, + {0X128, -30}, + {0X14C, -25}, + {0X170, -20}, + {0X194, -15}, + {0X1B8, -10}, + {0X1DC, -5}, + {0, 0}, + {0X24, 5}, + {0X48, 10}, + {0X6C, 15}, + {0X90, 20}, + {0XB4, 25}, + {0XD8, 30}, + {0XFC, 35}, + {0XFF, 40}, + + }; +#else + CODE_MAPPING_T arCodeTable[] = { + {0X100, 0x80}, + {0X104, 0x80}, + {0X128, 0x80}, + {0X14C, 0x80}, + {0X170, 0x80}, + {0X194, 0x94}, + {0X1B8, 0XB8}, + {0X1DC, 0xDC}, + {0, 0}, + {0X24, 0x24}, + {0X48, 0x48}, + {0X6C, 0x6c}, + {0X90, 0x7F}, + {0XB4, 0x7F}, + {0XD8, 0x7F}, + {0XFC, 0x7F}, + {0XFF, 0x7F}, + + }; +#endif + + for (i = 0; i < sizeof(arCodeTable) / sizeof(CODE_MAPPING_T); i++) { + + if (arCodeTable[i].u4RegisterValue == au4Input) + return arCodeTable[i].i4TxpowerOffset; + } + + return 0; +} +#endif + +#if TXPWR_USE_PDSLOPE + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo) +{ + UINT_8 ucCmdSeqNum; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_32 u4RxPktLength; + UINT_8 aucBuffer[sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG)]; + P_HIF_RX_HEADER_T prHifRxHdr; + P_WIFI_EVENT_T prEvent; + P_CMD_ACCESS_REG prCmdMcrQuery; + + ASSERT(prAdapter); + + /* 1. Allocate CMD Info Packet and its Buffer */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + + if (!prCmdInfo) { + DBGLOG(INIT, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + sizeof(CMD_ACCESS_REG)); + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_ACCESS_REG; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_ACCESS_REG); + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + kalMemCopy(prWifiCmd->aucBuffer, prMcrRdInfo, sizeof(CMD_ACCESS_REG)); + + wlanSendCommand(prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + + if (nicRxWaitResponse(prAdapter, + 1, + aucBuffer, + sizeof(WIFI_EVENT_T) + sizeof(CMD_ACCESS_REG), &u4RxPktLength) != WLAN_STATUS_SUCCESS) + return WLAN_STATUS_FAILURE; + /* header checking .. */ + prHifRxHdr = (P_HIF_RX_HEADER_T) aucBuffer; + if ((prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK) != HIF_RX_PKT_TYPE_EVENT) + return WLAN_STATUS_FAILURE; + + prEvent = (P_WIFI_EVENT_T) aucBuffer; + + if (prEvent->ucEID != EVENT_ID_ACCESS_REG) + return WLAN_STATUS_FAILURE; + + prCmdMcrQuery = (P_CMD_ACCESS_REG) (prEvent->aucBuffer); + prMcrRdInfo->u4McrOffset = prCmdMcrQuery->u4Address; + prMcrRdInfo->u4McrData = prCmdMcrQuery->u4Data; + + return WLAN_STATUS_SUCCESS; +} + +static INT_32 wlanIntRound(INT_32 au4Input) +{ + + if (au4Input >= 0) { + if ((au4Input % 10) == 5) { + au4Input = au4Input + 5; + return au4Input; + } + } + + if (au4Input < 0) { + if ((au4Input % 10) == -5) { + au4Input = au4Input - 5; + return au4Input; + } + } + + return au4Input; +} + +static INT_32 wlanCal6628EfuseForm(IN P_ADAPTER_T prAdapter, INT_32 au4Input) +{ + + PARAM_MCR_RW_STRUCT_T rMcrRdInfo; + INT_32 au4PdSlope, au4TxPwrOffset, au4TxPwrOffset_Round; + INT_8 auTxPwrOffset_Round; + + rMcrRdInfo.u4McrOffset = 0x60205c68; + rMcrRdInfo.u4McrData = 0; + au4TxPwrOffset = au4Input; + wlanQueryPdMcr(prAdapter, &rMcrRdInfo); + + au4PdSlope = (rMcrRdInfo.u4McrData) & BITS(0, 6); + au4TxPwrOffset_Round = wlanIntRound((au4TxPwrOffset * au4PdSlope)) / 10; + + au4TxPwrOffset_Round = -au4TxPwrOffset_Round; + + if (au4TxPwrOffset_Round < -128) + au4TxPwrOffset_Round = 128; + else if (au4TxPwrOffset_Round < 0) + au4TxPwrOffset_Round += 256; + else if (au4TxPwrOffset_Round > 127) + au4TxPwrOffset_Round = 127; + + auTxPwrOffset_Round = (UINT8) au4TxPwrOffset_Round; + + return au4TxPwrOffset_Round; +} + +#endif + +#if defined(MT6628) +static VOID wlanChangeNvram6620to6628(PUINT_8 pucEFUSE) +{ + +#define EFUSE_CH_OFFSET1_L_MASK_6620 BITS(0, 8) +#define EFUSE_CH_OFFSET1_L_SHIFT_6620 0 +#define EFUSE_CH_OFFSET1_M_MASK_6620 BITS(9, 17) +#define EFUSE_CH_OFFSET1_M_SHIFT_6620 9 +#define EFUSE_CH_OFFSET1_H_MASK_6620 BITS(18, 26) +#define EFUSE_CH_OFFSET1_H_SHIFT_6620 18 +#define EFUSE_CH_OFFSET1_VLD_MASK_6620 BIT(27) +#define EFUSE_CH_OFFSET1_VLD_SHIFT_6620 27 + +#define EFUSE_CH_OFFSET1_L_MASK_5931 BITS(0, 7) +#define EFUSE_CH_OFFSET1_L_SHIFT_5931 0 +#define EFUSE_CH_OFFSET1_M_MASK_5931 BITS(8, 15) +#define EFUSE_CH_OFFSET1_M_SHIFT_5931 8 +#define EFUSE_CH_OFFSET1_H_MASK_5931 BITS(16, 23) +#define EFUSE_CH_OFFSET1_H_SHIFT_5931 16 +#define EFUSE_CH_OFFSET1_VLD_MASK_5931 BIT(24) +#define EFUSE_CH_OFFSET1_VLD_SHIFT_5931 24 +#define EFUSE_ALL_CH_OFFSET1_MASK_5931 BITS(25, 27) +#define EFUSE_ALL_CH_OFFSET1_SHIFT_5931 25 + + INT_32 au4ChOffset; + INT_16 au2ChOffsetL, au2ChOffsetM, au2ChOffsetH; + + au4ChOffset = *(UINT_32 *) (pucEFUSE + 72); + + if ((au4ChOffset & EFUSE_CH_OFFSET1_VLD_MASK_6620) && ((*(UINT_32 *) (pucEFUSE + 28)) == 0)) { + + au2ChOffsetL = ((au4ChOffset & EFUSE_CH_OFFSET1_L_MASK_6620) >> EFUSE_CH_OFFSET1_L_SHIFT_6620); + + au2ChOffsetM = ((au4ChOffset & EFUSE_CH_OFFSET1_M_MASK_6620) >> EFUSE_CH_OFFSET1_M_SHIFT_6620); + + au2ChOffsetH = ((au4ChOffset & EFUSE_CH_OFFSET1_H_MASK_6620) >> EFUSE_CH_OFFSET1_H_SHIFT_6620); + + au2ChOffsetL = wlanChangeCodeWord(au2ChOffsetL); + au2ChOffsetM = wlanChangeCodeWord(au2ChOffsetM); + au2ChOffsetH = wlanChangeCodeWord(au2ChOffsetH); + + au4ChOffset = 0; + au4ChOffset |= *(UINT_32 *) (pucEFUSE + 72) + >> (EFUSE_CH_OFFSET1_VLD_SHIFT_6620 - + EFUSE_CH_OFFSET1_VLD_SHIFT_5931) & EFUSE_CH_OFFSET1_VLD_MASK_5931; + + au4ChOffset |= + ((((UINT_32) au2ChOffsetL) << EFUSE_CH_OFFSET1_L_SHIFT_5931) & EFUSE_CH_OFFSET1_L_MASK_5931); + au4ChOffset |= + ((((UINT_32) au2ChOffsetM) << EFUSE_CH_OFFSET1_M_SHIFT_5931) & EFUSE_CH_OFFSET1_M_MASK_5931); + au4ChOffset |= + ((((UINT_32) au2ChOffsetH) << EFUSE_CH_OFFSET1_H_SHIFT_5931) & EFUSE_CH_OFFSET1_H_MASK_5931); + + *((INT_32 *) ((pucEFUSE + 28))) = au4ChOffset; + + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to load manufacture data from NVRAM +* if available and valid +* +* @param prAdapter Pointer of Adapter Data Structure +* @param prRegInfo Pointer of REG_INFO_T +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ +#if CFG_SUPPORT_RDD_TEST_MODE + CMD_RDD_CH_T rRddParam; +#endif + + ASSERT(prAdapter); + + /* 1. Version Check */ + kalGetConfigurationVersion(prAdapter->prGlueInfo, + &(prAdapter->rVerInfo.u2Part1CfgOwnVersion), + &(prAdapter->rVerInfo.u2Part1CfgPeerVersion), + &(prAdapter->rVerInfo.u2Part2CfgOwnVersion), + &(prAdapter->rVerInfo.u2Part2CfgPeerVersion)); + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + if (CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION) { + return WLAN_STATUS_FAILURE; + } +#endif + + /* MT6620 E1/E2 would be ignored directly */ + if (prAdapter->rVerInfo.u2Part1CfgOwnVersion == 0x0001) { + prRegInfo->ucTxPwrValid = 1; + } else { + /* 2. Load TX power gain parameters if valid */ + if (prRegInfo->ucTxPwrValid != 0) { + /* send to F/W */ + nicUpdateTxPower(prAdapter, (P_CMD_TX_PWR_T) (&(prRegInfo->rTxPwr))); + } + } + + /* Workaround for supporting 5G */ + prRegInfo->ucEnable5GBand = 1; + prRegInfo->ucSupport5GBand = 1; + + /* 3. Check if needs to support 5GHz */ + /* if(prRegInfo->ucEnable5GBand) { // Frank workaround */ + if (1) { + /* check if it is disabled by hardware */ + if (prAdapter->fgIsHw5GBandDisabled || prRegInfo->ucSupport5GBand == 0) + prAdapter->fgEnable5GBand = FALSE; + else + prAdapter->fgEnable5GBand = TRUE; + } else + prAdapter->fgEnable5GBand = FALSE; + /* Workaround for supporting 5G */ + prAdapter->fgEnable5GBand = TRUE; +/* + DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d)\n", + prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled); +*/ + /* 4. Send EFUSE data */ +#if defined(MT6628) + wlanChangeNvram6620to6628(prRegInfo->aucEFUSE); +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PHY_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PHY_PARAM_T), (PUINT_8) (prRegInfo->aucEFUSE), NULL, 0); + +#if CFG_SUPPORT_RDD_TEST_MODE + rRddParam.ucRddTestMode = (UINT_8) prRegInfo->u4RddTestMode; + rRddParam.ucRddShutCh = (UINT_8) prRegInfo->u4RddShutFreq; + rRddParam.ucRddStartCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStartFreq); + rRddParam.ucRddStopCh = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4RddStopFreq); + rRddParam.ucRddDfs = (UINT_8) prRegInfo->u4RddDfs; + prAdapter->ucRddStatus = 0; + nicUpdateRddTestMode(prAdapter, (P_CMD_RDD_CH_T) (&rRddParam)); +#endif + + /* 5. Get 16-bits Country Code and Bandwidth */ + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) prRegInfo->au2CountryCode[0]) << 8) | (((UINT_16) prRegInfo->au2CountryCode[1]) & BITS(0, 7)); + + DBGLOG(INIT, INFO, "NVRAM 5G Enable(%d) SW_En(%d) HW_Dis(%d) CountryCode(0x%x 0x%x)\n", + prRegInfo->ucEnable5GBand, prRegInfo->ucSupport5GBand, prAdapter->fgIsHw5GBandDisabled, + prRegInfo->au2CountryCode[0], prRegInfo->au2CountryCode[1]); + +#if 0 /* Bandwidth control will be controlled by GUI. 20110930 + * So ignore the setting from registry/NVRAM + */ + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = + prRegInfo->uc2G4BwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = + prRegInfo->uc5GBwFixed20M ? CONFIG_BW_20M : CONFIG_BW_20_40M; +#endif + + /* 6. Set domain and channel information to chip */ + rlmDomainSendCmd(prAdapter, FALSE); + /* Update supported channel list in channel table */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + /* 7. Set band edge tx power if available */ + if (prRegInfo->fg2G4BandEdgePwrUsed) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK = prRegInfo->cBandEdgeMaxPwrCCK; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 = prRegInfo->cBandEdgeMaxPwrOFDM20; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 = prRegInfo->cBandEdgeMaxPwrOFDM40; + + DBGLOG(INIT, TRACE, "NVRAM 2G Bandedge CCK(%d) HT20(%d)HT40(%d)\n", + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrCCK, + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); + } + /* 8. set 5G band edge tx power if available (add for 6625) */ + if (prAdapter->fgEnable5GBand) { +#define NVRAM_5G_TX_BANDEDGE_VALID_OFFSET 10 +#define NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET 11 +#define NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET 12 + + if (prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_VALID_OFFSET]) { + CMD_EDGE_TXPWR_LIMIT_T rCmdEdgeTxPwrLimit; + + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20 + = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM20_OFFSET]; + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40 + = prRegInfo->aucEFUSE[NVRAM_5G_TX_BANDEDGE_OFDM40_OFFSET]; + + DBGLOG(INIT, TRACE, "NVRAM 5G Bandedge HT20(%d)HT40(%d)\n", + rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM20, rCmdEdgeTxPwrLimit.cBandEdgeMaxPwrOFDM40); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_EDGE_TXPWR_LIMIT_T), (PUINT_8)&rCmdEdgeTxPwrLimit, NULL, 0); + } + } + /* 9. set RSSI compensation */ + /* DBGLOG(INIT, INFO, ("[frank] RSSI valid(%d) 2G(%d) 5G(%d)", + prRegInfo->fgRssiCompensationValidbit, + prRegInfo->uc2GRssiCompensation, + prRegInfo->uc5GRssiCompensation)); */ + if (prRegInfo->fgRssiCompensationValidbit) { + CMD_RSSI_COMPENSATE_T rCmdRssiCompensate; + + rCmdRssiCompensate.uc2GRssiCompensation = prRegInfo->uc2GRssiCompensation; + rCmdRssiCompensate.uc5GRssiCompensation = prRegInfo->uc5GRssiCompensation; + + DBGLOG(INIT, LOUD, "NVRAM RSSI Comp. 2G(%d)5G(%d)\n", + rCmdRssiCompensate.uc2GRssiCompensation, rCmdRssiCompensate.uc5GRssiCompensation); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RSSI_COMPENSATE, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_RSSI_COMPENSATE_T), (PUINT_8)&rCmdRssiCompensate, NULL, 0); + } + /* 10. notify FW Band Support 5G */ + if (prAdapter->fgEnable5GBand) { + CMD_BAND_SUPPORT_T rCmdBandSupport; + + rCmdBandSupport.uc5GBandSupport = TRUE; + DBGLOG(INIT, TRACE, "NVRAM 5G BandSupport\n"); + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BAND_SUPPORT, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_BAND_SUPPORT_T), (PUINT_8)&rCmdBandSupport, NULL, 0); + + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check +* Media Stream Mode is set to non-default value or not, +* and clear to default value if above criteria is met +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return TRUE +* The media stream mode was non-default value and has been reset +* FALSE +* The media stream mode is default value +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode != 0) { + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending timer has expired +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* check timer status */ + cnmTimerDoTimeOutCheck(prAdapter); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to check if any pending mailbox message +* to be handled +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { /* MBOX_ID_TOTAL_NUM = 1 */ + mboxRcvAllMsg(prAdapter, (ENUM_MBOX_ID_T) i); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to enqueue a single TX packet into CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* prNativePacket Pointer of Native Packet +* +* @return WLAN_STATUS_SUCCESS +* WLAN_STATUS_RESOURCES +* WLAN_STATUS_INVALID_PACKET +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + /* get a free packet header */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo == NULL) + return WLAN_STATUS_RESOURCES; + + prMsduInfo->eSrc = TX_PACKET_OS; + + if (nicTxFillMsduInfo(prAdapter, prMsduInfo, prNativePacket) == FALSE) { + /* packet is not extractable */ + + /* fill fails */ + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_INVALID_PACKET); + + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + + return WLAN_STATUS_INVALID_PACKET; + } + /* enqueue to QM */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to flush pending TX packets in CORE +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return nicTxFlush(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function sends pending MSDU_INFO_T to MT6620 +* +* @param prAdapter Pointer to the Adapter structure. +* @param pfgHwAccess Pointer for tracking LP-OWN status +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(pfgHwAccess); + + /* <1> dequeue packets by txDequeuTxPackets() */ + /* Note: prMsduInfo is a packet list queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmDequeueTxPackets(prAdapter, &prTxCtrl->rTc); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == FALSE) { + /* <2> Acquire LP-OWN if necessary */ + if (*pfgHwAccess == FALSE) { + *pfgHwAccess = TRUE; + + wlanAcquirePowerControl(prAdapter); + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + /* <3> send packet"s" to HIF */ + nicTxMsduInfoList(prAdapter, prMsduInfo); + + /* <4> update TC by txAdjustTcQuotas() */ + nicTxAdjustTcq(prAdapter); + } else + wlanProcessQueuedMsduInfo(prAdapter, prMsduInfo); /* free the packet */ + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to acquire power control from firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* do driver own */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); + + /* Reset sleepy state *//* no use */ + if (prAdapter->fgWiFiInSleepyState == TRUE) + prAdapter->fgWiFiInSleepyState = FALSE; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to release power control to firmware +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* do FW own */ + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to report currently pending TX frames count +* (command packets are not included) +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return number of pending TX frames +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + UINT_32 u4Num; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* number in prTxQueue + number in RX forward */ + u4Num = kalGetTxPendingFrameCount(prAdapter->prGlueInfo) + (UINT_32) (prTxCtrl->i4PendingFwdFrameCount); + + return u4Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to report current ACPI state +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +*/ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rAcpiState; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to update current ACPI state only +* +* @param prAdapter Pointer of Adapter Data Structure +* @param ePowerState ACPI_STATE_D0 Normal Operation Mode +* ACPI_STATE_D3 Suspend Mode +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState) +{ + ASSERT(prAdapter); + ASSERT(ePowerState <= ACPI_STATE_D3); + + prAdapter->rAcpiState = ePowerState; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to query ECO version from HIFSYS CR +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (nicVerifyChipID(prAdapter) == TRUE) + return prAdapter->ucRevID + 1; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to setting the default Tx Power configuration +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return zero Unable to retrieve ECO version information +* non-zero ECO version (1-based) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter) +{ + UINT_8 i; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_SET_TXPWR_CTRL_T prTxpwr; + + ASSERT(prGlueInfo); + + prTxpwr = &prGlueInfo->rTxPwr; + + prTxpwr->c2GLegacyStaPwrOffset = 0; + prTxpwr->c2GHotspotPwrOffset = 0; + prTxpwr->c2GP2pPwrOffset = 0; + prTxpwr->c2GBowPwrOffset = 0; + prTxpwr->c5GLegacyStaPwrOffset = 0; + prTxpwr->c5GHotspotPwrOffset = 0; + prTxpwr->c5GP2pPwrOffset = 0; + prTxpwr->c5GBowPwrOffset = 0; + prTxpwr->ucConcurrencePolicy = 0; + for (i = 0; i < 3; i++) + prTxpwr->acReserved1[i] = 0; + + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = 63; + + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = 63; + + for (i = 0; i < 2; i++) + prTxpwr->acReserved2[i] = 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* set preferred band configuration corresponding to network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eBand Given band +* @param eNetTypeIndex Given Network Type +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + /* 1. set prefer band according to network type */ + prAdapter->aePreferBand[eNetTypeIndex] = eBand; + + /* 2. remove buffered BSS descriptors correspondingly */ + if (eBand == BAND_2G4) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_5G, eNetTypeIndex); + else if (eBand == BAND_5G) + scanRemoveBssDescByBandAndNetwork(prAdapter, BAND_2G4, eNetTypeIndex); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get channel information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + return prBssInfo->ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* get BSS descriptor information corresponding to specified network type +* +* @param prAdapter Pointer of Adapter Data Structure +* @param eNetTypeIndex Given Network Type +* +* @return pointer to BSS_DESC_T +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + return prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + + case NETWORK_TYPE_P2P_INDEX: + return NULL; + + case NETWORK_TYPE_BOW_INDEX: + return prAdapter->rWifiVar.rBowFsmInfo.prTargetBssDesc; + + default: + return NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to +* check unconfigured system properties and generate related message on +* scan list to notify users +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter) +{ +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) || (CFG_SW_NVRAM_VERSION_CHECK == 1) + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + const UINT_8 aucBCAddr[] = BC_MAC_ADDR; + BOOLEAN fgIsConfExist = TRUE; + BOOLEAN fgGenErrMsg = FALSE; + P_REG_INFO_T prRegInfo = NULL; + P_WLAN_BEACON_FRAME_T prBeacon = NULL; + P_IE_SSID_T prSsid = NULL; + UINT_32 u4ErrCode = 0; + UINT_8 aucErrMsg[32]; + PARAM_SSID_T rSsid; + PARAM_802_11_CONFIG_T rConfiguration; + PARAM_RATES_EX rSupportedRates; +#endif + + DEBUGFUNC("wlanCheckSystemConfiguration"); + + ASSERT(prAdapter); + +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) { + fgIsConfExist = FALSE; + fgGenErrMsg = TRUE; + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) + prRegInfo = kalGetConfiguration(prAdapter->prGlueInfo); + + if (fgIsConfExist == TRUE && (CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion + || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + || prAdapter->fgIsPowerLimitTableValid == FALSE +#endif + || (prAdapter->fgIsEmbbededMacAddrValid == FALSE && + (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, prRegInfo->aucMacAddr))) + || prRegInfo->ucTxPwrValid == 0)) + fgGenErrMsg = TRUE; +#endif + + if (fgGenErrMsg == TRUE) { + prBeacon = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + if (!prBeacon) { + ASSERT(FALSE); + return WLAN_STATUS_FAILURE; + } + + /* initialization */ + kalMemZero(prBeacon, sizeof(WLAN_BEACON_FRAME_T) + sizeof(IE_SSID_T)); + + /* prBeacon initialization */ + prBeacon->u2FrameCtrl = MAC_FRAME_BEACON; + COPY_MAC_ADDR(prBeacon->aucDestAddr, aucBCAddr); + COPY_MAC_ADDR(prBeacon->aucSrcAddr, aucZeroMacAddr); + COPY_MAC_ADDR(prBeacon->aucBSSID, aucZeroMacAddr); + prBeacon->u2BeaconInterval = 100; + prBeacon->u2CapInfo = CAP_INFO_ESS; + + /* prSSID initialization */ + prSsid = (P_IE_SSID_T) (&prBeacon->aucInfoElem[0]); + prSsid->ucId = ELEM_ID_SSID; + + /* rConfiguration initialization */ + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = 100; + rConfiguration.u4ATIMWindow = 1; + rConfiguration.u4DSConfig = 2412; + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + /* rSupportedRates initialization */ + kalMemZero(rSupportedRates, sizeof(PARAM_RATES_EX)); + } +#if (CFG_NVRAM_EXISTENCE_CHECK == 1) +#define NVRAM_ERR_MSG "NVRAM WARNING: Err = 0x01" + if ((kalIsConfigurationExist(prAdapter->prGlueInfo) == FALSE) && (prBeacon) && (prSsid)) { + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength, + 1, 0); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + prSsid->ucLength - + WLAN_MAC_MGMT_HEADER_LEN, (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } +#endif + +#if (CFG_SW_NVRAM_VERSION_CHECK == 1) +#define VER_ERR_MSG "NVRAM WARNING: Err = 0x%02X" + if ((fgIsConfExist == TRUE) && (prBeacon) && (prSsid)) { + if ((CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part1CfgPeerVersion + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2Part2CfgPeerVersion + || prAdapter->rVerInfo.u2Part1CfgOwnVersion <= CFG_DRV_PEER_VERSION + || prAdapter->rVerInfo.u2Part2CfgOwnVersion <= CFG_DRV_PEER_VERSION /* NVRAM */ + || CFG_DRV_OWN_VERSION < prAdapter->rVerInfo.u2FwPeerVersion + || prAdapter->rVerInfo.u2FwOwnVersion <= CFG_DRV_PEER_VERSION)) + u4ErrCode |= NVRAM_ERROR_VERSION_MISMATCH; + + if (prRegInfo->ucTxPwrValid == 0) + u4ErrCode |= NVRAM_ERROR_INVALID_TXPWR; + + if (prAdapter->fgIsEmbbededMacAddrValid == FALSE && (IS_BMCAST_MAC_ADDR(prRegInfo->aucMacAddr) + || EQUAL_MAC_ADDR(aucZeroMacAddr, + prRegInfo->aucMacAddr))) + u4ErrCode |= NVRAM_ERROR_INVALID_MAC_ADDR; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + if (prAdapter->fgIsPowerLimitTableValid == FALSE) + u4ErrCode |= NVRAM_POWER_LIMIT_TABLE_INVALID; +#endif + if (u4ErrCode != 0) { + sprintf(aucErrMsg, VER_ERR_MSG, (unsigned int)u4ErrCode); + COPY_SSID(prSsid->aucSSID, prSsid->ucLength, aucErrMsg, strlen(aucErrMsg)); + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBeacon, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength, 1, 0); + + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, NVRAM_ERR_MSG, strlen(NVRAM_ERR_MSG)); + nicAddScanResult(prAdapter, + prBeacon->aucBSSID, + &rSsid, + 0, + 0, + PARAM_NETWORK_TYPE_FH, + &rConfiguration, + NET_TYPE_INFRA, + rSupportedRates, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem) + OFFSET_OF(IE_SSID_T, + aucSSID) + + prSsid->ucLength - WLAN_MAC_MGMT_HEADER_LEN, + (PUINT_8) ((ULONG) (prBeacon) + WLAN_MAC_MGMT_HEADER_LEN)); + } + } +#endif + + if (fgGenErrMsg == TRUE) + cnmMemFree(prAdapter, prBeacon); + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prStaRec, prTempStaRec; + P_PARAM_GET_STA_STATISTICS prQueryStaStatistics; + UINT_8 ucStaRecIdx; + P_QUE_MGT_T prQM = &prAdapter->rQM; + CMD_GET_STA_STATISTICS_T rQueryCmdStaStatistics; + UINT_8 ucIdx; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(PARAM_GET_STA_STA_STATISTICS)) { + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prQueryStaStatistics = (P_PARAM_GET_STA_STATISTICS) pvQueryBuffer; + *pu4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* 4 5. Get driver global QM counter */ + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcAverageQueLen[ucIdx] = prQM->au4AverageQueLen[ucIdx]; + prQueryStaStatistics->au4TcCurrentQueLen[ucIdx] = prQM->au4CurrentTcResource[ucIdx]; + } + + /* 4 2. Get StaRec by MAC address */ + prStaRec = NULL; + + for (ucStaRecIdx = 0; ucStaRecIdx < CFG_NUM_OF_STA_RECORD; ucStaRecIdx++) { + prTempStaRec = &(prAdapter->arStaRec[ucStaRecIdx]); + if (prTempStaRec->fgIsValid && prTempStaRec->fgIsInUse) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prQueryStaStatistics->aucMacAddr)) { + prStaRec = prTempStaRec; + break; + } + } + } + + if (!prStaRec) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + prQueryStaStatistics->u4Flag |= BIT(0); + +#if CFG_ENABLE_PER_STA_STATISTICS + /* 4 3. Get driver statistics */ + DBGLOG(TX, INFO, "skbToDriver %lld, skbFreed: %lld\n", + prAdapter->prGlueInfo->u8SkbToDriver, + prAdapter->prGlueInfo->u8SkbFreed); + prAdapter->prGlueInfo->u8SkbFreed = 0; + prAdapter->prGlueInfo->u8SkbToDriver = 0; + + prQueryStaStatistics->u4TxTotalCount = prStaRec->u4TotalTxPktsNumber; + prQueryStaStatistics->u4TxExceedThresholdCount = prStaRec->u4ThresholdCounter; + prQueryStaStatistics->u4TxMaxTime = prStaRec->u4MaxTxPktsTime; + prQueryStaStatistics->u4TxMaxHifTime = prStaRec->u4MaxTxPktsHifTime; + if (prStaRec->u4TotalTxPktsNumber) { + prQueryStaStatistics->u4TxAverageProcessTime = + (prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber); + prQueryStaStatistics->u4TxAverageHifTime = + (prStaRec->u4TotalTxPktsHifTime / prStaRec->u4TotalTxPktsNumber); + } else + prQueryStaStatistics->u4TxAverageProcessTime = 0; + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) { + prQueryStaStatistics->au4TcResourceEmptyCount[ucIdx] = + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx]; + /* Reset */ + prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][ucIdx] = 0; + prQueryStaStatistics->au4TcResourceBackCount[ucIdx] = + prQM->au4QmTcResourceBackCounter[ucIdx]; + prQM->au4QmTcResourceBackCounter[ucIdx] = 0; + + prQueryStaStatistics->au4DequeueNoTcResource[ucIdx] = + prQM->au4DequeueNoTcResourceCounter[ucIdx]; + prQM->au4DequeueNoTcResourceCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceUsedCount[ucIdx] = + prQM->au4ResourceUsedCounter[ucIdx]; + prQM->au4ResourceUsedCounter[ucIdx] = 0; + prQueryStaStatistics->au4TcResourceWantedCount[ucIdx] = + prQM->au4ResourceWantedCounter[ucIdx]; + prQM->au4ResourceWantedCounter[ucIdx] = 0; + } + + prQueryStaStatistics->u4EnqueueCounter = prQM->u4EnqeueuCounter; + prQueryStaStatistics->u4DequeueCounter = prQM->u4DequeueCounter; + prQueryStaStatistics->u4EnqueueStaCounter = prStaRec->u4EnqeueuCounter; + prQueryStaStatistics->u4DequeueStaCounter = prStaRec->u4DeqeueuCounter; + + prQueryStaStatistics->IsrCnt = prGlueInfo->IsrCnt - prGlueInfo->IsrPreCnt; + prQueryStaStatistics->IsrPassCnt = prGlueInfo->IsrPassCnt - prGlueInfo->IsrPrePassCnt; + prQueryStaStatistics->TaskIsrCnt = prGlueInfo->TaskIsrCnt - prGlueInfo->TaskPreIsrCnt; + + prQueryStaStatistics->IsrAbnormalCnt = prGlueInfo->IsrAbnormalCnt; + prQueryStaStatistics->IsrSoftWareCnt = prGlueInfo->IsrSoftWareCnt; + prQueryStaStatistics->IsrRxCnt = prGlueInfo->IsrRxCnt; + prQueryStaStatistics->IsrTxCnt = prGlueInfo->IsrTxCnt; + + /* 4 4.1 Reset statistics */ + prStaRec->u4ThresholdCounter = 0; + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4MaxTxPktsHifTime = 0; + + prStaRec->u4EnqeueuCounter = 0; + prStaRec->u4DeqeueuCounter = 0; + + prQM->u4EnqeueuCounter = 0; + prQM->u4DequeueCounter = 0; + + prGlueInfo->IsrPreCnt = prGlueInfo->IsrCnt; + prGlueInfo->IsrPrePassCnt = prGlueInfo->IsrPassCnt; + prGlueInfo->TaskPreIsrCnt = prGlueInfo->TaskIsrCnt; + prGlueInfo->IsrAbnormalCnt = 0; + prGlueInfo->IsrSoftWareCnt = 0; + prGlueInfo->IsrRxCnt = 0; + prGlueInfo->IsrTxCnt = 0; +#endif + + for (ucIdx = TC0_INDEX; ucIdx <= TC3_INDEX; ucIdx++) + prQueryStaStatistics->au4TcQueLen[ucIdx] = prStaRec->arTxQueue[ucIdx].u4NumElem; + + rResult = WLAN_STATUS_SUCCESS; + + /* 4 6. Ensure FW supports get station link status */ + if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { + + rQueryCmdStaStatistics.ucIndex = prStaRec->ucIndex; + COPY_MAC_ADDR(rQueryCmdStaStatistics.aucMacAddr, prQueryStaStatistics->aucMacAddr); + rQueryCmdStaStatistics.ucReadClear = TRUE; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STA_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStaStatistics, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_STA_STATISTICS_T), + (PUINT_8)&rQueryCmdStaStatistics, + pvQueryBuffer, u4QueryBufferLen); + + prQueryStaStatistics->u4Flag |= BIT(1); + } else { + rResult = WLAN_STATUS_NOT_SUPPORTED; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + +/* 4 Auto Channel Selection */ +WLAN_STATUS +wlanoidQueryACSChannelList(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + /* P_PARAM_GET_CHN_LOAD prQueryChnLoad; */ + P_PARAM_GET_LTE_MODE prLteMode; + CMD_GET_LTE_SAFE_CHN_T rQuery_LTE_SAFE_CHN; + + DBGLOG(P2P, INFO, "[Auto Channel]wlanoidQueryACSChannelList\n"); + do { + ASSERT(pvQueryBuffer); + + /* 4 1. Sanity test */ + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + prLteMode = (P_PARAM_GET_LTE_MODE) pvQueryBuffer; + + /* 4 3. Ensure FW supports get station link status */ +#if 0 + if (prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) { + CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = 0xFFFFFFFF; + rCmdAccessReg.u4Data = ELEM_RM_TYPE_ACS_CHN; + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + TRUE, + TRUE, + /* The handler to receive firmware notification */ + nicCmdEventQueryChannelLoad, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8)&rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); + + prQueryChnLoad->u4Flag |= BIT(1); + } else { + rResult = WLAN_STATUS_NOT_SUPPORTED; + } +#endif + /* 4 4.Avoid LTE Channels */ + prLteMode->u4Flags &= BIT(0); + /*if(prAdapter->u4FwCompileFlag0 & COMPILE_FLAG0_GET_STA_LINK_STATUS) */ { + + rResult = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LTE_CHN, + FALSE, + TRUE, + /* Query ID */ + TRUE, + /* The handler to receive firmware notification */ + nicCmdEventQueryLTESafeChn, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_LTE_SAFE_CHN_T), + (PUINT_8)&rQuery_LTE_SAFE_CHN, + pvQueryBuffer, u4QueryBufferLen); + + DBGLOG(P2P, INFO, "[Auto Channel] Get LTE Channels\n"); + prLteMode->u4Flags |= BIT(1); + } + + /* 4 5. Calc the value */ + + DBGLOG(P2P, INFO, "[Auto Channel] Candidated Channels\n"); + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ +#endif +#if CFG_SUPPORT_CFG_FILE + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 i; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucKey); + + prWlanCfgEntry = NULL; + + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] != '\0') { + DBGLOG(INIT, LOUD, "compare key %s saved key %s\n", pucKey, prWlanCfgEntry->aucKey); + if (kalStrniCmp(pucKey, prWlanCfgEntry->aucKey, WLAN_CFG_KEY_LEN_MAX - 1) == 0) + return prWlanCfgEntry; + } + } + + DBGLOG(INIT, LOUD, "wifi config there is no entry \'%s\'\n", pucKey); + return NULL; + +} + +WLAN_STATUS wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + ASSERT(pucValue); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + kalStrnCpy(pucValue, prWlanCfgEntry->aucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_SUCCESS; + } + if (pucValueDef) + kalStrnCpy(pucValue, pucValueDef, WLAN_CFG_VALUE_LEN_MAX - 1); + return WLAN_STATUS_FAILURE; + +} + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4Value; + INT_32 u4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + u4Value = u4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + u4Ret = kalkStrtou32(prWlanCfgEntry->aucValue, 0, &u4Value); + if (u4Ret) + DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue u4Ret=%u\n", u4Ret); + /* u4Value = kalStrtoul(prWlanCfgEntry->aucValue, NULL, 0); */ + } + + return u4Value; +} + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef) +{ + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + INT_32 i4Value; + INT_32 i4Ret; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + i4Value = i4ValueDef; + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + i4Ret = kalkStrtos32(prWlanCfgEntry->aucValue, 0, &i4Value); + /* i4Ret = kalStrtol(prWlanCfgEntry->aucValue, NULL, 0); */ + if (i4Ret) + DBGLOG(INIT, ERROR, "parse prWlanCfgEntry->aucValue i4Ret=%u\n\r", i4Ret); + } + + return i4Value; +} + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + UINT_32 u4EntryIndex; + UINT_32 i; + UINT_8 ucExist; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + ASSERT(pucKey); + + /* Find the exist */ + ucExist = 0; + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (!prWlanCfgEntry) { + /* Find the empty */ + for (i = 0; i < WLAN_CFG_ENTRY_NUM_MAX; i++) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[i]; + if (prWlanCfgEntry->aucKey[0] == '\0') + break; + } + + u4EntryIndex = i; + if (u4EntryIndex < WLAN_CFG_ENTRY_NUM_MAX) { + prWlanCfgEntry = &prWlanCfg->arWlanCfgBuf[u4EntryIndex]; + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } else { + prWlanCfgEntry = NULL; + DBGLOG(INIT, ERROR, "wifi config there is no empty entry\n"); + } + } /* !prWlanCfgEntry */ + else + ucExist = 1; + + if (prWlanCfgEntry) { + if (ucExist == 0) { + kalStrnCpy(prWlanCfgEntry->aucKey, pucKey, WLAN_CFG_KEY_LEN_MAX - 1); + prWlanCfgEntry->aucKey[WLAN_CFG_KEY_LEN_MAX - 1] = '\0'; + } + + if (pucValue && pucValue[0] != '\0') { + kalStrnCpy(prWlanCfgEntry->aucValue, pucValue, WLAN_CFG_VALUE_LEN_MAX - 1); + prWlanCfgEntry->aucValue[WLAN_CFG_VALUE_LEN_MAX - 1] = '\0'; + + if (ucExist) { + if (prWlanCfgEntry->pfSetCb) + prWlanCfgEntry->pfSetCb(prAdapter, + prWlanCfgEntry->aucKey, + prWlanCfgEntry->aucValue, prWlanCfgEntry->pPrivate, 0); + } + } else { + /* Call the pfSetCb if value is empty ? */ + /* remove the entry if value is empty */ + kalMemZero(prWlanCfgEntry, sizeof(WLAN_CFG_ENTRY_T)); + } + + } + /* prWlanCfgEntry */ + if (prWlanCfgEntry) { + DBGLOG(INIT, LOUD, "Set wifi config exist %u \'%s\' \'%s\'\n", + ucExist, prWlanCfgEntry->aucKey, prWlanCfgEntry->aucValue); + return WLAN_STATUS_SUCCESS; + } + if (pucKey) + DBGLOG(INIT, ERROR, "Set wifi config error key \'%s\'\n", pucKey); + if (pucValue) + DBGLOG(INIT, ERROR, "Set wifi config error value \'%s\'\n", pucValue); + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags) +{ + + P_WLAN_CFG_ENTRY_T prWlanCfgEntry; + P_WLAN_CFG_T prWlanCfg; + + prWlanCfg = prAdapter->prWlanCfg; + ASSERT(prWlanCfg); + + /* Find the exist */ + prWlanCfgEntry = wlanCfgGetEntry(prAdapter, pucKey); + + if (prWlanCfgEntry) { + prWlanCfgEntry->pfSetCb = pfSetCb; + prWlanCfgEntry->pPrivate = pPrivate; + } + + if (prWlanCfgEntry) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; + +} + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value) +{ + + P_WLAN_CFG_T prWlanCfg; + UINT_8 aucBuf[WLAN_CFG_VALUE_LEN_MAX]; + + prWlanCfg = prAdapter->prWlanCfg; + + ASSERT(prWlanCfg); + + kalMemZero(aucBuf, sizeof(aucBuf)); + + kalSnprintf(aucBuf, WLAN_CFG_VALUE_LEN_MAX, "0x%x", (unsigned int)u4Value); + + return wlanCfgSet(prAdapter, pucKey, aucBuf, 0); +} + +enum { + STATE_EOF = 0, + STATE_TEXT = 1, + STATE_NEWLINE = 2 +}; + +struct WLAN_CFG_PARSE_STATE_S { + CHAR *ptr; + CHAR *text; + INT_32 nexttoken; + UINT_32 maxSize; +}; + +INT_32 wlanCfgFindNextToken(struct WLAN_CFG_PARSE_STATE_S *state) +{ + CHAR *x = state->ptr; + CHAR *s; + + if (state->nexttoken) { + INT_32 t = state->nexttoken; + + state->nexttoken = 0; + return t; + } + + for (;;) { + switch (*x) { + case 0: + state->ptr = x; + return STATE_EOF; + case '\n': + x++; + state->ptr = x; + return STATE_NEWLINE; + case ' ': + case '\t': + case '\r': + x++; + continue; + case '#': + while (*x && (*x != '\n')) + x++; + if (*x == '\n') { + state->ptr = x + 1; + return STATE_NEWLINE; + } + state->ptr = x; + return STATE_EOF; + default: + goto text; + } + } + +textdone: + state->ptr = x; + *s = 0; + return STATE_TEXT; +text: + state->text = s = x; +textresume: + for (;;) { + switch (*x) { + case 0: + goto textdone; + case ' ': + case '\t': + case '\r': + x++; + goto textdone; + case '\n': + state->nexttoken = STATE_NEWLINE; + x++; + goto textdone; + case '"': + x++; + for (;;) { + switch (*x) { + case 0: + /* unterminated quoted thing */ + state->ptr = x; + return STATE_EOF; + case '"': + x++; + goto textresume; + default: + *s++ = *x++; + } + } + break; + case '\\': + x++; + switch (*x) { + case 0: + goto textdone; + case 'n': + *s++ = '\n'; + break; + case 'r': + *s++ = '\r'; + break; + case 't': + *s++ = '\t'; + break; + case '\\': + *s++ = '\\'; + break; + case '\r': + /* \ -> line continuation */ + if (x[1] != '\n') { + x++; + continue; + } + case '\n': + /* \ -> line continuation */ + x++; + /* eat any extra whitespace */ + while ((*x == ' ') || (*x == '\t')) + x++; + continue; + default: + /* unknown escape -- just copy */ + *s++ = *x++; + } + continue; + default: + *s++ = *x++; + } + } + return STATE_EOF; +} + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]) +{ + struct WLAN_CFG_PARSE_STATE_S state; + CHAR **args; + INT_32 nargs; + + if (cmdLine == NULL || argc == NULL || argv == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + args = argv; + nargs = 0; + state.ptr = cmdLine; + state.nexttoken = 0; + state.maxSize = 0; + + if (kalStrnLen(cmdLine, 512) >= 512) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + goto exit; + case STATE_NEWLINE: + goto exit; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + *argc = nargs; + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanCfgParseAddEntry(IN P_ADAPTER_T prAdapter, + PUINT_8 pucKeyHead, PUINT_8 pucKeyTail, PUINT_8 pucValueHead, PUINT_8 pucValueTail) +{ + + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + UINT_32 u4Len; + + kalMemZero(aucKey, sizeof(aucKey)); + kalMemZero(aucValue, sizeof(aucValue)); + + if ((pucKeyHead == NULL) + || (pucValueHead == NULL) + ) + return WLAN_STATUS_FAILURE; + + if (pucKeyTail) { + if (pucKeyHead > pucKeyTail) + return WLAN_STATUS_FAILURE; + u4Len = pucKeyTail - pucKeyHead + 1; + } else + u4Len = kalStrnLen(pucKeyHead, WLAN_CFG_KEY_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_KEY_LEN_MAX) + u4Len = WLAN_CFG_KEY_LEN_MAX - 1; + + if (u4Len < WLAN_CFG_VALUE_LEN_MAX) + kalStrnCpy(aucKey, pucKeyHead, u4Len); + else + DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); + + if (pucValueTail) { + if (pucValueHead > pucValueTail) + return WLAN_STATUS_FAILURE; + u4Len = pucValueTail - pucValueHead + 1; + } else + u4Len = kalStrnLen(pucValueHead, WLAN_CFG_VALUE_LEN_MAX - 1); + + if (u4Len >= WLAN_CFG_VALUE_LEN_MAX) + u4Len = WLAN_CFG_VALUE_LEN_MAX - 1; + + if (u4Len < WLAN_CFG_VALUE_LEN_MAX) + kalStrnCpy(aucValue, pucValueHead, u4Len); + else + DBGLOG(INIT, ERROR, "wifi entry parse error: Data len > %d\n", u4Len); + + return wlanCfgSet(prAdapter, aucKey, aucValue, 0); +} + +enum { + WAIT_KEY_HEAD = 0, + WAIT_KEY_TAIL, + WAIT_VALUE_HEAD, + WAIT_VALUE_TAIL, + WAIT_COMMENT_TAIL +}; + +WLAN_STATUS wlanCfgParse(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen) +{ + + struct WLAN_CFG_PARSE_STATE_S state; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + CHAR **args; + INT_32 nargs; + + if (pucConfigBuf == NULL) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (kalStrnLen(pucConfigBuf, 4000) >= 4000) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + if (u4ConfigBufLen == 0) + return WLAN_STATUS_FAILURE; + args = apcArgv; + nargs = 0; + state.ptr = pucConfigBuf; + state.nexttoken = 0; + state.maxSize = u4ConfigBufLen; + + for (;;) { + switch (wlanCfgFindNextToken(&state)) { + case STATE_EOF: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + goto exit; + case STATE_NEWLINE: + if (nargs > 1) + wlanCfgParseAddEntry(prAdapter, args[0], NULL, args[1], NULL); + nargs = 0; + break; + case STATE_TEXT: + if (nargs < WLAN_CFG_ARGV_MAX) + args[nargs++] = state.text; + break; + } + } + +exit: + return WLAN_STATUS_SUCCESS; + +#if 0 + /* Old version */ + UINT_32 i; + UINT_8 c; + PUINT_8 pbuf; + UINT_8 ucState; + PUINT_8 pucKeyTail = NULL; + PUINT_8 pucKeyHead = NULL; + PUINT_8 pucValueHead = NULL; + PUINT_8 pucValueTail = NULL; + + ucState = WAIT_KEY_HEAD; + pbuf = pucConfigBuf; + + for (i = 0; i < u4ConfigBufLen; i++) { + c = pbuf[i]; + if (c == '\r' || c == '\n') { + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueHead) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, + pucValueHead, pucValueTail); + } + ucState = WAIT_KEY_HEAD; + pucKeyTail = NULL; + pucKeyHead = NULL; + pucValueHead = NULL; + pucValueTail = NULL; + + } else if (c == '=') { + if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else if (c == ' ' || c == '\t') { + if (ucState == WAIT_KEY_HEAD) + ; + else if (ucState == WAIT_KEY_TAIL) { + pucKeyTail = &pbuf[i - 1]; + ucState = WAIT_VALUE_HEAD; + } + } else { + + if (c == '#') { + /* comments */ + if (ucState == WAIT_KEY_HEAD) + ucState = WAIT_COMMENT_TAIL; + else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + + } else { + if (ucState == WAIT_KEY_HEAD) { + pucKeyHead = &pbuf[i]; + pucKeyTail = &pbuf[i]; + ucState = WAIT_KEY_TAIL; + } else if (ucState == WAIT_VALUE_HEAD) { + pucValueHead = &pbuf[i]; + pucValueTail = &pbuf[i]; + ucState = WAIT_VALUE_TAIL; + } else if (ucState == WAIT_VALUE_TAIL) + pucValueTail = &pbuf[i]; + } + } + + } /* for */ + + if (ucState == WAIT_VALUE_TAIL) { + /* Entry found */ + if (pucValueTail) + wlanCfgParseAddEntry(prAdapter, pucKeyHead, pucKeyTail, pucValueHead, pucValueTail); + } +#endif + + return WLAN_STATUS_SUCCESS; +} +#endif + +#if CFG_SUPPORT_CFG_FILE +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags) +{ + P_WLAN_CFG_T prWlanCfg; + /* P_WLAN_CFG_ENTRY_T prWlanCfgEntry; */ + prAdapter->prWlanCfg = &prAdapter->rWlanCfg; + prWlanCfg = prAdapter->prWlanCfg; + + kalMemZero(prWlanCfg, sizeof(WLAN_CFG_T)); + ASSERT(prWlanCfg); + prWlanCfg->u4WlanCfgEntryNumMax = WLAN_CFG_ENTRY_NUM_MAX; + prWlanCfg->u4WlanCfgKeyLenMax = WLAN_CFG_KEY_LEN_MAX; + prWlanCfg->u4WlanCfgValueLenMax = WLAN_CFG_VALUE_LEN_MAX; +#if 0 + DBGLOG(INIT, INFO, "Init wifi config len %u max entry %u\n", u4ConfigBufLen, prWlanCfg->u4WlanCfgEntryNumMax); +#endif + /* self test */ + wlanCfgSet(prAdapter, "ConfigValid", "0x123", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 0x123) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); + wlanCfgSet(prAdapter, "ConfigValid", "1", 0); + if (wlanCfgGetUint32(prAdapter, "ConfigValid", 0) != 1) + DBGLOG(INIT, ERROR, "wifi config error %u\n", __LINE__); +#if 0 /* soc chip didn't support these parameters now */ + /* Add initil config */ + /* use g,wlan,p2p,ap as prefix */ + /* Don't set cb here , overwrite by another api */ + wlanCfgSet(prAdapter, "TxLdpc", "1", 0); + wlanCfgSet(prAdapter, "RxLdpc", "1", 0); + wlanCfgSet(prAdapter, "RxBeamformee", "1", 0); + wlanCfgSet(prAdapter, "RoamTh1", "100", 0); + wlanCfgSet(prAdapter, "RoamTh2", "150", 0); + wlanCfgSet(prAdapter, "wlanRxLdpc", "1", 0); + wlanCfgSet(prAdapter, "apRxLdpc", "1", 0); + wlanCfgSet(prAdapter, "p2pRxLdpc", "1", 0); +#endif + /* Parse the pucConfigBuff */ + + if (pucConfigBuf && (u4ConfigBufLen > 0)) + wlanCfgParse(prAdapter, pucConfigBuf, u4ConfigBufLen); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to initialize WLAN feature options +* +* @param prAdapter Pointer of ADAPTER_T +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanCfgApply(IN P_ADAPTER_T prAdapter) +{ +#define STR2BYTE(s) (((((PUINT_8)s)[0]-'0')*10)+(((PUINT_8)s)[1]-'0')) + CHAR aucValue[WLAN_CFG_VALUE_LEN_MAX]; + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + P_REG_INFO_T prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + P_TX_PWR_PARAM_T prTxPwr = &prRegInfo->rTxPwr; + + kalMemZero(aucValue, sizeof(aucValue)); + DBGLOG(INIT, LOUD, "CFG_FILE: Apply Config File\n"); + /* Apply COUNTRY Config */ + if (wlanCfgGet(prAdapter, "country", aucValue, "", 0) == WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, LOUD, "CFG_FILE: Found Country Key, Value=%s\n", aucValue); + prAdapter->rWifiVar.rConnSettings.u2CountryCode = + (((UINT_16) aucValue[0]) << 8) | ((UINT_16) aucValue[1]); + prRegInfo->au2CountryCode[0] = aucValue[0]; + prRegInfo->au2CountryCode[1] = aucValue[1]; + } + prWifiVar->ucApWpsMode = (UINT_8) wlanCfgGetUint32(prAdapter, "ApWpsMode", 0); + prWifiVar->ucCert11nMode = (UINT_8)wlanCfgGetUint32(prAdapter, "Cert11nMode", 0); + DBGLOG(INIT, LOUD, "CFG_FILE: ucApWpsMode = %u, ucCert11nMode = %u\n", + prWifiVar->ucApWpsMode, prWifiVar->ucCert11nMode); + if (prWifiVar->ucCert11nMode == 1) + nicWriteMcr(prAdapter, 0x11111115 , 1); + + if (wlanCfgGet(prAdapter, "5G_support", aucValue, "", 0) == WLAN_STATUS_SUCCESS) + prRegInfo->ucSupport5GBand = (*aucValue == 'y') ? 1 : 0; + if (wlanCfgGet(prAdapter, "TxPower2G4CCK", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 2) { + prTxPwr->cTxPwr2G4Cck = STR2BYTE(aucValue); + DBGLOG(INIT, LOUD, "2.4G cck=%d\n", prTxPwr->cTxPwr2G4Cck); + } + if (wlanCfgGet(prAdapter, "TxPower2G4OFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 10) { + prTxPwr->cTxPwr2G4OFDM_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4OFDM_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4OFDM_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4OFDM_48Mbps = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4OFDM_54Mbps = STR2BYTE(aucValue + 8); + DBGLOG(INIT, LOUD, "2.4G OFDM=%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4OFDM_BPSK, prTxPwr->cTxPwr2G4OFDM_QPSK, + prTxPwr->cTxPwr2G4OFDM_16QAM, prTxPwr->cTxPwr2G4OFDM_48Mbps, + prTxPwr->cTxPwr2G4OFDM_54Mbps); + } + if (wlanCfgGet(prAdapter, "TxPower2G4HT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr2G4HT20_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4HT20_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4HT20_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4HT20_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4HT20_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr2G4HT20_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "2.4G HT20=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4HT20_BPSK, prTxPwr->cTxPwr2G4HT20_QPSK, + prTxPwr->cTxPwr2G4HT20_16QAM, prTxPwr->cTxPwr2G4HT20_MCS5, + prTxPwr->cTxPwr2G4HT20_MCS6, prTxPwr->cTxPwr2G4HT20_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower2G4HT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS && + kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr2G4HT40_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr2G4HT40_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr2G4HT40_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr2G4HT40_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr2G4HT40_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr2G4HT40_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "2.4G HT40=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr2G4HT40_BPSK, prTxPwr->cTxPwr2G4HT40_QPSK, + prTxPwr->cTxPwr2G4HT40_16QAM, prTxPwr->cTxPwr2G4HT40_MCS5, + prTxPwr->cTxPwr2G4HT40_MCS6, prTxPwr->cTxPwr2G4HT40_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower5GOFDM", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 10) { + prTxPwr->cTxPwr5GOFDM_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GOFDM_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GOFDM_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GOFDM_48Mbps = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GOFDM_54Mbps = STR2BYTE(aucValue + 8); + DBGLOG(INIT, LOUD, "5G OFDM=%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GOFDM_BPSK, prTxPwr->cTxPwr5GOFDM_QPSK, + prTxPwr->cTxPwr5GOFDM_16QAM, prTxPwr->cTxPwr5GOFDM_48Mbps, + prTxPwr->cTxPwr5GOFDM_54Mbps); + } + if (wlanCfgGet(prAdapter, "TxPower5GHT20", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr5GHT20_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GHT20_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GHT20_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GHT20_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GHT20_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr5GHT20_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "5G HT20=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GHT20_BPSK, prTxPwr->cTxPwr5GHT20_QPSK, + prTxPwr->cTxPwr5GHT20_16QAM, prTxPwr->cTxPwr5GHT20_MCS5, prTxPwr->cTxPwr5GHT20_MCS6, + prTxPwr->cTxPwr5GHT20_MCS7); + } + if (wlanCfgGet(prAdapter, "TxPower5GHT40", aucValue, "", 0) == WLAN_STATUS_SUCCESS + && kalStrLen(aucValue) == 12) { + prTxPwr->cTxPwr5GHT40_BPSK = STR2BYTE(aucValue); + prTxPwr->cTxPwr5GHT40_QPSK = STR2BYTE(aucValue + 2); + prTxPwr->cTxPwr5GHT40_16QAM = STR2BYTE(aucValue + 4); + prTxPwr->cTxPwr5GHT40_MCS5 = STR2BYTE(aucValue + 6); + prTxPwr->cTxPwr5GHT40_MCS6 = STR2BYTE(aucValue + 8); + prTxPwr->cTxPwr5GHT40_MCS7 = STR2BYTE(aucValue + 10); + DBGLOG(INIT, LOUD, "5G HT40=%d,%d,%d,%d,%d,%d\n", + prTxPwr->cTxPwr5GHT40_BPSK, prTxPwr->cTxPwr5GHT40_QPSK, + prTxPwr->cTxPwr5GHT40_16QAM, prTxPwr->cTxPwr5GHT40_MCS5, prTxPwr->cTxPwr5GHT40_MCS6, + prTxPwr->cTxPwr5GHT40_MCS7); + } + /* TODO: Apply other Config */ +} +#endif /* CFG_SUPPORT_CFG_FILE */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c new file mode 100644 index 0000000000000..993ff061ed203 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_oid.c @@ -0,0 +1,11050 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/common/wlan_oid.c#5 +*/ + +/*! \file wlanoid.c + \brief This file contains the WLAN OID processing routines of Windows driver for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_oid.c +** +** 09 05 2013 cp.wu +** isolate logic regarding roaming & reassociation +** +** 09 03 2013 cp.wu +** add path for reassociation +** +** 09 02 2013 cp.wu +** add path to handle reassociation request +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * using the wlanSendSetQueryCmd to set the tx power control cmd. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * change the set tx power cmd name. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 12 20 2011 cp.wu + * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information + * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO + * to expose version information + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to + * asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state + * without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 21 2011 cp.wu + * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing + * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer + * add more checking for such cases + * + * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. + * add some tweaking to protect such cases because that net device has become invalid. + * + * 11 15 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 11 09 2011 george.huang + * [WCXRP00000871] [MT6620 Wi-Fi][FW] Include additional wakeup condition, which is by + * consequent DTIM unicast indication add XLOG for Set PS mode entry + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 11 02 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add RDD certification features. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 15 2011 tsaiyuan.hsu + * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA + * correct fifo full control from query to set operation for CTIA. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 17 2011 tsaiyuan.hsu + * [WCXRP00000938] [MT6620 Wi-Fi][FW] add system config for CTIA + * add system config for CTIA. + * + * 08 15 2011 george.huang + * [MT6620 Wi-Fi][FW] handle TSF drift for connection detection + * . + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, + * for customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 05 02 2011 eddie.chen + * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control + * Fix compile warning. + * + * 04 29 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * . + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * add more debug message + * + * 04 26 2011 eddie.chen + * [WCXRP00000373] [MT6620 Wi-Fi][FW] SW debug control + * Add rx path profiling. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 31 2011 puff.wen + * NULL + * . + * + * 03 29 2011 puff.wen + * NULL + * Add chennel switch for stress test + * + * 03 29 2011 cp.wu + * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning + * surpress klock warning with code path rewritten + * + * 03 24 2011 wh.su + * [WCXRP00000595] [MT6620 Wi-Fi][Driver] at CTIA indicate disconnect to make the ps profile can apply + * use disconnect event instead of ais abort for CTIA testing. + * + * 03 23 2011 george.huang + * [WCXRP00000586] [MT6620 Wi-Fi][FW] Modify for blocking absence request right after connected + * revise for CTIA power mode setting + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 17 2011 yarco.yang + * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage + * . + * + * 03 15 2011 george.huang + * [WCXRP00000557] [MT6620 Wi-Fi] Support current consumption test mode commands + * Support current consumption measurement mode command + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 04 2011 cp.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * surpress compile warning occurred when compiled by GNU compiler collection. + * + * 03 03 2011 wh.su + * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue + * fixed the enter ctia test mode issue. + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Update sigma CAPI for U-APSD setting + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as + * initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 01 27 2011 george.huang + * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting + * Support CTIA power mode setting. + * + * 01 26 2011 wh.su + * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux + * adding the SW cmd ioctl support, use set/get structure ioctl. + * + * 01 25 2011 cp.wu + * [WCXRP00000394] [MT6620 Wi-Fi][Driver] Count space needed for generating error message in + * scanning list into buffer size checking + * when doing size prechecking, check illegal MAC address as well + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cp.wu + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * check if allow to switch to IBSS mode via concurrent module before setting to IBSS mode + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 01 04 2011 cp.wu + * [WCXRP00000342] [MT6620 Wi-Fi][Driver] show error code in scanning list when MAC address is not + * correctly configured in NVRAM + * show error code 0x10 when MAC address in NVRAM is not configured correctly. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations + * to ease physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 28 2010 george.huang + * [WCXRP00000232] [MT5931 Wi-Fi][FW] Modifications for updated HW power on sequence and related design + * support WMM-PS U-APSD AC assignment. + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 16 2010 cp.wu + * [WCXRP00000268] [MT6620 Wi-Fi][Driver] correction for WHQL failed items + * correction for OID_802_11_NETWORK_TYPES_SUPPORTED handlers + * + * 12 13 2010 cp.wu + * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork + * suppress warning reported by Klockwork. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 30 2010 cp.wu + * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 + * . + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only + * with necessary data field checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available + * but extra scan result used to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 21 2010 wh.su + * [WCXRP00000192] [MT6620 Wi-Fi][Driver] Fixed fail trying to build connection with Security + * AP while enable WAPI message check + * Not set the wapi mode while the wapi assoc info set non-wapi ie. + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying + * current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 22 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * dos2unix conversion. + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version + * Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android complete + * implementation of Android NVRAM access + * + * 10 06 2010 yuche.tsai + * NULL + * Update SLT 5G Test Channel Set. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 06 2010 yuche.tsai + * NULL + * Update For SLT 5G Test Channel Selection Rule. + * + * 10 05 2010 cp.wu + * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form + * Query buffer size needs to be enlarged due to result is filled in 4-bytes alignment boundary + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and + * replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions + * + * 10 04 2010 cp.wu + * [WCXRP00000075] [MT6620 Wi-Fi][Driver] Fill query buffer for OID_802_11_BSSID_LIST in 4-bytes aligned form + * Extend result length to multiples of 4-bytes + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Update SLT due to API change of SCAN module. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 yuche.tsai + * NULL + * Refine SLT IO control handler. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 chinglan.wang + * NULL + * Modify the rescan condition. + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 27 2010 chinglan.wang + * NULL + * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 16 2010 george.huang + * NULL + * . + * + * 08 16 2010 george.huang + * NULL + * update params defined in CMD_SET_NETWORK_ADDRESS_LIST + * + * 08 04 2010 cp.wu + * NULL + * fix for check build WHQL testing: + * 1) do not assert query buffer if indicated buffer length is zero + * 2) sdio.c has bugs which cause freeing same pointer twice + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 04 2010 cp.wu + * NULL + * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. + * + * 08 04 2010 cp.wu + * NULL + * bypass u4FuncData for RF-Test query request as well. + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 26 2010 cp.wu + * + * re-commit code logic being overwriten. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 20 2010 cp.wu + * + * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one + * 2) refine disconnection behaviour when issued during BG-SCAN process + * + * 07 19 2010 wh.su + * + * modify the auth and encry status variable. + * + * 07 16 2010 cp.wu + * + * remove work-around in case SCN is not available. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. + * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add SCN compilation option. + * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement SCAN-REQUEST oid as mailbox message dispatching. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * adding the compiling flag for oid pmkid. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 28 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * simplify cmd packet sending for RF test and MCR access OIDs + * + * 05 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable radio even when STA is not associated. + * + * 05 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct 2 OID behaviour to meet WHQL requirement. + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power management macro + * + * 05 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct BSSID_LIST oid when radio if turned off. + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll + * 2) correct address list parsing + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * disable wlanoidSetNetworkAddress() temporally. + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * some OIDs should be DRIVER_CORE instead of GLUE_EXTENSION + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. + * 2) finish statistics OIDs + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct wlanoidSet802dot11PowerSaveProfile implementation. + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) enable CMD/EVENT ver 0.9 definition. + * 2) abandon use of ENUM_MEDIA_STATE + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add dissassocation support for wpa supplicant + * + * 05 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct return value. + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * for disassociation, still use parameter with current setting. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * for disassociation, generate a WZC-compatible invalid SSID. + * + * 05 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * associate to illegal SSID when handling OID_802_11_DISASSOCIATE + * + * 04 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * reserve field of privacy filter and RTS threshold setting. + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 04 22 2010 cp.wu + * [WPD00003830]add OID_802_11_PRIVACY_FILTER support + * enable RX filter OID + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add ioctl of power management + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * 2) command sequence number is now increased atomically + * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_CONFIGURATION query for infrastructure mode. + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) remove unused spin lock declaration + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * are done in adapter layer. + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)improve none-glue code portability + * (2) disable set Multicast address during atomic context + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve glue code portability + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * the frequency is used for adhoc connection only + * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * + * + * 03 22 2010 cp.wu + * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list + * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result + * + * 03 19 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * adding the check for pass WHQL test item. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * +* 03 16 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * fixed some whql pre-test fail case. + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. + * + * 02 24 2010 wh.su + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Don't needed to check the auth mode, WHQL testing not specific at auth wpa2. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not check SSID validity anymore. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * 2. follow MSDN defined behavior when associates to another AP + * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move ucCmdSeqNum as instance variable + * + * 02 04 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when OID_CUSTOM_OID_INTERFACE_VERSION is queried, do modify connection states + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * 2. block TX/ordinary OID when RF test mode is engaged + * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * 4. correct some HAL implementation + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * OID_802_11_RSSI, + * OID_802_11_RSSI_TRIGGER, + * OID_802_11_STATISTICS, + * OID_802_11_DISASSOCIATE, + * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not fill ucJoinOnly currently + * + * 01 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable to connect to ad-hoc network + * + * 01 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * .implement Set/Query BeaconInterval/AtimWindow + * + * 01 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * .Set/Get AT Info is not blocked even when driver is not in fg test mode + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * and result is retrieved by get ATInfo instead + * 2) add 4 counter for recording aggregation statistics + * + * 12 28 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate redundant variables for connection_state +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-12-16 22:13:36 GMT mtk02752 +** change hard-coded MAC address to match with FW (temporally) +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-12-10 16:49:50 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-12-08 17:38:49 GMT mtk02752 +** + add OID for RF test +** * MCR RD/WR are modified to match with cmd/event definition +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-12-08 11:32:20 GMT mtk02752 +** add skeleton for RF test implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-12-03 16:43:24 GMT mtk01461 +** Modify query SCAN list oid by adding prEventScanResult +** +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-03 16:39:27 GMT mtk01461 +** Sync CMD data structure in set ssid oid +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-03 16:28:22 GMT mtk01461 +** Add invalid check of set SSID oid and fix query scan list oid +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-30 17:33:08 GMT mtk02752 +** implement wlanoidSetInfrastructureMode/wlanoidQueryInfrastructureMode +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-30 10:53:49 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-30 09:22:48 GMT mtk02752 +** correct wifi cmd length mismatch +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-25 21:34:33 GMT mtk02752 +** sync EVENT_SCAN_RESULT_T with firmware +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 21:03:27 GMT mtk02752 +** implement wlanoidQueryBssidList() +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-25 18:17:17 GMT mtk02752 +** refine GL_WLAN_INFO_T for buffering scan result +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-23 20:28:51 GMT mtk02752 +** some OID will be set to WLAN_STATUS_PENDING until it is sent via wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-23 17:56:36 GMT mtk02752 +** implement wlanoidSetBssidListScan(), wlanoidSetBssid() and wlanoidSetSsid() +** +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-13 17:20:53 GMT mtk02752 +** add Set BSSID/SSID path but disabled temporally due to FW is not ready yet +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 12:28:58 GMT mtk02752 +** add wlanoidSetBssidListScan -> cmd_info path +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-09 22:48:07 GMT mtk01084 +** modify test cases entry +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-04 14:10:58 GMT mtk01084 +** add new test interfaces +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-30 18:17:10 GMT mtk01084 +** fix compiler warning +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:46:26 GMT mtk01084 +** add test functions +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:07:56 GMT mtk01084 +** include new file +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:29 GMT mtk01084 +** modify for new HW architecture +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-02 13:48:49 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-09-09 17:26:04 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-21 12:09:50 GMT mtk01461 +** Update for MCR Write OID +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:35:18 GMT mtk01461 +** Update wlanoidQueryMcrRead() for composing CMD_INFO_T +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 18:09:51 GMT mtk01426 +** Remove kalIndicateStatusAndComplete() in wlanoidQueryOidInterfaceVersion() +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-14 15:51:50 GMT mtk01426 +** Add MCR read/write support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:40 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:06:31 GMT mtk01426 +** Init for develop +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "mgmt/rsn.h" + +#include + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +#if CFG_ENABLE_STATISTICS_BUFFERING +static BOOLEAN IsBufferedStatisticsUsable(P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + if (prAdapter->fgIsStatValid == TRUE && + (kalGetTimeTick() - prAdapter->rStatUpdateTime) <= CFG_STATISTICS_VALID_CYCLE) + return TRUE; + else + return FALSE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the supported physical layer network +* type that can be used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + UINT_32 u4NumItem = 0; + ENUM_PARAM_NETWORK_TYPE_T eSupportedNetworks[PARAM_NETWORK_TYPE_NUM]; + PPARAM_NETWORK_TYPE_LIST prSupported; + + /* The array of all physical layer network subtypes that the driver supports. */ + + DEBUGFUNC("wlanoidQueryNetworkTypesSupported"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + /* Init. */ + for (u4NumItem = 0; u4NumItem < PARAM_NETWORK_TYPE_NUM; u4NumItem++) + eSupportedNetworks[u4NumItem] = 0; + + u4NumItem = 0; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_DS; + u4NumItem++; + + eSupportedNetworks[u4NumItem] = PARAM_NETWORK_TYPE_OFDM24; + u4NumItem++; + + *pu4QueryInfoLen = + (UINT_32) OFFSET_OF(PARAM_NETWORK_TYPE_LIST, eNetworkType) + + (u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prSupported = (PPARAM_NETWORK_TYPE_LIST) pvQueryBuffer; + prSupported->NumberOfItems = u4NumItem; + kalMemCopy(prSupported->eNetworkType, eSupportedNetworks, u4NumItem * sizeof(ENUM_PARAM_NETWORK_TYPE_T)); + + DBGLOG(OID, TRACE, "NDIS supported network type list: %u\n", prSupported->NumberOfItems); + DBGLOG_MEM8(OID, TRACE, prSupported, *pu4QueryInfoLen); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypesSupported */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current physical layer network +* type used by the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T rCurrentNetworkTypeInUse = PARAM_NETWORK_TYPE_OFDM24; + + DEBUGFUNC("wlanoidQueryNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkType); + else + rCurrentNetworkTypeInUse = (ENUM_PARAM_NETWORK_TYPE_T) (prAdapter->rWlanInfo.ucNetworkTypeInUse); + + *(P_ENUM_PARAM_NETWORK_TYPE_T) pvQueryBuffer = rCurrentNetworkTypeInUse; + *pu4QueryInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, TRACE, "Network type in use: %d\n", rCurrentNetworkTypeInUse); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the physical layer network type used +* by the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS The given network type is supported and accepted. +* \retval WLAN_STATUS_INVALID_DATA The given network type is not in the +* supported list. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + /* TODO: need to check the OID handler content again!! */ + + ENUM_PARAM_NETWORK_TYPE_T eNewNetworkType; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNetworkTypeInUse"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_NETWORK_TYPE_T)) { + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + return WLAN_STATUS_INVALID_LENGTH; + } + + eNewNetworkType = *(P_ENUM_PARAM_NETWORK_TYPE_T) pvSetBuffer; + *pu4SetInfoLen = sizeof(ENUM_PARAM_NETWORK_TYPE_T); + + DBGLOG(OID, INFO, "New network type: %d mode\n", eNewNetworkType); + + switch (eNewNetworkType) { + + case PARAM_NETWORK_TYPE_DS: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PARAM_NETWORK_TYPE_OFDM5: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + case PARAM_NETWORK_TYPE_OFDM24: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PARAM_NETWORK_TYPE_AUTOMODE: + prAdapter->rWlanInfo.ucNetworkTypeInUse = (UINT_8) PARAM_NETWORK_TYPE_AUTOMODE; + break; + + case PARAM_NETWORK_TYPE_FH: + DBGLOG(OID, INFO, "Not support network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + + default: + DBGLOG(OID, INFO, "Unknown network type: %d\n", eNewNetworkType); + rStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + /* Verify if we support the new network type. */ + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(OID, WARN, "Unknown network type: %d\n", eNewNetworkType); + + return rStatus; +} /* wlanoidSetNetworkTypeInUse */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current BSSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryBssid"); + + ASSERT(prAdapter); + + if (u4QueryBufferLen < MAC_ADDR_LEN) { + ASSERT(pu4QueryInfoLen); + *pu4QueryInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(u4QueryBufferLen >= MAC_ADDR_LEN); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) + kalMemCopy(pvQueryBuffer, prAdapter->rWlanInfo.rCurrBssId.arMacAddress, MAC_ADDR_LEN); + else if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS) { + PARAM_MAC_ADDRESS aucTemp; /*!< BSSID */ + + COPY_MAC_ADDR(aucTemp, prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + aucTemp[0] &= ~BIT(0); + aucTemp[1] |= BIT(1); + COPY_MAC_ADDR(pvQueryBuffer, aucTemp); + } else + rStatus = WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = MAC_ADDR_LEN; + return rStatus; +} /* wlanoidQueryBssid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the list of all BSSIDs detected by +* the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4BssidListExLen; + P_PARAM_BSSID_LIST_EX_T prList; + P_PARAM_BSSID_EX_T prBssidEx; + PUINT_8 cp; + + DEBUGFUNC("wlanoidQueryBssidList"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) { + ASSERT(pvQueryBuffer); + + if (!pvQueryBuffer) + return WLAN_STATUS_INVALID_DATA; + } + + prGlueInfo = prAdapter->prGlueInfo; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in qeury BSSID list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + u4BssidListExLen = 0; + + if (prAdapter->fgIsRadioOff == FALSE) { + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) + u4BssidListExLen += ALIGN_4(prAdapter->rWlanInfo.arScanResult[i].u4Length); + } + + if (u4BssidListExLen) + u4BssidListExLen += 4; /* u4NumberOfItems. */ + else + u4BssidListExLen = sizeof(PARAM_BSSID_LIST_EX_T); + + *pu4QueryInfoLen = u4BssidListExLen; + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* Clear the buffer */ + kalMemZero(pvQueryBuffer, u4BssidListExLen); + + prList = (P_PARAM_BSSID_LIST_EX_T) pvQueryBuffer; + cp = (PUINT_8) &prList->arBssid[0]; + + if (prAdapter->fgIsRadioOff == FALSE && prAdapter->rWlanInfo.u4ScanResultNum > 0) { + /* fill up for each entry */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + prBssidEx = (P_PARAM_BSSID_EX_T) cp; + + /* copy structure */ + kalMemCopy(prBssidEx, + &(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /*For WHQL test, Rssi should be in range -10 ~ -200 dBm */ + if (prBssidEx->rRssi > PARAM_WHQL_RSSI_MAX_DBM) + prBssidEx->rRssi = PARAM_WHQL_RSSI_MAX_DBM; + + if (prAdapter->rWlanInfo.arScanResult[i].u4IELength > 0) { + /* copy IEs */ + kalMemCopy(prBssidEx->aucIEs, + prAdapter->rWlanInfo.apucScanResultIEs[i], + prAdapter->rWlanInfo.arScanResult[i].u4IELength); + } + /* 4-bytes alignement */ + prBssidEx->u4Length = ALIGN_4(prBssidEx->u4Length); + + cp += prBssidEx->u4Length; + prList->u4NumberOfItems++; + } + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryBssidList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SSID_T prSsid; + PARAM_SSID_T rSsid; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetBssidListScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(OID, TRACE, "Scan\n"); + + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, pvSetBuffer, u4SetBufferLen); + prSsid = &rSsid; + } else { + prSsid = NULL; + } + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, NULL, 0); + } else { + /* reject the scan request */ + rStatus = WLAN_STATUS_FAILURE; + } + } + + return rStatus; +} /* wlanoidSetBssidListScan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to perform +* scanning with attaching information elements(IEs) specified from user space +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssidListScanExt(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCAN_REQUEST_EXT_T prScanRequest; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_PARAM_SSID_T prSsid; + PUINT_8 pucIe; + UINT_32 u4IeLength; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 ucScanTime = AIS_SCN_DONE_TIMEOUT_SEC; + + DEBUGFUNC("wlanoidSetBssidListScanExt()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, ERROR, "Fail in set BSSID list scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgTestMode) { + DBGLOG(OID, WARN, "didn't support Scan in test mode\n"); + return WLAN_STATUS_FAILURE; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)) { + DBGLOG(OID, ERROR, "u4SetBufferLen != sizeof(PARAM_SCAN_REQUEST_EXT_T)\n"); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(OID, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(OID, TRACE, "ScanEx\n"); + + /* clear old scan backup results if exists */ + { + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + } + } + } + + if (pvSetBuffer != NULL && u4SetBufferLen != 0) { + prScanRequest = (P_PARAM_SCAN_REQUEST_EXT_T) pvSetBuffer; + prSsid = &(prScanRequest->rSsid); + pucIe = prScanRequest->pucIE; + u4IeLength = prScanRequest->u4IELength; + } else { + prScanRequest = NULL; + prSsid = NULL; + pucIe = NULL; + u4IeLength = 0; + } + +/* P_AIS_FSM_INFO_T prAisFsmInfo; */ + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + +/* #if CFG_SUPPORT_WFD */ +#if 0 + if ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.ucWfdEnable) && + ((prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings.u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, TRACE, "Twice the Scan Time for WFD\n"); + ucScanTime *= 2; + } + } +#endif /* CFG_SUPPORT_WFD */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer, SEC_TO_MSEC(ucScanTime)); + +#if CFG_SUPPORT_RDD_TEST_MODE + if (prAdapter->prGlueInfo->rRegInfo.u4RddTestMode) { + if ((prAdapter->fgEnOnlineScan == TRUE) && (prAdapter->ucRddStatus)) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + } + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + } + } else +#endif + { + if (prAdapter->fgEnOnlineScan == TRUE) { + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + aisFsmScanRequest(prAdapter, prSsid, pucIe, u4IeLength); + } else { + /* reject the scan request */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + rStatus = WLAN_STATUS_FAILURE; + DBGLOG(OID, WARN, "ScanEx fail %d!\n", prAdapter->fgEnOnlineScan); + } + } + + return rStatus; +} /* wlanoidSetBssidListScanWithIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt to associate +* with the specified BSSID. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_UINT_8 pAddr; + UINT_32 i; + INT_32 i4Idx = -1; + P_MSG_AIS_ABORT_T prAisAbortMsg; + UINT_8 ucReasonOfDisconnect; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = MAC_ADDR_LEN; + if (u4SetBufferLen != MAC_ADDR_LEN) { + *pu4SetInfoLen = MAC_ADDR_LEN; + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prGlueInfo = prAdapter->prGlueInfo; + pAddr = (P_UINT_8) pvSetBuffer; + + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } else { + DBGLOG(OID, TRACE, "DisByBssid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else { + ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + + /* check if any scanned result matchs with the BSSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + /* Set Connection Request Issued Flag */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_BSSID; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* Update the information to CONNECTION_SETTINGS_T */ + prAdapter->rWifiVar.rConnSettings.ucSSIDLen = 0; + prAdapter->rWifiVar.rConnSettings.aucSSID[0] = '\0'; + + COPY_MAC_ADDR(prAdapter->rWifiVar.rConnSettings.aucBSSID, pAddr); + + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pAddr)) + prAisAbortMsg->fgDelayIndication = TRUE; + else + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(OID, INFO, "SetBssid\n"); + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBssid() */ + +WLAN_STATUS +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_CONNECT_T pParamConn; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_32 i; + /*INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN;*/ + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + BOOLEAN fgEqualSsid = FALSE; + BOOLEAN fgEqualBssid = FALSE; + const UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen != sizeof(PARAM_CONNECT_T)) + return WLAN_STATUS_INVALID_LENGTH; + else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + + pParamConn = (P_PARAM_CONNECT_T) pvSetBuffer; + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + if (pParamConn->u4SsidLen > 32) { + cnmMemFree(prAdapter, prAisAbortMsg); + return WLAN_STATUS_INVALID_LENGTH; + } else if (!pParamConn->pucBssid && !pParamConn->pucSsid) { + cnmMemFree(prAdapter, prAisAbortMsg); + return WLAN_STATUS_INVALID_LENGTH; + } + + prGlueInfo = prAdapter->prGlueInfo; + kalMemZero(prConnSettings->aucSSID, sizeof(prConnSettings->aucSSID)); + kalMemZero(prConnSettings->aucBSSID, sizeof(prConnSettings->aucBSSID)); + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_ANY; + prConnSettings->fgIsConnByBssidIssued = FALSE; + + if (pParamConn->pucSsid) { + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + COPY_SSID(prConnSettings->aucSSID, + prConnSettings->ucSSIDLen, pParamConn->pucSsid, (UINT_8) pParamConn->u4SsidLen); + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamConn->pucSsid, pParamConn->u4SsidLen)) + fgEqualSsid = TRUE; + } + if (pParamConn->pucBssid) { + if (!EQUAL_MAC_ADDR(aucZeroMacAddr, pParamConn->pucBssid) && IS_UCAST_MAC_ADDR(pParamConn->pucBssid)) { + prConnSettings->eConnectionPolicy = CONNECT_BY_BSSID; + prConnSettings->fgIsConnByBssidIssued = TRUE; + COPY_MAC_ADDR(prConnSettings->aucBSSID, pParamConn->pucBssid); + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, pParamConn->pucBssid)) + fgEqualBssid = TRUE; + } else + DBGLOG(OID, TRACE, "wrong bssid %pM to connect\n", pParamConn->pucBssid); + } else + DBGLOG(OID, TRACE, "No Bssid set\n"); + prConnSettings->u4FreqInKHz = pParamConn->u4CenterFreq; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (fgEqualSsid) { + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_ROAMING; + if (fgEqualBssid) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_REASSOCIATION; + } + } else { + DBGLOG(OID, TRACE, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + } + } else + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; +#if 0 + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamConn->pucSsid, pParamConn->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + if (EQUAL_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, pAddr)) { + i4Idx = (INT_32) i; + break; + } + } +#endif + /* prepare message to AIS */ + if (prConnSettings->eOPMode == NET_TYPE_IBSS || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prConnSettings->u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prConnSettings->u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamConn->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (pParamConn->pucSsid) { + if (!((0 < pParamConn->pucSsid[i]) && (pParamConn->pucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) + prConnSettings->fgIsConnReqIssued = TRUE; + else + prConnSettings->fgIsConnReqIssued = FALSE; + + if (fgEqualSsid || fgEqualBssid) + prAisAbortMsg->fgDelayIndication = TRUE; + else + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(OID, INFO, "ssid %s, bssid %pM, conn policy %d, disc reason %d\n", + prConnSettings->aucSSID, prConnSettings->aucBSSID, + prConnSettings->eConnectionPolicy, prAisAbortMsg->ucReasonOfDisconnect); + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will initiate the join procedure to attempt +* to associate with the new SSID. If the previous scanning +* result is aged, we will scan the channels at first. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_PARAM_SSID_T pParamSsid; + UINT_32 i; + INT_32 i4Idx = -1, i4MaxRSSI = INT_MIN; + P_MSG_AIS_ABORT_T prAisAbortMsg; + BOOLEAN fgIsValidSsid = TRUE; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* MSDN: + * Powering on the radio if the radio is powered off through a setting of OID_802_11_DISASSOCIATE + */ + if (prAdapter->fgIsRadioOff == TRUE) + prAdapter->fgIsRadioOff = FALSE; + + if (u4SetBufferLen < sizeof(PARAM_SSID_T) || u4SetBufferLen > sizeof(PARAM_SSID_T)) { + return WLAN_STATUS_INVALID_LENGTH; + } else if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set ssid! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + pParamSsid = (P_PARAM_SSID_T) pvSetBuffer; + + if (pParamSsid->u4SsidLen > 32) + return WLAN_STATUS_INVALID_LENGTH; + + prGlueInfo = prAdapter->prGlueInfo; + + /* prepare for CMD_BUILD_CONNECTION & CMD_GET_CONNECTION_STATUS */ + /* re-association check */ + if (kalGetMediaStateIndicated(prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, + pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + kalSetMediaStateIndicated(prGlueInfo, PARAM_MEDIA_STATE_TO_BE_INDICATED); + } else { + DBGLOG(OID, TRACE, "DisBySsid\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + } + /* check if any scanned result matchs with the SSID */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + PUINT_8 aucSsid = prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid; + UINT_8 ucSsidLength = (UINT_8) prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen; + INT_32 i4RSSI = prAdapter->rWlanInfo.arScanResult[i].rRssi; + + if (EQUAL_SSID(aucSsid, ucSsidLength, pParamSsid->aucSsid, pParamSsid->u4SsidLen) && + i4RSSI >= i4MaxRSSI) { + i4Idx = (INT_32) i; + i4MaxRSSI = i4RSSI; + } + } + + /* prepare message to AIS */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_IBSS + || prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_DEDICATED_IBSS) { + /* IBSS *//* beacon period */ + prAdapter->rWifiVar.rConnSettings.u2BeaconPeriod = prAdapter->rWlanInfo.u2BeaconPeriod; + prAdapter->rWifiVar.rConnSettings.u2AtimWindow = prAdapter->rWlanInfo.u2AtimWindow; + } + + if (prAdapter->rWifiVar.fgSupportWZCDisassociation) { + if (pParamSsid->u4SsidLen == ELEM_MAX_LEN_SSID) { + fgIsValidSsid = FALSE; + + for (i = 0; i < ELEM_MAX_LEN_SSID; i++) { + if (!((0 < pParamSsid->aucSsid[i]) && (pParamSsid->aucSsid[i] <= 0x1F))) { + fgIsValidSsid = TRUE; + break; + } + } + } + } + + /* Set Connection Request Issued Flag */ + if (fgIsValidSsid) { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = TRUE; + + if (pParamSsid->u4SsidLen) { + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + } else { + /* wildcard SSID */ + prAdapter->rWifiVar.rConnSettings.eConnectionPolicy = CONNECT_BY_SSID_ANY; + } + } else { + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + } + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + + COPY_SSID(prAdapter->rWifiVar.rConnSettings.aucSSID, + prAdapter->rWifiVar.rConnSettings.ucSSIDLen, pParamSsid->aucSsid, (UINT_8) pParamSsid->u4SsidLen); + + prAdapter->rWifiVar.rConnSettings.u4FreqInKHz = pParamSsid->u4CenterFreq; + if (EQUAL_SSID(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen, pParamSsid->aucSsid, pParamSsid->u4SsidLen)) { + prAisAbortMsg->fgDelayIndication = TRUE; + } else { + /* Update the information to CONNECTION_SETTINGS_T */ + prAisAbortMsg->fgDelayIndication = FALSE; + } + DBGLOG(SCN, INFO, "SSID %s\n", prAdapter->rWifiVar.rConnSettings.aucSSID); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidSetSsid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the currently associated SSID. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_SSID_T prAssociatedSsid; + + DEBUGFUNC("wlanoidQuerySsid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_SSID_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAssociatedSsid = (P_PARAM_SSID_T) pvQueryBuffer; + + kalMemZero(prAssociatedSsid->aucSsid, sizeof(prAssociatedSsid->aucSsid)); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + prAssociatedSsid->u4SsidLen = prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen; + + if (prAssociatedSsid->u4SsidLen) { + kalMemCopy(prAssociatedSsid->aucSsid, + prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, prAssociatedSsid->u4SsidLen); + } + } else { + prAssociatedSsid->u4SsidLen = 0; + + DBGLOG(OID, TRACE, "Null SSID\n"); + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQuerySsid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 network type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eOPMode; + + /* + ** According to OID_802_11_INFRASTRUCTURE_MODE + ** If there is no prior OID_802_11_INFRASTRUCTURE_MODE, + ** NDIS_STATUS_ADAPTER_NOT_READY shall be returned. + */ +#if DBG + switch (*(P_ENUM_PARAM_OP_MODE_T) pvQueryBuffer) { + case NET_TYPE_IBSS: + DBGLOG(OID, INFO, "IBSS mode\n"); + break; + case NET_TYPE_INFRA: + DBGLOG(OID, INFO, "Infrastructure mode\n"); + break; + default: + DBGLOG(OID, INFO, "Automatic mode\n"); + } +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set mode to infrastructure or +* IBSS, or automatic switch between the two. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid +* length of the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + ENUM_PARAM_OP_MODE_T eOpMode; + + DEBUGFUNC("wlanoidSetInfrastructureMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4SetBufferLen < sizeof(ENUM_PARAM_OP_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_OP_MODE_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set infrastructure mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eOpMode = *(P_ENUM_PARAM_OP_MODE_T) pvSetBuffer; + /* Verify the new infrastructure mode. */ + if (eOpMode >= NET_TYPE_NUM) { + DBGLOG(OID, TRACE, "Invalid mode value %d\n", eOpMode); + return WLAN_STATUS_INVALID_DATA; + } + + /* check if possible to switch to AdHoc mode */ + if (eOpMode == NET_TYPE_IBSS || eOpMode == NET_TYPE_DEDICATED_IBSS) { + if (cnmAisIbssIsPermitted(prAdapter) == FALSE) { + DBGLOG(OID, TRACE, "Mode value %d unallowed\n", eOpMode); + return WLAN_STATUS_FAILURE; + } + } + + /* Save the new infrastructure mode setting. */ + prAdapter->rWifiVar.rConnSettings.eOPMode = eOpMode; + + /* Clean up the Tx key flag */ + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; +#if CFG_SUPPORT_WAPI + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = 0; + kalMemZero(&prAdapter->prGlueInfo->aucWapiAssocInfoIEs, 42); +#endif + +#if CFG_SUPPORT_802_11W + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled = FALSE; +#endif + +#if CFG_SUPPORT_WPS2 + kalMemZero(&prAdapter->prGlueInfo->aucWSCAssocInfoIE, 200); + prAdapter->prGlueInfo->u2WSCAssocInfoIELen = 0; +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INFRASTRUCTURE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, nicOidCmdTimeoutCommon, 0, NULL, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetInfrastructureMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 authentication +* mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAuthMode"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer = prAdapter->rWifiVar.rConnSettings.eAuthMode; + +#if DBG + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer) { + case AUTH_MODE_OPEN: + DBGLOG(OID, INFO, "Current auth mode: Open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(OID, INFO, "Current auth mode: Shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(OID, INFO, "Current auth mode: Auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(OID, INFO, "Current auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(OID, INFO, "Current auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(OID, INFO, "Current auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(OID, INFO, "Current auth mode: WPA2 PSK\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + break; + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryAuthMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 authentication mode +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_32 i, u4AkmSuite; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + + DEBUGFUNC("wlanoidSetAuthMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_AUTH_MODE_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_AUTH_MODE_T)) + return WLAN_STATUS_INVALID_LENGTH; + + /* RF Test */ + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer >= AUTH_MODE_NUM) { + DBGLOG(OID, TRACE, "Invalid auth mode %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer) { + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + /* infrastructure mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_INFRA) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + case AUTH_MODE_WPA_NONE: + /* ad hoc mode only */ + if (prAdapter->rWifiVar.rConnSettings.eOPMode != NET_TYPE_IBSS) + return WLAN_STATUS_NOT_ACCEPTED; + break; + + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = *(P_ENUM_PARAM_AUTH_MODE_T) pvSetBuffer; + +#if DBG + switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_OPEN: + DBGLOG(RSN, TRACE, "New auth mode: open\n"); + break; + + case AUTH_MODE_SHARED: + DBGLOG(RSN, TRACE, "New auth mode: shared\n"); + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(RSN, TRACE, "New auth mode: auto-switch\n"); + break; + + case AUTH_MODE_WPA: + DBGLOG(RSN, TRACE, "New auth mode: WPA\n"); + break; + + case AUTH_MODE_WPA_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA PSK\n"); + break; + + case AUTH_MODE_WPA_NONE: + DBGLOG(RSN, TRACE, "New auth mode: WPA None\n"); + break; + + case AUTH_MODE_WPA2: + DBGLOG(RSN, TRACE, "New auth mode: WPA2\n"); + break; + + case AUTH_MODE_WPA2_PSK: + DBGLOG(RSN, TRACE, "New auth mode: WPA2 PSK\n"); + break; + + default: + DBGLOG(RSN, TRACE, "New auth mode: unknown (%d)\n", prAdapter->rWifiVar.rConnSettings.eAuthMode); + } +#endif + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode >= AUTH_MODE_WPA) { + switch (prAdapter->rWifiVar.rConnSettings.eAuthMode) { + case AUTH_MODE_WPA: + u4AkmSuite = WPA_AKM_SUITE_802_1X; + break; + + case AUTH_MODE_WPA_PSK: + u4AkmSuite = WPA_AKM_SUITE_PSK; + break; + + case AUTH_MODE_WPA_NONE: + u4AkmSuite = WPA_AKM_SUITE_NONE; + break; + + case AUTH_MODE_WPA2: + u4AkmSuite = RSN_AKM_SUITE_802_1X; + break; + + case AUTH_MODE_WPA2_PSK: + u4AkmSuite = RSN_AKM_SUITE_PSK; + break; + + default: + u4AkmSuite = 0; + } + } else { + u4AkmSuite = 0; + } + + /* Enable the specific AKM suite only. */ + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite) + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + else + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = FALSE; +#if CFG_SUPPORT_802_11W + if (kalGetMfpSetting(prAdapter->prGlueInfo) != RSN_AUTH_MFP_DISABLED) { + if ((u4AkmSuite == RSN_AKM_SUITE_PSK) && + prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_PSK_SHA256) { + DBGLOG(RSN, TRACE, "Enable RSN_AKM_SUITE_PSK_SHA256 AKM support\n"); + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + + } + if ((u4AkmSuite == RSN_AKM_SUITE_802_1X) && + prEntry->dot11RSNAConfigAuthenticationSuite == RSN_AKM_SUITE_802_1X_SHA256) { + DBGLOG(RSN, TRACE, "Enable RSN_AKM_SUITE_802_1X_SHA256 AKM support\n"); + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled = TRUE; + } + } +#endif + } + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetAuthMode */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current 802.11 privacy filter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPrivacyFilter"); + + ASSERT(prAdapter); + + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4QueryBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer = prAdapter->rWlanInfo.ePrivacyFilter; + +#if DBG + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvQueryBuffer) { + case PRIVACY_FILTER_ACCEPT_ALL: + DBGLOG(OID, INFO, "Current privacy mode: open mode\n"); + break; + + case PRIVACY_FILTER_8021xWEP: + DBGLOG(OID, INFO, "Current privacy mode: filtering mode\n"); + break; + + default: + DBGLOG(OID, INFO, "Current auth mode: %d\n", *(P_ENUM_PARAM_AUTH_MODE_T) pvQueryBuffer); + } +#endif + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPrivacyFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the IEEE 802.11 privacy filter +* to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("wlanoidSetPrivacyFilter"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_PRIVACY_FILTER_T); + + if (u4SetBufferLen < sizeof(ENUM_PARAM_PRIVACY_FILTER_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Authentication mode! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* Check if the new authentication mode is valid. */ + if (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer >= PRIVACY_FILTER_NUM) { + DBGLOG(OID, TRACE, "Invalid privacy filter %d\n", *(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer); + return WLAN_STATUS_INVALID_DATA; + } + + switch (*(P_ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer) { + default: + break; + } + + /* Save the new authentication mode. */ + prAdapter->rWlanInfo.ePrivacyFilter = *(ENUM_PARAM_PRIVACY_FILTER_T) pvSetBuffer; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPrivacyFilter */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to reload the available default settings for +* the specified type field. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + UINT_32 u4Len; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetReloadDefaults"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = sizeof(PARAM_RELOAD_DEFAULTS); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set Reload default! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + /* Verify the available reload options and reload the settings. */ + switch (*(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer) { + case ENUM_RELOAD_WEP_KEYS: + /* Reload available default WEP keys from the permanent + storage. */ + prAdapter->rWifiVar.rConnSettings.eAuthMode = AUTH_MODE_OPEN; + /* ENUM_ENCRYPTION_DISABLED; */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + { + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_802_11_KEY prCmdKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = 0; /* (UINT_8)(prRemovedKey->u4KeyIndex & 0x000000ff); */ + kalMemCopy(prCmdKey->aucPeerAddr, aucBCAddr, MAC_ADDR_LEN); + + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); + + prCmdKey->ucKeyType = 0; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; + } + + break; + + default: + DBGLOG(OID, TRACE, "Invalid reload option %d\n", *(P_PARAM_RELOAD_DEFAULTS) pvSetBuffer); + rStatus = WLAN_STATUS_INVALID_DATA; + } + + /* OID_802_11_RELOAD_DEFAULTS requiest to reset to auto mode */ + eNetworkType = PARAM_NETWORK_TYPE_AUTOMODE; + wlanoidSetNetworkTypeInUse(prAdapter, &eNetworkType, sizeof(eNetworkType), &u4Len); + + return rStatus; +} /* wlanoidSetReloadDefaults */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a WEP key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +#ifdef LINUX +UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; +UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif +WLAN_STATUS +wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#ifndef LINUX + UINT_8 keyBuffer[sizeof(PARAM_KEY_T) + 16 /* LEGACY_KEY_MAX_LEN */]; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; +#endif + P_PARAM_WEP_T prNewWepKey; + P_PARAM_KEY_T prParamKey = (P_PARAM_KEY_T) keyBuffer; + UINT_32 u4KeyId, u4SetLen; + + DEBUGFUNC("wlanoidSetAddWep"); + + ASSERT(prAdapter); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)) { + ASSERT(pu4SetInfoLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewWepKey = (P_PARAM_WEP_T) pvSetBuffer; + + /* Verify the total buffer for minimum length. */ + if (u4SetBufferLen < OFFSET_OF(PARAM_WEP_T, aucKeyMaterial) + prNewWepKey->u4KeyLength) { + DBGLOG(OID, WARN, "Invalid total buffer length (%d) than minimum length (%d)\n", + (UINT_8) u4SetBufferLen, (UINT_8) OFFSET_OF(PARAM_WEP_T, aucKeyMaterial)); + + *pu4SetInfoLen = OFFSET_OF(PARAM_WEP_T, aucKeyMaterial); + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key structure length. */ + if (prNewWepKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewWepKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Verify the key material length for maximum key material length:16 */ + if (prNewWepKey->u4KeyLength > 16 /* LEGACY_KEY_MAX_LEN */) { + DBGLOG(OID, WARN, "Invalid key material length (%d) greater than maximum key material length (16)\n", + (UINT_8) prNewWepKey->u4KeyLength); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + + u4KeyId = prNewWepKey->u4KeyIndex & BITS(0, 29) /* WEP_KEY_ID_FIELD */; + + /* Verify whether key index is valid or not, current version + driver support only 4 global WEP keys setting by this OID */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "Error, invalid WEP key ID: %d\n", (UINT_8) u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + prParamKey->u4KeyIndex = u4KeyId; + + /* Transmit key */ + if (prNewWepKey->u4KeyIndex & IS_TRANSMIT_KEY) + prParamKey->u4KeyIndex |= IS_TRANSMIT_KEY; + + /* Per client key */ + if (prNewWepKey->u4KeyIndex & IS_UNICAST_KEY) + prParamKey->u4KeyIndex |= IS_UNICAST_KEY; + + prParamKey->u4KeyLength = prNewWepKey->u4KeyLength; + + kalMemCopy(prParamKey->arBSSID, aucBCAddr, MAC_ADDR_LEN); + + kalMemCopy(prParamKey->aucKeyMaterial, prNewWepKey->aucKeyMaterial, prNewWepKey->u4KeyLength); + + prParamKey->u4Length = OFFSET_OF(PARAM_KEY_T, aucKeyMaterial) + prNewWepKey->u4KeyLength; + + wlanoidSetAddKey(prAdapter, (PVOID) prParamKey, prParamKey->u4Length, &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the WEP key +* at the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4KeyId, u4SetLen; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + DEBUGFUNC("wlanoidSetRemoveWep"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_KEY_INDEX); + + if (u4SetBufferLen < sizeof(PARAM_KEY_INDEX)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4KeyId = *(PUINT_32) pvSetBuffer; + + /* Dump PARAM_WEP content. */ + DBGLOG(OID, INFO, "Set: Dump PARAM_KEY_INDEX content\n"); + DBGLOG(OID, INFO, "Index : 0x%08x\n", u4KeyId); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set remove WEP! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4KeyId & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "Invalid WEP key index: 0x%08x\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + u4KeyId &= BITS(0, 7); + + /* Verify whether key index is valid or not. Current version + driver support only 4 global WEP keys. */ + if (u4KeyId > MAX_KEY_NUM - 1) { + DBGLOG(OID, ERROR, "invalid WEP key ID %u\n", u4KeyId); + return WLAN_STATUS_INVALID_DATA; + } + + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + rRemoveKey.u4KeyIndex = *(PUINT_32) pvSetBuffer; + + kalMemCopy(rRemoveKey.arBSSID, aucBCAddr, MAC_ADDR_LEN); + + wlanoidSetRemoveKey(prAdapter, (PVOID)&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T), &u4SetLen); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveWep */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_KEY_T, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + +#if 0 + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } +#endif + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + +#if 0 + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) + return WLAN_STATUS_INVALID_DATA; + + if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || + prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { + if (((prNewKey->u4KeyIndex & 0xff) != 0) || + ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) + && (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) + && (prNewKey->arBSSID[5] == 0xff))) { + return WLAN_STATUS_INVALID_DATA; + } + } + + *pu4SetInfoLen = u4SetBufferLen; +#endif + + /* Dump PARAM_KEY content. */ + DBGLOG(OID, TRACE, "Set: PARAM_KEY Length: 0x%08x, Key Index: 0x%08x, Key Length: 0x%08x\n", + prNewKey->u4Length, prNewKey->u4KeyIndex, prNewKey->u4KeyLength); + DBGLOG(OID, TRACE, "BSSID:\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->arBSSID, sizeof(PARAM_MAC_ADDRESS)); + DBGLOG(OID, TRACE, "Key RSC:\n"); + DBGLOG_MEM8(OID, TRACE, &prNewKey->rKeyRSC, sizeof(PARAM_KEY_RSC)); + DBGLOG(OID, TRACE, "Key Material:\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucKeyMaterial, prNewKey->u4KeyLength); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + /* Todo:: Store the legacy wep key for OID_802_11_RELOAD_DEFAULTS */ + /* Todo:: Nothing */ + } + + if (prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = TRUE; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum = %d\n", ucCmdSeqNum); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + prCmdKey->ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; + prCmdKey->ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + prCmdKey->ucIsAuthenticator = ((prNewKey->u4KeyIndex & IS_AUTHENTICATOR) == IS_AUTHENTICATOR) ? 1 : 0; + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->arBSSID, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + + /* Note: adjust the key length for WPA-None */ + prCmdKey->ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, prCmdKey->ucKeyLen); + + if (prNewKey->u4KeyLength == 5) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP40; + } else if (prNewKey->u4KeyLength == 13) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP104; + } else if (prNewKey->u4KeyLength == 16) { + if ((ucAlgorithmId != CIPHER_SUITE_CCMP) && + (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA)) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WEP128; + else { +#if CFG_SUPPORT_802_11W + if (prCmdKey->ucKeyId >= 4) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_BIP; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + prAisSpecBssInfo->fgBipKeyInstalled = TRUE; + } else +#endif + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + if (rsnCheckPmkidCandicate(prAdapter)) { + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + DBGLOG(RSN, TRACE, + "Add key: Prepare a timer to indicate candidate PMKID Candidate\n"); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } else if (prNewKey->u4KeyLength == 32) { + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prCmdKey->ucAlgorithmId = CIPHER_SUITE_CCMP; + prCmdKey->ucKeyLen = CCMP_KEY_LEN; + } + } else + prCmdKey->ucAlgorithmId = CIPHER_SUITE_TKIP; + } + + DBGLOG(RSN, TRACE, "prCmdKey->ucAlgorithmId=%d, key len=%d\n", + prCmdKey->ucAlgorithmId, (UINT32) prNewKey->u4KeyLength); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_KEY_T prNewKey; + + DEBUGFUNC("wlanoidSetAddKey"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(OID, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + + /* Verify the key material length for key material buffer */ + if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(OID, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + + /* Exception check */ + if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + + /* Exception check, pairwise key must with transmit bit enabled */ + if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { + if (((prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN) && + (prNewKey->u4KeyIndex & 0xff) != 0) || + EQUAL_MAC_ADDR(prNewKey->arBSSID, "\xff\xff\xff\xff\xff\xff")) { + return WLAN_STATUS_INVALID_DATA; + } + } else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) + return WLAN_STATUS_INVALID_DATA; + + if (!(prNewKey->u4KeyLength == WEP_40_LEN || prNewKey->u4KeyLength == WEP_104_LEN || + prNewKey->u4KeyLength == CCMP_KEY_LEN || prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + + *pu4SetInfoLen = u4SetBufferLen; + +#if (CFG_SUPPORT_TDLS == 1) + /* + supplicant will set key before updating station & enabling the link so we need to + backup the key information and set key when link is enabled + */ + if (TdlsexKeyHandle(prAdapter, prNewKey) == TDLS_STATUS_SUCCESS) + return WLAN_STATUS_SUCCESS; +#endif /* CFG_SUPPORT_TDLS */ + + return _wlanoidSetAddKey(prAdapter, pvSetBuffer, u4SetBufferLen, TRUE, CIPHER_SUITE_NONE, pu4SetInfoLen); +} /* wlanoidSetAddKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request the driver to remove the key at +* the specified key index. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_REMOVE_KEY_T prRemovedKey; + P_CMD_802_11_KEY prCmdKey; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetRemoveKey"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set remove key! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Dump PARAM_REMOVE_KEY content. */ + DBGLOG(OID, TRACE, "Set: Dump PARAM_REMOVE_KEY content\n"); + DBGLOG(OID, TRACE, "Length : 0x%08x\n", prRemovedKey->u4Length); + DBGLOG(OID, TRACE, "Key Index : 0x%08x\n", prRemovedKey->u4KeyIndex); + DBGLOG(OID, TRACE, "BSSID:\n"); + DBGLOG_MEM8(OID, TRACE, prRemovedKey->arBSSID, MAC_ADDR_LEN); + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(OID, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Clean up the Tx key flag */ + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_802_11_KEY))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_802_11_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(PARAM_REMOVE_KEY_T); + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero((PUINT_8) prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 0; /* Remove */ + prCmdKey->ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + +#if CFG_SUPPORT_802_11W + ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM + 2); +#else + /* ASSERT(prCmdKey->ucKeyId < MAX_KEY_NUM); */ +#endif + + if (prRemovedKey->u4KeyIndex & IS_UNICAST_KEY) + prCmdKey->ucKeyType = 1; + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetRemoveKey */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current encryption status. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + BOOLEAN fgTransmitKeyAvailable = TRUE; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus = 0; + + DEBUGFUNC("wlanoidQueryEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + fgTransmitKeyAvailable = prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist; + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION3_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION2_ENABLED: + if (fgTransmitKeyAvailable) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + break; + } + eEncStatus = ENUM_ENCRYPTION2_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION1_ENABLED: + if (fgTransmitKeyAvailable) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION1_KEY_ABSENT; + break; + + case ENUM_ENCRYPTION_DISABLED: + eEncStatus = ENUM_ENCRYPTION_DISABLED; + break; + + default: + DBGLOG(OID, ERROR, "Unknown Encryption Status Setting:%d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } + +#if DBG + DBGLOG(OID, INFO, + "Encryption status: %d Return:%d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, eEncStatus); +#endif + + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvQueryBuffer = eEncStatus; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the encryption status to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_NOT_SUPPORTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_ENCRYPTION_STATUS_T eEewEncrypt; + + DEBUGFUNC("wlanoidSetEncryptionStatus"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prGlueInfo = prAdapter->prGlueInfo; + + *pu4SetInfoLen = sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T); + + /* if (IS_ARB_IN_RFTEST_STATE(prAdapter)) { */ + /* return WLAN_STATUS_SUCCESS; */ + /* } */ + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set encryption status! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + eEewEncrypt = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + DBGLOG(OID, TRACE, "ENCRYPTION_STATUS %d\n", eEewEncrypt); + + switch (eEewEncrypt) { + case ENUM_ENCRYPTION_DISABLED: /* Disable WEP, TKIP, AES */ + DBGLOG(RSN, TRACE, "Disable Encryption\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION1_ENABLED: /* Enable WEP. Disable TKIP, AES */ + DBGLOG(RSN, TRACE, "Enable Encryption1\n"); + secSetCipherSuite(prAdapter, CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128); + break; + + case ENUM_ENCRYPTION2_ENABLED: /* Enable WEP, TKIP. Disable AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP); + DBGLOG(RSN, TRACE, "Enable Encryption2\n"); + break; + + case ENUM_ENCRYPTION3_ENABLED: /* Enable WEP, TKIP, AES */ + secSetCipherSuite(prAdapter, + CIPHER_FLAG_WEP40 | + CIPHER_FLAG_WEP104 | CIPHER_FLAG_WEP128 | CIPHER_FLAG_TKIP | CIPHER_FLAG_CCMP); + DBGLOG(RSN, TRACE, "Enable Encryption3\n"); + break; + + default: + DBGLOG(RSN, WARN, "Unacceptible encryption status: %d\n", + *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer); + + rStatus = WLAN_STATUS_NOT_SUPPORTED; + } + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Save the new encryption status. */ + prAdapter->rWifiVar.rConnSettings.eEncStatus = *(P_ENUM_PARAM_ENCRYPTION_STATUS_T) pvSetBuffer; + + DBGLOG(RSN, TRACE, "wlanoidSetEncryptionStatus to %d\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } + + return rStatus; +} /* wlanoidSetEncryptionStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to test the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_802_11_TEST_T prTest; + PVOID pvTestData; + PVOID pvStatusBuffer; + UINT_32 u4StatusBufferSize; + + DEBUGFUNC("wlanoidSetTest"); + + ASSERT(prAdapter); + + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + *pu4SetInfoLen = u4SetBufferLen; + + prTest = (P_PARAM_802_11_TEST_T) pvSetBuffer; + + DBGLOG(OID, TRACE, "Test - Type %u\n", prTest->u4Type); + + switch (prTest->u4Type) { + case 1: /* Type 1: generate an authentication event */ + pvTestData = (PVOID) &prTest->u.AuthenticationEvent; + pvStatusBuffer = (PVOID) prAdapter->aucIndicationEventBuffer; + u4StatusBufferSize = prTest->u4Length - 8; + if (u4StatusBufferSize > sizeof(PARAM_AUTH_EVENT_T)) { + DBGLOG(OID, TRACE, "prTest->u4Length error %u\n", u4StatusBufferSize); + ASSERT(FALSE); + } + break; + + case 2: /* Type 2: generate an RSSI status indication */ + pvTestData = (PVOID) &prTest->u.RssiTrigger; + pvStatusBuffer = (PVOID) &prAdapter->rWlanInfo.rCurrBssId.rRssi; + u4StatusBufferSize = sizeof(PARAM_RSSI); + break; + + default: + return WLAN_STATUS_INVALID_DATA; + } + + ASSERT(u4StatusBufferSize <= 180); + if (u4StatusBufferSize > 180) + return WLAN_STATUS_INVALID_LENGTH; + + /* Get the contents of the StatusBuffer from the test structure. */ + kalMemCopy(pvStatusBuffer, pvTestData, u4StatusBufferSize); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, pvStatusBuffer, u4StatusBufferSize); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetTest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the driver's WPA2 status. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCapability(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CAPABILITY_T prCap; + P_PARAM_AUTH_ENCRYPTION_T prAuthenticationEncryptionSupported; + + DEBUGFUNC("wlanoidQueryCapability"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = 4 * sizeof(UINT_32) + 14 * sizeof(PARAM_AUTH_ENCRYPTION_T); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prCap = (P_PARAM_CAPABILITY_T) pvQueryBuffer; + + prCap->u4Length = *pu4QueryInfoLen; + prCap->u4Version = 2; /* WPA2 */ + prCap->u4NoOfPMKIDs = CFG_MAX_PMKID_CACHE; + prCap->u4NoOfAuthEncryptPairsSupported = 14; + + prAuthenticationEncryptionSupported = &prCap->arAuthenticationEncryptionSupported[0]; + + /* fill 14 entries of supported settings */ + prAuthenticationEncryptionSupported[0].eAuthModeSupported = AUTH_MODE_OPEN; + + prAuthenticationEncryptionSupported[0].eEncryptStatusSupported = ENUM_ENCRYPTION_DISABLED; + + prAuthenticationEncryptionSupported[1].eAuthModeSupported = AUTH_MODE_OPEN; + prAuthenticationEncryptionSupported[1].eEncryptStatusSupported = ENUM_ENCRYPTION1_ENABLED; + + prAuthenticationEncryptionSupported[2].eAuthModeSupported = AUTH_MODE_SHARED; + prAuthenticationEncryptionSupported[2].eEncryptStatusSupported = ENUM_ENCRYPTION_DISABLED; + + prAuthenticationEncryptionSupported[3].eAuthModeSupported = AUTH_MODE_SHARED; + prAuthenticationEncryptionSupported[3].eEncryptStatusSupported = ENUM_ENCRYPTION1_ENABLED; + + prAuthenticationEncryptionSupported[4].eAuthModeSupported = AUTH_MODE_WPA; + prAuthenticationEncryptionSupported[4].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[5].eAuthModeSupported = AUTH_MODE_WPA; + prAuthenticationEncryptionSupported[5].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[6].eAuthModeSupported = AUTH_MODE_WPA_PSK; + prAuthenticationEncryptionSupported[6].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[7].eAuthModeSupported = AUTH_MODE_WPA_PSK; + prAuthenticationEncryptionSupported[7].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[8].eAuthModeSupported = AUTH_MODE_WPA_NONE; + prAuthenticationEncryptionSupported[8].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[9].eAuthModeSupported = AUTH_MODE_WPA_NONE; + prAuthenticationEncryptionSupported[9].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[10].eAuthModeSupported = AUTH_MODE_WPA2; + prAuthenticationEncryptionSupported[10].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[11].eAuthModeSupported = AUTH_MODE_WPA2; + prAuthenticationEncryptionSupported[11].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; + + prAuthenticationEncryptionSupported[12].eAuthModeSupported = AUTH_MODE_WPA2_PSK; + prAuthenticationEncryptionSupported[12].eEncryptStatusSupported = ENUM_ENCRYPTION2_ENABLED; + + prAuthenticationEncryptionSupported[13].eAuthModeSupported = AUTH_MODE_WPA2_PSK; + prAuthenticationEncryptionSupported[13].eEncryptStatusSupported = ENUM_ENCRYPTION3_ENABLED; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryCapability */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the PMKID in the PMK cache. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPmkid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + UINT_32 i; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidQueryPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + *pu4QueryInfoLen = OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo) + + prAisSpecBssInfo->u4PmkidCacheCount * sizeof(PARAM_BSSID_INFO_T); + + if (u4QueryBufferLen < *pu4QueryInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + prPmkid = (P_PARAM_PMKID_T) pvQueryBuffer; + + prPmkid->u4Length = *pu4QueryInfoLen; + prPmkid->u4BSSIDInfoCount = prAisSpecBssInfo->u4PmkidCacheCount; + + for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { + kalMemCopy(prPmkid->arBSSIDInfo[i].arBSSID, + prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, sizeof(PARAM_MAC_ADDRESS)); + kalMemCopy(prPmkid->arBSSIDInfo[i].arPMKID, + prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arPMKID, sizeof(PARAM_PMKID_VALUE)); + } + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the PMKID to the PMK cache in the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetPmkid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i, j; + P_PARAM_PMKID_T prPmkid; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("wlanoidSetPmkid"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = u4SetBufferLen; + + /* It's possibble BSSIDInfoCount is zero, because OS wishes to clean PMKID */ + if (u4SetBufferLen < OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + ASSERT(pvSetBuffer); + prPmkid = (P_PARAM_PMKID_T) pvSetBuffer; + + if (u4SetBufferLen < + ((prPmkid->u4BSSIDInfoCount * sizeof(PARAM_BSSID_INFO_T)) + OFFSET_OF(PARAM_PMKID_T, arBSSIDInfo))) + return WLAN_STATUS_INVALID_DATA; + + if (prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE) + return WLAN_STATUS_INVALID_DATA; + + DBGLOG(OID, TRACE, "Count %u\n", prPmkid->u4BSSIDInfoCount); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* This OID replace everything in the PMKID cache. */ + if (prPmkid->u4BSSIDInfoCount == 0) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + if ((prAisSpecBssInfo->u4PmkidCacheCount + prPmkid->u4BSSIDInfoCount > CFG_MAX_PMKID_CACHE)) { + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero(prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); + } + + /* + The driver can only clear its PMKID cache whenever it make a media disconnect + indication. Otherwise, it must change the PMKID cache only when set through this OID. + */ +#if CFG_RSN_MIGRATION + for (i = 0; i < prPmkid->u4BSSIDInfoCount; i++) { + /* Search for desired BSSID. If desired BSSID is found, + then set the PMKID */ + if (!rsnSearchPmkidEntry(prAdapter, (PUINT_8) prPmkid->arBSSIDInfo[i].arBSSID, &j)) { + /* No entry found for the specified BSSID, so add one entry */ + if (prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE - 1) { + j = prAisSpecBssInfo->u4PmkidCacheCount; + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prPmkid->arBSSIDInfo[i].arBSSID, sizeof(PARAM_MAC_ADDRESS)); + prAisSpecBssInfo->u4PmkidCacheCount++; + } else { + j = CFG_MAX_PMKID_CACHE; + } + } + + if (j < CFG_MAX_PMKID_CACHE) { + kalMemCopy(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID, + prPmkid->arBSSIDInfo[i].arPMKID, sizeof(PARAM_PMKID_VALUE)); + DBGLOG(RSN, TRACE, "Add BSSID %pM idx=%d PMKID value %pM\n", + (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID), (UINT_32) j, + (prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arPMKID)); + prAisSpecBssInfo->arPmkidCache[j].fgPmkidExist = TRUE; + } + } +#endif + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetPmkid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the set of supported data rates that +* the radio is capable of running +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query +* \param[in] u4QueryBufferLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number +* of bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PARAM_RATES eRate = { + /* BSSBasicRateSet for 802.11n Non-HT rates */ + 0x8C, /* 6M */ + 0x92, /* 9M */ + 0x98, /* 12M */ + 0xA4, /* 18M */ + 0xB0, /* 24M */ + 0xC8, /* 36M */ + 0xE0, /* 48M */ + 0xEC /* 54M */ + }; + + DEBUGFUNC("wlanoidQuerySupportedRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &eRate, sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQuerySupportedRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RATES_EX); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, (PVOID) &(prAdapter->rWlanInfo.eDesiredRates), sizeof(PARAM_RATES)); + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the desired rates. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i; + + DEBUGFUNC("wlanoidSetDesiredRates"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(PARAM_RATES); + + if (u4SetBufferLen < sizeof(PARAM_RATES)) + return WLAN_STATUS_INVALID_LENGTH; + + kalMemCopy((PVOID) &(prAdapter->rWlanInfo.eDesiredRates), pvSetBuffer, sizeof(PARAM_RATES)); + + prAdapter->rWlanInfo.eLinkAttr.ucDesiredRateLen = PARAM_MAX_LEN_RATES; + for (i = 0; i < PARAM_MAX_LEN_RATES; i++) + prAdapter->rWlanInfo.eLinkAttr.u2DesiredRate[i] = (UINT_16) (prAdapter->rWlanInfo.eDesiredRates[i]); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetDesiredRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum frame size in bytes, +* not including the header. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxFrameSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ - ETHERNET_HEADER_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxFrameSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the maximum total packet length +* in bytes. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMaxTotalSize"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(PUINT_32) pvQueryBuffer = ETHERNET_MAX_PKT_SZ; + *pu4QueryInfoLen = sizeof(UINT_32); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryMaxTotalSize */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the vendor ID of the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PUINT_8 cp; +#endif + DEBUGFUNC("wlanoidQueryVendorId"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + kalMemCopy(pvQueryBuffer, prAdapter->aucMacAddress, 3); + *((PUINT_8) pvQueryBuffer + 3) = 1; + *pu4QueryInfoLen = sizeof(UINT_32); + +#if DBG + cp = (PUINT_8) pvQueryBuffer; + DBGLOG(OID, LOUD, "Vendor ID=%02x-%02x-%02x-%02x\n", cp[0], cp[1], cp[2], cp[3]); +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryVendorId */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI) prAdapter->rLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +#endif +} /* end of wlanoidQueryRssi() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RSSI trigger value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call failed due to invalid length of +* the query buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRssiTrigger"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_NONE) + return WLAN_STATUS_ADAPTER_NOT_READY; + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *(PARAM_RSSI *) pvQueryBuffer = prAdapter->rWlanInfo.rRssiTriggerValue; + DBGLOG(OID, INFO, "RSSI trigger: %d dBm\n", *(PARAM_RSSI *) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a trigger value of the RSSI event. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns the +* amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RSSI rRssiTriggerValue; + + DEBUGFUNC("wlanoidSetRssiTrigger"); + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RSSI); + rRssiTriggerValue = *(PARAM_RSSI *) pvSetBuffer; + + if (rRssiTriggerValue > PARAM_WHQL_RSSI_MAX_DBM || rRssiTriggerValue < PARAM_WHQL_RSSI_MIN_DBM) + return + /* Save the RSSI trigger value to the Adapter structure */ + prAdapter->rWlanInfo.rRssiTriggerValue = rRssiTriggerValue; + + /* If the RSSI trigger value is equal to the current RSSI value, the + * indication triggers immediately. We need to indicate the protocol + * that an RSSI status indication event triggers. */ + if (rRssiTriggerValue == (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) &prAdapter->rWlanInfo.rRssiTriggerValue, sizeof(PARAM_RSSI)); + } else if (rRssiTriggerValue < (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_GREATER; + else if (rRssiTriggerValue > (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_LESS; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetRssiTrigger */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a suggested value for the number of +* bytes of received packet data that will be indicated to the protocol +* driver. We just accept the set and ignore this value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetCurrentLookahead"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(UINT_32); + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetCurrentLookahead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* receives but does not indicate to the protocols due to errors. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* cannot receive due to lack of NIC receive buffer space. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvNoBuffer"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) 0; /* @FIXME */ + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) 0; /* @FIXME */ + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvNoBuffer, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvNoBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the number of frames that the NIC +* received and it is CRC error. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS If success; +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvCrcError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFCSErrorCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvCrcError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvCrcError */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS_PL, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the current 802.11 statistics. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryStatistics"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(PARAM_802_11_STATISTICS_STRUCT_T)) { + DBGLOG(OID, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + + *pu4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) pvQueryBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prAdapter->rStatStruct.rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prAdapter->rStatStruct.rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prAdapter->rStatStruct.rFailedCount; + prStatistics->rRetryCount = prAdapter->rStatStruct.rRetryCount; + prStatistics->rMultipleRetryCount = prAdapter->rStatStruct.rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prAdapter->rStatStruct.rRTSSuccessCount; + prStatistics->rRTSFailureCount = prAdapter->rStatStruct.rRTSFailureCount; + prStatistics->rACKFailureCount = prAdapter->rStatStruct.rACKFailureCount; + prStatistics->rFrameDuplicateCount = prAdapter->rStatStruct.rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prAdapter->rStatStruct.rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prAdapter->rStatStruct.rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prAdapter->rStatStruct.rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryStatistics, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryStatistics */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query current media streaming status. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *(P_ENUM_MEDIA_STREAM_MODE) pvQueryBuffer = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to enter media streaming mode or exit media streaming mode +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ENUM_MEDIA_STREAM_MODE eStreamMode; + + DEBUGFUNC("wlanoidSetMediaStreamMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(ENUM_MEDIA_STREAM_MODE)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = sizeof(ENUM_MEDIA_STREAM_MODE); + + eStreamMode = *(P_ENUM_MEDIA_STREAM_MODE) pvSetBuffer; + + if (eStreamMode == ENUM_MEDIA_STREAM_OFF) + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 0; + else + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode = 1; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_LINK_ATTRIB, + TRUE, + FALSE, + TRUE, + nicCmdEventSetMediaStreamMode, + nicOidCmdTimeoutCommon, + sizeof(CMD_LINK_ATTRIB), + (PUINT_8) &(prAdapter->rWlanInfo.eLinkAttr), pvSetBuffer, u4SetBufferLen); +} /* wlanoidSetMediaStreamMode */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the permanent MAC address of the NIC. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryPermanentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + COPY_MAC_ADDR(pvQueryBuffer, prAdapter->rWifiVar.aucPermanentAddress); + *pu4QueryInfoLen = MAC_ADDR_LEN; + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryPermanentAddr */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidQueryCurrentAddr"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < MAC_ADDR_LEN) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryAddress, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), + (PUINT_8) &rCmdBasicConfig, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryCurrentAddr */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query NIC link speed. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryLinkSpeed"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (prAdapter->fgIsLinkRateValid == TRUE && + (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + *(PUINT_32) pvQueryBuffer = prAdapter->rLinkQuality.u2LinkSpeed * 5000; /* change to unit of 100bps */ + return WLAN_STATUS_SUCCESS; + } else { + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkSpeed, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + } +} /* end of wlanoidQueryLinkSpeed() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query MCR value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + CMD_ACCESS_REG rCmdAccessReg; + + DEBUGFUNC("wlanoidQueryMcrRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvQueryBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrRdInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_READ, + (UINT_16) (prMcrRdInfo->u4McrOffset & BITS(0, 15)), &prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + + /* Check if access F/W Domain MCR (due to WiFiSYS is placed from 0x6000-0000 */ + if (prMcrRdInfo->u4McrOffset & 0xFFFF0000) { + /* fill command */ + rCmdAccessReg.u4Address = prMcrRdInfo->u4McrOffset; + rCmdAccessReg.u4Data = 0; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcrRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvQueryBuffer, u4QueryBufferLen); + } else { + HAL_MCR_RD(prAdapter, prMcrRdInfo->u4McrOffset & BITS(2, 31), /* address is in DWORD unit */ + &prMcrRdInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Read: Offset = %#08x, Data = %#08x\n", + prMcrRdInfo->u4McrOffset, prMcrRdInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +} /* end of wlanoidQueryMcrRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write MCR and enable specific function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrWrInfo; + CMD_ACCESS_REG rCmdAccessReg; + +#if CFG_STRESS_TEST_SUPPORT + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + P_STA_RECORD_T prStaRec = prBssInfo->prStaRecOfAP; + UINT_32 u4McrOffset, u4McrData; +#endif + + DEBUGFUNC("wlanoidSetMcrWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMcrWrInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) pvSetBuffer; + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + + /* -- Puff Stress Test Begin */ +#if CFG_STRESS_TEST_SUPPORT + + /* 0xFFFFFFFE for Control Rate */ + if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFE) { + if (prMcrWrInfo->u4McrData < FIXED_RATE_NUM && prMcrWrInfo->u4McrData > 0) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (prMcrWrInfo->u4McrData); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DEBUGFUNC("[Stress Test]Complete Rate is Changed...\n"); + DBGLOG(OID, TRACE, + "[Stress Test] Rate is Changed to index %d...\n", prAdapter->rWifiVar.eRateSetting); + } + /* 0xFFFFFFFD for Switch Channel */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFD) { + if (prMcrWrInfo->u4McrData <= 11 && prMcrWrInfo->u4McrData >= 1) + prBssInfo->ucPrimaryChannel = prMcrWrInfo->u4McrData; + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + DBGLOG(OID, TRACE, "[Stress Test] Channel is switched to %d ...\n", prBssInfo->ucPrimaryChannel); + + return WLAN_STATUS_SUCCESS; + } + /* 0xFFFFFFFFC for Control RF Band and SCO */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFC) { + /* Band */ + if (prMcrWrInfo->u4McrData & 0x80000000) { + /* prBssInfo->eBand = BAND_5G; */ + /* prBssInfo->ucPrimaryChannel = 52; // Bond to Channel 52 */ + } else { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 8; /* Bond to Channel 6 */ + } + + /* Bandwidth */ + if (prMcrWrInfo->u4McrData & 0x00010000) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + if (prMcrWrInfo->u4McrData == 0x00010002) { + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* U20 */ + prBssInfo->ucPrimaryChannel += 2; + } else if (prMcrWrInfo->u4McrData == 0x00010001) { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* L20 */ + prBssInfo->ucPrimaryChannel -= 2; + } else { + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* 40 */ + } + } + + if (prMcrWrInfo->u4McrData & 0x00000000) { + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + } + /* 0xFFFFFFFB for HT Capability */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFB) { + /* Enable HT Capability */ + if (prMcrWrInfo->u4McrData & 0x00000001) { + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + DEBUGFUNC("[Stress Test]Enable HT capability...\n"); + } else { + prStaRec->u2HtCapInfo &= (~HT_CAP_INFO_HT_GF); + DEBUGFUNC("[Stress Test]Disable HT capability...\n"); + } + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + } + /* 0xFFFFFFFA for Enable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFFA) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF9 for Disable Random Rx Reset */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF9) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_RANDOM_RX_RESET_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF8 for Enable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF8) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_EN, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + /* 0xFFFFFFF7 for Disable SAPP */ + else if (prMcrWrInfo->u4McrOffset == 0xFFFFFFF7) { + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SAPP_DE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } + + else +#endif + /* -- Puff Stress Test End */ + + /* Check if access F/W Domain MCR */ + if (prMcrWrInfo->u4McrOffset & 0xFFFF0000) { + + /* 0x9000 - 0x9EFF reserved for FW */ +#if CFG_SUPPORT_SWCR + if ((prMcrWrInfo->u4McrOffset >> 16) == 0x9F00) { + swCrReadWriteCmd(prAdapter, + SWCR_WRITE, + (UINT_16) (prMcrWrInfo->u4McrOffset & BITS(0, 15)), &prMcrWrInfo->u4McrData); + return WLAN_STATUS_SUCCESS; + } +#endif /* CFG_SUPPORT_SWCR */ + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + /* DbgPrint("Enter test mode\n"); */ + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111) { + /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112) { + + /* DbgPrint("LP enter sleep\n"); */ + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } +#endif + +#if 1 + /* low power test special command */ + if (prMcrWrInfo->u4McrOffset == 0x11111110) { + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + /* DbgPrint("Enter test mode\n"); */ + prAdapter->fgTestMode = TRUE; + return rStatus; + } + if (prMcrWrInfo->u4McrOffset == 0x11111111) { + /* DbgPrint("nicpmSetAcpiPowerD3\n"); */ + + nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + return WLAN_STATUS_SUCCESS; + } + if (prMcrWrInfo->u4McrOffset == 0x11111112) { + + /* DbgPrint("LP enter sleep\n"); */ + + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } +#endif + /* fill command */ + rCmdAccessReg.u4Address = prMcrWrInfo->u4McrOffset; + rCmdAccessReg.u4Data = prMcrWrInfo->u4McrData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_REG), + (PUINT_8) &rCmdAccessReg, pvSetBuffer, u4SetBufferLen); + } else { + HAL_MCR_WR(prAdapter, (prMcrWrInfo->u4McrOffset & BITS(2, 31)), /* address is in DWORD unit */ + prMcrWrInfo->u4McrData); + + DBGLOG(OID, TRACE, "MCR Write: Offset = %#08x, Data = %#08x\n", + prMcrWrInfo->u4McrOffset, prMcrWrInfo->u4McrData); + + return WLAN_STATUS_SUCCESS; + } +} /* wlanoidSetMcrWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query SW CTRL +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; + + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + + DEBUGFUNC("wlanoidQuerySwCtrlRead"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvQueryBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = 0; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_READ /* Read */ , + (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0xFFFF: + { + u4Data = 0x5AA56620; + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = 0; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + FALSE, + TRUE, + TRUE, + nicCmdEventQuerySwCtrlRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvQueryBuffer, u4QueryBufferLen); + } + } /* switch(u2Id) */ + + prSwCtrlInfo->u4Data = u4Data; + + return rWlanStatus; + +} + + /* end of wlanoidQuerySwCtrlRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write SW CTRL +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rWlanStatus; + UINT_16 u2Id, u2SubId; + UINT_32 u4Data; +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + P_GLUE_INFO_T prGlueInfo; + CMD_HOTSPOT_OPTIMIZATION_CONFIG arHotspotOptimizationCfg; +#endif + + DEBUGFUNC("wlanoidSetSwCtrlWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + prGlueInfo = prAdapter->prGlueInfo; +#endif + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) pvSetBuffer; + + u2Id = (UINT_16) (prSwCtrlInfo->u4Id >> 16); + u2SubId = (UINT_16) (prSwCtrlInfo->u4Id & BITS(0, 15)); + u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = WLAN_STATUS_SUCCESS; + + switch (u2Id) { + + /* 0x9000 - 0x9EFF reserved for FW */ + /* 0xFFFE reserved for FW */ + +#if CFG_SUPPORT_SWCR + case 0x9F00: + swCrReadWriteCmd(prAdapter, SWCR_WRITE, (UINT_16) u2SubId, &u4Data); + break; +#endif /* CFG_SUPPORT_SWCR */ + + case 0x1000: + if (u2SubId == 0x8000) { + /* CTIA power save mode setting (code: 0x10008000) */ + prAdapter->u4CtiaPowerMode = u4Data; + prAdapter->fgEnCtiaPowerMode = TRUE; + + /* */ + { + PARAM_POWER_MODE ePowerMode; + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else + ePowerMode = Param_PowerModeFast_PSP; + + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); + } + } + break; + case 0x1001: + if (u2SubId == 0x0) + prAdapter->fgEnOnlineScan = (BOOLEAN) u4Data; + else if (u2SubId == 0x1) + prAdapter->fgDisBcnLostDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x2) + prAdapter->rWifiVar.fgSupportUAPSD = (BOOLEAN) u4Data; + else if (u2SubId == 0x3) { + prAdapter->u4UapsdAcBmp = u4Data & BITS(0, 15); + prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpDeliveryAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + prAdapter->rWifiVar.arBssInfo[u4Data >> 16].rPmProfSetupInfo.ucBmpTriggerAC = + (UINT_8) prAdapter->u4UapsdAcBmp; + } else if (u2SubId == 0x4) + prAdapter->fgDisStaAgingTimeoutDetection = (BOOLEAN) u4Data; + else if (u2SubId == 0x5) + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = (UINT_8) u4Data; + else if (u2SubId == 0x0100) + prAdapter->rWifiVar.u8SupportRxGf = (UINT_8) u4Data; + else if (u2SubId == 0x0101) { + prAdapter->rWifiVar.u8SupportRxSgi20 = (UINT_8) u4Data; + prAdapter->rWifiVar.u8SupportRxSgi40 = (UINT_8) u4Data; + } else if (u2SubId == 0x0102) + prAdapter->rWifiVar.u8SupportRxSTBC = (UINT_8) u4Data; + break; + +#if CFG_SUPPORT_SWCR + case 0x1002: + if (u2SubId == 0x0) { + if (u4Data) + u4Data = BIT(HIF_RX_PKT_TYPE_MANAGEMENT); + swCrFrameCheckEnable(prAdapter, u4Data); + } else if (u2SubId == 0x1) { + BOOLEAN fgIsEnable; + UINT_8 ucType; + UINT_32 u4Timeout; + + fgIsEnable = (BOOLEAN) (u4Data & 0xff); + ucType = 0; /* ((u4Data>>4) & 0xf); */ + u4Timeout = ((u4Data >> 8) & 0xff); + swCrDebugCheckEnable(prAdapter, fgIsEnable, ucType, u4Timeout); + } + break; +#endif + +#if CFG_SUPPORT_802_11W + case 0x2000: + DBGLOG(RSN, TRACE, "802.11w test 0x%x\n", u2SubId); + if (u2SubId == 0x0) + rsnStartSaQuery(prAdapter); + if (u2SubId == 0x1) + rsnStopSaQuery(prAdapter); + if (u2SubId == 0x2) + rsnSaQueryRequest(prAdapter, NULL); + if (u2SubId == 0x3) { + P_BSS_INFO_T prBssInfo = &(prAdapter->rWifiVar.arBssInfo[(NETWORK_TYPE_AIS_INDEX)]); + + authSendDeauthFrame(prAdapter, prBssInfo->prStaRecOfAP, NULL, 7, NULL); + } + /* wext_set_mode */ + /* + if (u2SubId == 0x3) { + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_DISABLED; + } + if (u2SubId == 0x4) { + //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_OPTIONAL; + } + if (u2SubId == 0x5) { + //prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + prAdapter->prGlueInfo->rWpaInfo.u4Mfp = RSN_AUTH_MFP_REQUIRED; + } + */ + break; +#endif + case 0xFFFF: + { +/* CMD_ACCESS_REG rCmdAccessReg; */ +#if 1 /* CFG_MT6573_SMT_TEST */ + if (u2SubId == 0x0123) { + + DBGLOG(HAL, TRACE, "set smt fixed rate: %u\n", u4Data); + + if ((ENUM_REGISTRY_FIXED_RATE_T) (u4Data) < FIXED_RATE_NUM) + prAdapter->rWifiVar.eRateSetting = (ENUM_REGISTRY_FIXED_RATE_T) (u4Data); + else + prAdapter->rWifiVar.eRateSetting = FIXED_RATE_NONE; + + if (prAdapter->rWifiVar.eRateSetting == FIXED_RATE_NONE) + /* Enable Auto (Long/Short) Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_AUTO; + else if ((prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_20M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS7_20M_400NS) + || (prAdapter->rWifiVar.eRateSetting >= FIXED_RATE_MCS0_40M_400NS && + prAdapter->rWifiVar.eRateSetting <= FIXED_RATE_MCS32_400NS)) + /* Force Short Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_SHORT; + else + /* Force Long Preamble */ + prAdapter->rWifiVar.ePreambleType = PREAMBLE_TYPE_LONG; + + /* abort to re-connect */ +#if 1 + DBGLOG(OID, TRACE, "DisBySwC\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); +#else + aisBssBeaconTimeout(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; + + } else if (u2SubId == 0x1234) { + /* 1. Disable On-Lin Scan */ + /* 3. Disable FIFO FULL no ack */ + /* 4. Disable Roaming */ + /* Disalbe auto tx power */ + /* 2. Keep at CAM mode */ + /* 5. Disable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, TRUE, TRUE); + } else if (u2SubId == 0x1235) { + /* 1. Enaable On-Lin Scan */ + /* 3. Enable FIFO FULL no ack */ + /* 4. Enable Roaming */ + /* Enable auto tx power */ + /* 2. Keep at Fast PS */ + /* 5. Enable Beacon Timeout Detection */ + rWlanStatus = nicEnterCtiaMode(prAdapter, FALSE, TRUE); + } +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + else if (u2SubId == 0x1240) { + DBGLOG(P2P, TRACE, "Disable Hotspot Optimization!\n"); + + arHotspotOptimizationCfg.fgHotspotOptimizationEn = FALSE; + arHotspotOptimizationCfg.u4Level = 0; + wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_HOTSPOT_OPTIMIZATION, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), + (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); + } else if (u2SubId == 0x1241) { + DBGLOG(P2P, TRACE, "Enable Hotspot Optimization!\n"); + + arHotspotOptimizationCfg.fgHotspotOptimizationEn = TRUE; + arHotspotOptimizationCfg.u4Level = 5; + wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_HOTSPOT_OPTIMIZATION, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), + (PUINT_8) &arHotspotOptimizationCfg, NULL, 0); + } +#endif /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ + else if (u2SubId == 0x1250) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET DUAL BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_NULL; + } else if (u2SubId == 0x1251) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET 2.4G BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_2G4; + } else if (u2SubId == 0x1252) { + DBGLOG(OID, TRACE, "LTE_COEX: SW SET 5G BAND\n"); + prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] = BAND_5G; + } +#endif + } + break; + + case 0x9000: + default: + { + rCmdSwCtrl.u4Id = prSwCtrlInfo->u4Id; + rCmdSwCtrl.u4Data = prSwCtrlInfo->u4Data; + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_SW_DBG_CTRL_T), + (PUINT_8) &rCmdSwCtrl, pvSetBuffer, u4SetBufferLen); + } + } /* switch(u2Id) */ + + return rWlanStatus; +} + + /* wlanoidSetSwCtrlWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query EEPROM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidQueryEepromRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvQueryBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryEepromRead, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryEepromRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write EEPROM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRwInfo; + CMD_ACCESS_EEPROM rCmdAccessEeprom; + + DEBUGFUNC("wlanoidSetEepromWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prEepromRwInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdAccessEeprom, sizeof(CMD_ACCESS_EEPROM)); + rCmdAccessEeprom.u2Offset = prEepromRwInfo->ucEepromIndex; + rCmdAccessEeprom.u2Data = prEepromRwInfo->u2EepromData; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_EEPROM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ACCESS_EEPROM), + (PUINT_8) &rCmdAccessEeprom, pvSetBuffer, u4SetBufferLen); + +} /* wlanoidSetEepromWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully transmitted +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rTransmittedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of the successfully received +* packets. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRcvOk"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rReceivedFragmentCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryRecvOk, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryRcvOk */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames that the driver +* fails to transmit. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitError"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitError, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitError */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after exactly one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitOneCollision"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) + (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart - + prAdapter->rStatStruct.rRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitOneCollision, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +} /* wlanoidQueryXmitOneCollision */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames successfully +* transmitted after more than one collision. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMoreCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) (prAdapter->rStatStruct.rMultipleRetryCount.QuadPart); + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMoreCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryXmitMoreCollisions */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the number of frames +* not transmitted due to excessive collisions. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryXmitMaxCollisions"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in query receive error! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + *pu4QueryInfoLen = sizeof(UINT_32); + return WLAN_STATUS_ADAPTER_NOT_READY; + } else if (u4QueryBufferLen < sizeof(UINT_32) + || (u4QueryBufferLen > sizeof(UINT_32) && u4QueryBufferLen < sizeof(UINT_64))) { + *pu4QueryInfoLen = sizeof(UINT_64); + return WLAN_STATUS_INVALID_LENGTH; + } +#if CFG_ENABLE_STATISTICS_BUFFERING + if (IsBufferedStatisticsUsable(prAdapter) == TRUE) { + if (u4QueryBufferLen == sizeof(UINT_32)) { + *pu4QueryInfoLen = sizeof(UINT_32); + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rStatStruct.rFailedCount.QuadPart; + } else { + *pu4QueryInfoLen = sizeof(UINT_64); + *(PUINT_64) pvQueryBuffer = (UINT_64) prAdapter->rStatStruct.rFailedCount.QuadPart; + } + + return WLAN_STATUS_SUCCESS; + } +#endif + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_STATISTICS, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryXmitMaxCollisions, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +} /* wlanoidQueryXmitMaxCollisions */ + +#define MTK_CUSTOM_OID_INTERFACE_VERSION 0x00006620 /* for WPDWifi DLL */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current the OID interface version, +* which is the interface between the application and driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryOidInterfaceVersion"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *(PUINT_32) pvQueryBuffer = MTK_CUSTOM_OID_INTERFACE_VERSION; + *pu4QueryInfoLen = sizeof(UINT_32); + + DBGLOG(OID, WARN, "Custom OID interface version: %#08X\n", *(PUINT_32) pvQueryBuffer); + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryOidInterfaceVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#ifndef LINUX + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMcastAddr, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); +#else + return WLAN_STATUS_SUCCESS; +#endif +} /* end of wlanoidQueryMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_8 ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Caller should provide this information */ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(OID, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { + DBGLOG(OID, WARN, "Too many MC addresses\n"); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = ucNetTypeIndex; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_MAC_MCAST_ADDR, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); +} /* end of wlanoidSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 u4NewPacketFilter; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen < sizeof(UINT_32)) { + *pu4SetInfoLen = sizeof(UINT_32); + DBGLOG(OID, INFO, "iput buffer is too small"); + return WLAN_STATUS_INVALID_LENGTH; + } + ASSERT(pvSetBuffer); + + /* Set the new packet filter. */ + u4NewPacketFilter = *(PUINT_32) pvSetBuffer; + + DBGLOG(OID, TRACE, "New packet filter: %#08x\n", u4NewPacketFilter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set current packet filter! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + do { + /* Verify the bits of the new packet filter. If any bits are set that + we don't support, leave. */ + if (u4NewPacketFilter & ~(PARAM_PACKET_FILTER_SUPPORTED)) { + rStatus = WLAN_STATUS_NOT_SUPPORTED; + break; + } +#if DBG + /* Need to enable or disable promiscuous support depending on the new + filter. */ + if (u4NewPacketFilter & PARAM_PACKET_FILTER_PROMISCUOUS) + DBGLOG(OID, TRACE, "Enable promiscuous mode\n"); + else + DBGLOG(OID, TRACE, "Disable promiscuous mode\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_ALL_MULTICAST) + DBGLOG(OID, TRACE, "Enable all-multicast mode\n"); + else if (u4NewPacketFilter & PARAM_PACKET_FILTER_MULTICAST) + DBGLOG(OID, TRACE, "Enable multicast\n"); + else + DBGLOG(OID, TRACE, "Disable multicast\n"); + + if (u4NewPacketFilter & PARAM_PACKET_FILTER_BROADCAST) + DBGLOG(OID, TRACE, "Enable Broadcast\n"); + else + DBGLOG(OID, TRACE, "Disable Broadcast\n"); +#endif + } while (FALSE); + + if (rStatus == WLAN_STATUS_SUCCESS) { + /* Store the packet filter */ + + prAdapter->u4OsPacketFilter &= PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8) &prAdapter->u4OsPacketFilter, pvSetBuffer, u4SetBufferLen); + } else { + return rStatus; + } +} /* wlanoidSetCurrentPacketFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current packet filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryCurrentPacketFilter"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen >= sizeof(UINT_32)) { + ASSERT(pvQueryBuffer); + *(PUINT_32) pvQueryBuffer = prAdapter->u4OsPacketFilter; + } + + return WLAN_STATUS_SUCCESS; +} /* wlanoidQueryCurrentPacketFilter */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query ACPI device power state. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +#if DBG + PPARAM_DEVICE_POWER_STATE prPowerState; +#endif + + DEBUGFUNC("wlanoidQueryAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + +#if DBG + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvQueryBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Query Power State: D0\n"); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Query Power State: D1\n"); + break; + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Query Power State: D2\n"); + break; + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Query Power State: D3\n"); + break; + default: + break; + } +#endif + + /* Since we will disconnect the newwork, therefore we do not + need to check queue empty */ + *(PPARAM_DEVICE_POWER_STATE) pvQueryBuffer = ParamDeviceStateD3; + /* WARNLOG(("Ready to transition to D3\n")); */ + return WLAN_STATUS_SUCCESS; + +} /* pwrmgtQueryPower */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set ACPI device power state. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PPARAM_DEVICE_POWER_STATE prPowerState; + BOOLEAN fgRetValue = TRUE; + + DEBUGFUNC("wlanoidSetAcpiDevicePowerState"); + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_DEVICE_POWER_STATE); + + ASSERT(pvSetBuffer); + prPowerState = (PPARAM_DEVICE_POWER_STATE) pvSetBuffer; + switch (*prPowerState) { + case ParamDeviceStateD0: + DBGLOG(OID, INFO, "Set Power State: D0\n"); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD0); + fgRetValue = nicpmSetAcpiPowerD0(prAdapter); + break; + case ParamDeviceStateD1: + DBGLOG(OID, INFO, "Set Power State: D1\n"); + /* no break here */ + case ParamDeviceStateD2: + DBGLOG(OID, INFO, "Set Power State: D2\n"); + /* no break here */ + case ParamDeviceStateD3: + DBGLOG(OID, INFO, "Set Power State: D3\n"); + fgRetValue = nicpmSetAcpiPowerD3(prAdapter); + kalDevSetPowerState(prAdapter->prGlueInfo, (UINT_32) ParamDeviceStateD3); + break; + default: + break; + } + + if (fgRetValue == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} /* end of wlanoidSetAcpiDevicePowerState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current fragmentation threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryFragThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidQueryFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new fragmentation threshold to the +* driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if CFG_TX_FRAGMENT + + return WLAN_STATUS_SUCCESS; + +#else + + return WLAN_STATUS_NOT_SUPPORTED; +#endif /* CFG_TX_FRAGMENT */ + +} /* end of wlanoidSetFragThreshold() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the current RTS threshold. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryRtsThreshold"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + DBGLOG(OID, LOUD, "\n"); + + if (u4QueryBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + *pu4QueryInfoLen = sizeof(PARAM_RTS_THRESHOLD); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + *((PARAM_RTS_THRESHOLD *) pvQueryBuffer) = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidQueryRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a new RTS threshold to the driver. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PARAM_RTS_THRESHOLD *prRtsThreshold; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_RTS_THRESHOLD); + if (u4SetBufferLen < sizeof(PARAM_RTS_THRESHOLD)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRtsThreshold = (PARAM_RTS_THRESHOLD *) pvSetBuffer; + *prRtsThreshold = prAdapter->rWlanInfo.eRtsThreshold; + + return WLAN_STATUS_SUCCESS; + +} /* wlanoidSetRtsThreshold */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to turn radio off. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + + DEBUGFUNC("wlanoidSetDisassociate"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set disassociate! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + /* prepare message to AIS */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + + /* Send AIS Abort Message */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_OID_AIS_FSM_JOIN_REQ; + prAisAbortMsg->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_NEW_CONNECTION; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + /* indicate for disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + DBGLOG(OID, INFO, "DisconnectByOid\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY, NULL, 0); + } +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + + return WLAN_STATUS_SUCCESS; +} /* wlanoidSetDisassociate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQuery802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + +/* *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE)(prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile); */ + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_AIS_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + + /* hack for CTIA power mode setting function */ + if (prAdapter->fgEnCtiaPowerMode) { + /* set to non-zero value (to prevent MMI query 0, before it intends to set 0, */ + /* which will skip its following state machine) */ + *(PPARAM_POWER_MODE) pvQueryBuffer = (PARAM_POWER_MODE) 2; + } + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSet802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSet802dot11PowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + /* WARNLOG(("Invalid power mode %d\n", */ + /* *(PPARAM_POWER_MODE) pvSetBuffer)); */ + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) + ; + else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + else if (prAdapter->u4CtiaPowerMode == 1) + ePowerMode = Param_PowerModeMAX_PSP; + else if (prAdapter->u4CtiaPowerMode == 2) + ePowerMode = Param_PowerModeFast_PSP; + } + } + + status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, ePowerMode, TRUE); + + switch (ePowerMode) { + case Param_PowerModeCAM: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to CAM (%d)\n", ePowerMode); + break; + case Param_PowerModeMAX_PSP: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to MAX PS (%d)\n", ePowerMode); + break; + case Param_PowerModeFast_PSP: + DBGLOG(OID, INFO, "Set Wi-Fi PS mode to FAST PS (%d)\n", ePowerMode); + break; + default: + DBGLOG(OID, INFO, "invalid Wi-Fi PS mode setting (%d)\n", ePowerMode); + break; + } + + return status; + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current status of AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set AdHoc Mode. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query RF frequency. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryFrequency(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) { + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + *(PUINT_32) pvQueryBuffer = + nicChannelNum2Freq(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].ucPrimaryChannel); + } else { + *(PUINT_32) pvQueryBuffer = 0; + } + } else { + *(PUINT_32) pvQueryBuffer = nicChannelNum2Freq(prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum); + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set RF frequency by User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4FreqInKHz; + + DEBUGFUNC("wlanoidSetFrequency"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4FreqInKHz = (PUINT_32) pvSetBuffer; + + prAdapter->rWifiVar.rConnSettings.ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(*pu4FreqInKHz); + prAdapter->rWifiVar.rConnSettings.eAdHocBand = *pu4FreqInKHz < 5000000 ? BAND_2G4 : BAND_5G; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetFrequency() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set 802.11 channel of the radio frequency. +* This is a proprietary function call to Lunux currently. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChannel(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the Beacon Interval from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryBeaconInterval"); + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED) { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } else { + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2BeaconPeriod; + } + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidQueryBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the Beacon Interval to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4BeaconInterval; + + DEBUGFUNC("wlanoidSetBeaconInterval"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4BeaconInterval = (PUINT_32) pvSetBuffer; + + if ((*pu4BeaconInterval < DOT11_BEACON_PERIOD_MIN) || (*pu4BeaconInterval > DOT11_BEACON_PERIOD_MAX)) { + DBGLOG(OID, TRACE, "Invalid Beacon Interval = %u\n", *pu4BeaconInterval); + return WLAN_STATUS_INVALID_DATA; + } + + prAdapter->rWlanInfo.u2BeaconPeriod = (UINT_16) *pu4BeaconInterval; + + DBGLOG(OID, INFO, "Set beacon interval: %d\n", prAdapter->rWlanInfo.u2BeaconPeriod); + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetBeaconInterval() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the ATIM window from User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + if (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA) + *(PUINT_32) pvQueryBuffer = 0; + else + *(PUINT_32) pvQueryBuffer = (UINT_32) prAdapter->rWlanInfo.u2AtimWindow; + + return WLAN_STATUS_SUCCESS; + +} /* end of wlanoidQueryAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the ATIM window to User Settings. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4AtimWindow; + + DEBUGFUNC("wlanoidSetAtimWindow"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + pu4AtimWindow = (PUINT_32) pvSetBuffer; + + prAdapter->rWlanInfo.u2AtimWindow = (UINT_16) *pu4AtimWindow; + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetAtimWindow() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to Set the MAC address which is currently used by the NIC. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(0); /* // */ + + return WLAN_STATUS_SUCCESS; +} /* end of wlanoidSetCurrentAddr() */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the checksum offload function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + UINT_32 i, u4CSUMFlags; + CMD_BASIC_CONFIG rCmdBasicConfig; + + DEBUGFUNC("wlanoidSetCSUMOffload"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + u4CSUMFlags = *(PUINT_32) pvSetBuffer; + + kalMemZero(&rCmdBasicConfig, sizeof(CMD_BASIC_CONFIG)); + + for (i = 0; i < 6; i++) { /* set to broadcast address for not-specified */ + rCmdBasicConfig.rMyMacAddr[i] = 0xff; + } + + rCmdBasicConfig.ucNative80211 = 0; /* @FIXME: for Vista */ + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_TCP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(2); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_UDP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(1); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_TX_IP) + rCmdBasicConfig.rCsumOffload.u2TxChecksum |= BIT(0); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_TCP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(2); + + if (u4CSUMFlags & CSUM_OFFLOAD_EN_RX_UDP) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(1); + + if (u4CSUMFlags & (CSUM_OFFLOAD_EN_RX_IPv4 | CSUM_OFFLOAD_EN_RX_IPv6)) + rCmdBasicConfig.rCsumOffload.u2RxChecksum |= BIT(0); + + prAdapter->u4CSUMFlags = u4CSUMFlags; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BASIC_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_BASIC_CONFIG), (PUINT_8) &rCmdBasicConfig, pvSetBuffer, u4SetBufferLen); +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; +#if CFG_ENABLE_GTK_FRAME_FILTER + UINT_32 u4IpV4AddrListSize; + P_BSS_INFO_T prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; +#endif + + DEBUGFUNC("wlanoidSetNetworkAddress"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + +#if CFG_ENABLE_GTK_FRAME_FILTER + u4IpV4AddrListSize = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + + (u4IpAddressCount * sizeof(IPV4_NETWORK_ADDRESS)); + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); + prBssInfo->prIpV4NetAddrList = (P_IPV4_NETWORK_ADDRESS_LIST) kalMemAlloc(u4IpV4AddrListSize, VIR_MEM_TYPE); + if (prBssInfo->prIpV4NetAddrList == NULL) { + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return WLAN_STATUS_FAILURE; + } + prBssInfo->prIpV4NetAddrList->ucAddrCount = (UINT_8) u4IpAddressCount; +#endif + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(OID, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); + + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + +#if CFG_ENABLE_GTK_FRAME_FILTER + kalMemCopy(prBssInfo->prIpV4NetAddrList->arNetAddr[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); +#endif + + j++; + + pucBuf = (PUINT_8) &prNetAddrIp->in_addr; + DBGLOG(OID, INFO, + "prNetAddrIp->in_addr:%d:%d:%d:%d\n", pucBuf[0], pucBuf[1], pucBuf[2], + pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) (prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set, +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgTestMode == FALSE) { + /* switch to RF Test mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 1; /* RF test mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + TRUE, + TRUE, + nicCmdEventEnterRfTest, + nicOidCmdEnterRFTestTimeout, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in test mode .. */ + rStatus = WLAN_STATUS_SUCCESS; + } + } else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Enter TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", + u4SetBufferLen, prAdapter->fgTestMode, rStatus); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set driver to switch into normal operation mode from RF test mode +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* should be NULL +* \param[in] u4SetBufferLen The length of the set buffer, should be 0 +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_DATA +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus; + CMD_TEST_CTRL_T rCmdTestCtrl; + + DEBUGFUNC("wlanoidRftestSetTestMode"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 0; + + if (u4SetBufferLen == 0) { + if (prAdapter->fgTestMode == TRUE) { + /* switch to normal mode */ + rCmdTestCtrl.ucAction = 0; /* Switch mode */ + rCmdTestCtrl.u.u4OpMode = 0; /* normal mode */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventLeaveRfTest, + nicOidCmdTimeoutCommon, + sizeof(CMD_TEST_CTRL_T), + (PUINT_8) &rCmdTestCtrl, pvSetBuffer, u4SetBufferLen); + } else { + /* already in normal mode .. */ + rStatus = WLAN_STATUS_SUCCESS; + } + } else { + rStatus = WLAN_STATUS_INVALID_DATA; + } + DBGLOG(OID, INFO, "Abort TestMode, setBufLen %u, InTestMode %d, rStatus %u\n", + u4SetBufferLen, prAdapter->fgTestMode, rStatus); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief query for RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestQueryAutoTest"); + + ASSERT(prAdapter); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4QueryBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(OID, ERROR, "Invalid data. QueryBufferLen: %u.\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvQueryBuffer; + rStatus = rftestQueryATInfo(prAdapter, + prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set RF test parameter +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_MTK_WIFI_TEST_STRUCT_T prRfATInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidRftestSetAutoTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T); + + if (u4SetBufferLen != sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T)) { + DBGLOG(OID, ERROR, "Invalid data. SetBufferLen: %u.\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prRfATInfo = (P_PARAM_MTK_WIFI_TEST_STRUCT_T) pvSetBuffer; + rStatus = rftestSetATInfo(prAdapter, prRfATInfo->u4FuncIndex, prRfATInfo->u4FuncData); + + return rStatus; +} + +/* RF test OID set handler */ +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 1; /* Set ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_CMD_TEST_CTRL_T pCmdTestCtrl; + UINT_8 ucCmdSeqNum; + P_EVENT_TEST_STATUS prTestStatus; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + + if (u4FuncIndex == RF_AT_FUNCID_FW_INFO) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = + (prAdapter->rVerInfo.u2FwProductID << 16) | (prAdapter->rVerInfo.u2FwOwnVersion); + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } else if (u4FuncIndex == RF_AT_FUNCID_DRV_INFO) { + /* driver implementation */ + prTestStatus = (P_EVENT_TEST_STATUS) pvQueryBuffer; + + prTestStatus->rATInfo.u4FuncData = CFG_DRV_OWN_VERSION; + u4QueryBufferLen = sizeof(EVENT_TEST_STATUS); + + return WLAN_STATUS_SUCCESS; + } + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T))); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_GENERAL_IOCTL; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pfCmdDoneHandler = nicCmdEventQueryRfTestATInfo; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_TEST_MODE; + prCmdInfo->fgSetQuery = FALSE; + prCmdInfo->fgNeedResp = TRUE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = sizeof(CMD_TEST_CTRL_T); + prCmdInfo->pvInformationBuffer = pvQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4QueryBufferLen; + + /* Setup WIFI_CMD_T (payload = CMD_TEST_CTRL_T) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + pCmdTestCtrl = (P_CMD_TEST_CTRL_T) (prWifiCmd->aucBuffer); + pCmdTestCtrl->ucAction = 2; /* Get ATInfo */ + pCmdTestCtrl->u.rRfATInfo.u4FuncIndex = u4FuncIndex; + pCmdTestCtrl->u.rRfATInfo.u4FuncData = u4FuncData; + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + return WLAN_STATUS_PENDING; +} + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen) +{ + CMD_TEST_CTRL_T rCmdTestCtrl; + + ASSERT(prAdapter); + + rCmdTestCtrl.ucAction = 5; /* Set Channel Frequency */ + rCmdTestCtrl.u.u4ChannelFreq = u4FreqInKHz; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TEST_MODE, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, sizeof(CMD_TEST_CTRL_T), (PUINT_8) &rCmdTestCtrl, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + prGlueInfo = prAdapter->prGlueInfo; + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + DEBUGFUNC("wlanSendSetQueryCmd"); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(OID, TRACE, "ucCmdSeqNum =%d, ucCID =%d\n", ucCmdSeqNum, ucCID); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI ui to set wapi mode, which is needed to info the the driver +* to operation at WAPI mode while driver initialize. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + DEBUGFUNC("wlanoidSetWapiMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + ASSERT(pvSetBuffer); + + /* Todo:: For support WAPI and Wi-Fi at same driver, use the set wapi assoc ie at the check point */ + /* The Adapter Connection setting fgUseWapi will cleat whil oid set mode (infra), */ + /* And set fgUseWapi True while set wapi assoc ie */ + /* policay selection, add key all depend on this flag, */ + /* The fgUseWapi may remove later */ + if (*(PUINT_32) pvSetBuffer) + prAdapter->fgUseWapi = TRUE; + else + prAdapter->fgUseWapi = FALSE; + +#if 0 + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + 4)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_BUILD_CONNECTION cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + 4; + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_WAPI_MODE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + cp = (PUINT_8) (prWifiCmd->aucBuffer); + + kalMemCopy(cp, (PUINT_8) pvSetBuffer, 4); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +#else + return WLAN_STATUS_SUCCESS; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WAPI to set the assoc info, which is needed to add to +* Association request frame while join WAPI AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_WAPI_INFO_ELEM_T prWapiInfo; + PUINT_8 cp; + UINT_16 u2AuthSuiteCount = 0; + UINT_16 u2PairSuiteCount = 0; + UINT_32 u4AuthKeyMgtSuite = 0; + UINT_32 u4PairSuite = 0; + UINT_32 u4GroupSuite = 0; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWapiAssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen < 20 /* From EID to Group cipher */) { + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + DBGLOG(SEC, INFO, "fgWapiMode = FALSE due to u4SetBufferLen %u < 20!\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prAdapter->rWifiVar.rConnSettings.fgWapiMode = TRUE; + + /* if (prWapiInfo->ucElemId != ELEM_ID_WAPI) */ + /* DBGLOG(SEC, TRACE, ("Not WAPI IE ?!\n")); */ + + /* if (prWapiInfo->ucLength < 18) */ + /* return WLAN_STATUS_INVALID_LENGTH; */ + + *pu4SetInfoLen = u4SetBufferLen; + + prWapiInfo = (P_WAPI_INFO_ELEM_T) pvSetBuffer; + + if (prWapiInfo->ucElemId != ELEM_ID_WAPI) { + DBGLOG(SEC, INFO, "Not WAPI IE ?! u4SetBufferLen = %u\n", u4SetBufferLen); + prAdapter->rWifiVar.rConnSettings.fgWapiMode = FALSE; + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prWapiInfo->ucLength < 18) + return WLAN_STATUS_INVALID_LENGTH; + + /* Skip Version check */ + cp = (PUINT_8) &prWapiInfo->u2AuthKeyMgtSuiteCount; + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + + if (u2AuthSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + cp = (PUINT_8) &prWapiInfo->aucAuthKeyMgtSuite1[0]; + WLAN_GET_FIELD_32(cp, &u4AuthKeyMgtSuite); + + DBGLOG(SEC, TRACE, "WAPI: Assoc Info auth mgt suite [%d]: %02x-%02x-%02x-%02x\n", + u2AuthSuiteCount, + (UCHAR) (u4AuthKeyMgtSuite & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 8) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 16) & 0x000000FF), + (UCHAR) ((u4AuthKeyMgtSuite >> 24) & 0x000000FF)); + + if (u4AuthKeyMgtSuite != WAPI_AKM_SUITE_802_1X && u4AuthKeyMgtSuite != WAPI_AKM_SUITE_PSK) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + if (u2PairSuiteCount > 1) + return WLAN_STATUS_INVALID_LENGTH; + + cp += 2; + WLAN_GET_FIELD_32(cp, &u4PairSuite); + DBGLOG(SEC, TRACE, "WAPI: Assoc Info pairwise cipher suite [%d]: %02x-%02x-%02x-%02x\n", + u2PairSuiteCount, + (UCHAR) (u4PairSuite & 0x000000FF), + (UCHAR) ((u4PairSuite >> 8) & 0x000000FF), + (UCHAR) ((u4PairSuite >> 16) & 0x000000FF), (UCHAR) ((u4PairSuite >> 24) & 0x000000FF)); + + if (u4PairSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + cp += 4; + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + DBGLOG(SEC, TRACE, "WAPI: Assoc Info group cipher suite : %02x-%02x-%02x-%02x\n", + (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (u4GroupSuite != WAPI_CIPHER_SUITE_WPI) + ASSERT(FALSE); + + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite = u4AuthKeyMgtSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher = u4PairSuite; + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher = u4GroupSuite; + + kalMemCopy(prAdapter->prGlueInfo->aucWapiAssocInfoIEs, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2WapiAssocInfoIESz = (UINT_16) u4SetBufferLen; + DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the wpi key to the driver. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer P_PARAM_WPI_KEY, which is set by NDIS, is unpacked. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + P_PARAM_WPI_KEY_T prNewKey; + P_CMD_802_11_KEY prCmdKey; + PUINT_8 pc; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanoidSetWapiKey"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail in set add key! (Adapter not ready). ACPI=D%d, Radio=%d\r\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + prNewKey = (P_PARAM_WPI_KEY_T) pvSetBuffer; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) pvSetBuffer, 560); + pc = (PUINT_8) pvSetBuffer; + + *pu4SetInfoLen = u4SetBufferLen; + + /* Exception check */ + if (prNewKey->ucKeyID != 0x1 || prNewKey->ucKeyID != 0x0) { + prNewKey->ucKeyID = prNewKey->ucKeyID & BIT(0); + /* DBGLOG(SEC, INFO, ("Invalid WAPI key ID (%d)\r\n", prNewKey->ucKeyID)); */ + } + + /* Dump P_PARAM_WPI_KEY_T content. */ + DBGLOG(OID, TRACE, "Set: Dump P_PARAM_WPI_KEY_T content\r\n"); + DBGLOG(OID, TRACE, "TYPE : %d\r\n", prNewKey->eKeyType); + DBGLOG(OID, TRACE, "Direction : %d\r\n", prNewKey->eDirection); + DBGLOG(OID, TRACE, "KeyID : %d\r\n", prNewKey->ucKeyID); + DBGLOG(OID, TRACE, "AddressIndex:\r\n"); + DBGLOG_MEM8(OID, TRACE, prNewKey->aucAddrIndex, 12); + prNewKey->u4LenWPIEK = 16; + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPIEK, (UINT_8) prNewKey->u4LenWPIEK); + prNewKey->u4LenWPICK = 16; + + DBGLOG(OID, TRACE, "CK Key(%d):\r\n", (UINT_8) prNewKey->u4LenWPICK); + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucWPICK, (UINT_8) prNewKey->u4LenWPICK); + DBGLOG(OID, TRACE, "PN:\r\n"); + if (prNewKey->eKeyType == 0) { + prNewKey->aucPN[0] = 0x5c; + prNewKey->aucPN[1] = 0x36; + prNewKey->aucPN[2] = 0x5c; + prNewKey->aucPN[3] = 0x36; + prNewKey->aucPN[4] = 0x5c; + prNewKey->aucPN[5] = 0x36; + prNewKey->aucPN[6] = 0x5c; + prNewKey->aucPN[7] = 0x36; + prNewKey->aucPN[8] = 0x5c; + prNewKey->aucPN[9] = 0x36; + prNewKey->aucPN[10] = 0x5c; + prNewKey->aucPN[11] = 0x36; + prNewKey->aucPN[12] = 0x5c; + prNewKey->aucPN[13] = 0x36; + prNewKey->aucPN[14] = 0x5c; + prNewKey->aucPN[15] = 0x36; + } + + DBGLOG_MEM8(OID, TRACE, (PUINT_8) prNewKey->aucPN, 16); + + prGlueInfo = prAdapter->prGlueInfo; + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetBufferLen)); + + if (!prCmdInfo) { + DBGLOG(OID, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + + /* compose CMD_ID_ADD_REMOVE_KEY cmd pkt */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_AIS_INDEX; + prCmdInfo->u2InfoBufLen = CMD_HDR_SIZE + sizeof(CMD_802_11_KEY); + prCmdInfo->pfCmdDoneHandler = nicCmdEventSetCommon; + prCmdInfo->pfCmdTimeoutHandler = nicOidCmdTimeoutCommon; + prCmdInfo->fgIsOid = TRUE; + prCmdInfo->ucCID = CMD_ID_ADD_REMOVE_KEY; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetBufferLen; + prCmdInfo->pvInformationBuffer = pvSetBuffer; + prCmdInfo->u4InformationBufferLength = u4SetBufferLen; + + /* Setup WIFI_CMD_T */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdKey = (P_CMD_802_11_KEY) (prWifiCmd->aucBuffer); + + kalMemZero(prCmdKey, sizeof(CMD_802_11_KEY)); + + prCmdKey->ucAddRemove = 1; /* Add */ + + if (prNewKey->eKeyType == ENUM_WPI_PAIRWISE_KEY) { + prCmdKey->ucTxKey = 1; + prCmdKey->ucKeyType = 1; + } + + kalMemCopy(prCmdKey->aucPeerAddr, (PUINT_8) prNewKey->aucAddrIndex, MAC_ADDR_LEN); + + prCmdKey->ucNetType = 0; /* AIS */ + + prCmdKey->ucKeyId = prNewKey->ucKeyID; + + prCmdKey->ucKeyLen = 32; + + prCmdKey->ucAlgorithmId = CIPHER_SUITE_WPI; + + kalMemCopy(prCmdKey->aucKeyMaterial, (PUINT_8) prNewKey->aucWPIEK, 16); + + kalMemCopy(prCmdKey->aucKeyMaterial + 16, (PUINT_8) prNewKey->aucWPICK, 16); + + kalMemCopy(prCmdKey->aucKeyRsc, (PUINT_8) prNewKey->aucPN, 16); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + + return WLAN_STATUS_PENDING; +} /* wlanoidSetAddKey */ +#endif + +#if CFG_SUPPORT_WPS2 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the assoc info, which is needed to add to +* Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWSCAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetWSCAssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + kalMemCopy(prAdapter->prGlueInfo->aucWSCAssocInfoIE, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2WSCAssocInfoIELen = (UINT_16) u4SetBufferLen; + DBGLOG(SEC, TRACE, "Assoc Info IE sz %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* FIXME: + * Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_PM_PACKET_PATTERN prPacketPattern; + + DEBUGFUNC("wlanoidSetAddWakeupPattern"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_PM_PACKET_PATTERN); + + if (u4SetBufferLen < sizeof(PARAM_PM_PACKET_PATTERN)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prPacketPattern = (P_PARAM_PM_PACKET_PATTERN) pvSetBuffer; + + /* FIXME: + * Send the struct to firmware */ + + return WLAN_STATUS_FAILURE; +} + +WLAN_STATUS +wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidQueryEnableWakeup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + if (u4QueryBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_BUFFER_TOO_SHORT; + + pu4WakeupEventEnable = (PUINT_32) pvQueryBuffer; + + *pu4WakeupEventEnable = prAdapter->u4WakeupEventEnable; + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4WakeupEventEnable; + + DEBUGFUNC("wlanoidSetEnableWakup"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + + if (u4SetBufferLen < sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + pu4WakeupEventEnable = (PUINT_32) pvSetBuffer; + prAdapter->u4WakeupEventEnable = *pu4WakeupEventEnable; + + /* FIXME: + * Send Command Event for setting wakeup-pattern / Magic Packet to firmware + * */ + + return WLAN_STATUS_FAILURE; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure PS related settings for WMM-PS test. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T prWmmPsTestInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_SET_WMM_PS_TEST_STRUCT_T rSetWmmPsTestParam; + UINT_16 u2CmdBufLen; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetWiFiWmmPsTest"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T); + + prWmmPsTestInfo = (P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T) pvSetBuffer; + + rSetWmmPsTestParam.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rSetWmmPsTestParam.bmfgApsdEnAc = prWmmPsTestInfo->bmfgApsdEnAc; + rSetWmmPsTestParam.ucIsEnterPsAtOnce = prWmmPsTestInfo->ucIsEnterPsAtOnce; + rSetWmmPsTestParam.ucIsDisableUcTrigger = prWmmPsTestInfo->ucIsDisableUcTrigger; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[rSetWmmPsTestParam.ucNetTypeIndex]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + prPmProfSetupInfo->ucBmpDeliveryAC = (rSetWmmPsTestParam.bmfgApsdEnAc >> 4) & BITS(0, 3); + prPmProfSetupInfo->ucBmpTriggerAC = rSetWmmPsTestParam.bmfgApsdEnAc & BITS(0, 3); + + u2CmdBufLen = sizeof(CMD_SET_WMM_PS_TEST_STRUCT_T); + +#if 0 + /* it will apply the disable trig or not immediately */ + if (prPmInfo->ucWmmPsDisableUcPoll && prPmInfo->ucWmmPsConnWithTrig) + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, TRUE); */ + else + ; /* NIC_PM_WMM_PS_DISABLE_UC_TRIG(prAdapter, FALSE); */ +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, CMD_ID_SET_WMM_PS_TEST_PARMS, TRUE, FALSE, TRUE, NULL, /* TODO? */ + NULL, u2CmdBufLen, (PUINT_8) &rSetWmmPsTestParam, NULL, 0); + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure enable/disable TX A-MPDU feature. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_TX_AMPDU_T rTxAmpdu; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetTxAmpdu"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rTxAmpdu.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_TX_AMPDU_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AMPDU, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rTxAmpdu, NULL, 0); + + return rStatus; +} /* wlanoidSetTxAmpdu */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to configure reject/accept ADDBA Request. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + CMD_ADDBA_REJECT_T rAddbaReject; + UINT_16 u2CmdBufLen; + PBOOLEAN pfgEnable; + + DEBUGFUNC("wlanoidSetAddbaReject"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(BOOLEAN); + + pfgEnable = (PBOOLEAN) pvSetBuffer; + + rAddbaReject.fgEnable = *pfgEnable; + + u2CmdBufLen = sizeof(CMD_ADDBA_REJECT_T); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_ADDBA_REJECT, + TRUE, FALSE, TRUE, NULL, NULL, u2CmdBufLen, (PUINT_8) &rAddbaReject, NULL, 0); + + return rStatus; +} /* wlanoidSetAddbaReject */ + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + + DEBUGFUNC("wlanoidQuerySLTStatus"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvQueryBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_LP_SET: + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + prLpSetting->u4BcnRcvNum = prSltInfo->u4BeaconReceiveCnt; + } + break; + default: + /* TBD... */ + break; + } + + return rWlanStatus; +} /* wlanoidQuerySLTStatus */ + +WLAN_STATUS +wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_MTK_SLT_TEST_STRUCT_T prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) NULL; + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + /* 1. Action: Update or Initial Set + * 2. Role. + * 3. Target MAC address. + * 4. RF BW & Rate Settings + */ + + DEBUGFUNC("wlanoidUpdateSLTMode"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_MTK_SLT_TEST_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_MTK_SLT_TEST_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prMtkSltInfo = (P_PARAM_MTK_SLT_TEST_STRUCT_T) pvSetBuffer; + + prSltInfo = &(prAdapter->rWifiVar.rSltInfo); + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + switch (prMtkSltInfo->rSltFuncIdx) { + case ENUM_MTK_SLT_FUNC_INITIAL: /* Initialize */ + { + P_PARAM_MTK_SLT_INITIAL_STRUCT_T prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_INITIAL_STRUCT_T)); + + prMtkSltInit = (P_PARAM_MTK_SLT_INITIAL_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoStaRec != NULL) { + /* The driver has been initialized. */ + prSltInfo->prPseudoStaRec = NULL; + } + + prSltInfo->prPseudoBssDesc = scanSearchExistingBssDesc(prAdapter, + BSS_TYPE_IBSS, + prMtkSltInit->aucTargetMacAddr, + prMtkSltInit->aucTargetMacAddr); + + prSltInfo->u2SiteID = prMtkSltInit->u2SiteID; + + /* Bandwidth 2.4G: Channel 1~14 + * Bandwidth 5G: *36, 40, 44, 48, 52, 56, 60, 64, + * *100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, + * 149, 153, *157, 161, + * 184, 188, 192, 196, 200, 204, 208, 212, *216 + */ + prSltInfo->ucChannel2G4 = 1 + (prSltInfo->u2SiteID % 4) * 5; + + switch (prSltInfo->ucChannel2G4) { + case 1: + prSltInfo->ucChannel5G = 36; + break; + case 6: + prSltInfo->ucChannel5G = 52; + break; + case 11: + prSltInfo->ucChannel5G = 104; + break; + case 16: + prSltInfo->ucChannel2G4 = 14; + prSltInfo->ucChannel5G = 161; + break; + default: + ASSERT(FALSE); + } + + if (prSltInfo->prPseudoBssDesc == NULL) { + do { + prSltInfo->prPseudoBssDesc = scanAllocateBssDesc(prAdapter); + + if (prSltInfo->prPseudoBssDesc == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + } while (FALSE); + } else { + prBssDesc = prSltInfo->prPseudoBssDesc; + } + + if (prBssDesc) { + prBssDesc->eBSSType = BSS_TYPE_IBSS; + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prMtkSltInit->aucTargetMacAddr); + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + + prBssDesc->u2BeaconInterval = 100; + prBssDesc->u2ATIMWindow = 0; + prBssDesc->ucDTIMPeriod = 1; + + prBssDesc->u2IELength = 0; + + prBssDesc->fgIsERPPresent = TRUE; + prBssDesc->fgIsHTPresent = TRUE; + + prBssDesc->u2OperationalRateSet = BIT(RATE_36M_INDEX); + prBssDesc->u2BSSBasicRateSet = BIT(RATE_36M_INDEX); + prBssDesc->fgIsUnknownBssBasicRate = FALSE; + + prBssDesc->fgIsLargerTSF = TRUE; + + prBssDesc->eBand = BAND_2G4; + + prBssDesc->ucChannelNum = prSltInfo->ucChannel2G4; + + prBssDesc->ucPhyTypeSet = PHY_TYPE_SET_802_11ABGN; + + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + } + } + break; + case ENUM_MTK_SLT_FUNC_RATE_SET: /* Update RF Settings. */ + if (prSltInfo->prPseudoStaRec == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + P_PARAM_MTK_SLT_TR_TEST_STRUCT_T prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_TR_TEST_STRUCT_T)); + + prStaRec = prSltInfo->prPseudoStaRec; + prTRSetting = (P_PARAM_MTK_SLT_TR_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->eBand = BAND_5G; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel5G; + } + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM24) { + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = prSltInfo->ucChannel2G4; + } + + if ((prTRSetting->u4FixedRate & FIXED_BW_DL40) != 0) { + /* RF 40 */ + /* It would controls RFBW capability in WTBL. */ + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + /* This controls RF BW, RF BW would be 40 only if */ + /* 1. PHY_TYPE_BIT_HT is TRUE. */ + /* 2. SCO is SCA/SCB. */ + prStaRec->ucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + + /* U20/L20 Control. */ + switch (prTRSetting->u4FixedRate & 0xC000) { + case FIXED_EXT_CHNL_U20: + prBssInfo->eBssSCO = CHNL_EXT_SCB; /* +2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) + prBssInfo->ucPrimaryChannel += 2; + else { + /* For channel 1, testing L20 at channel 8. */ + if (prBssInfo->ucPrimaryChannel < 5) + prBssInfo->ucPrimaryChannel = 8; + } + break; + case FIXED_EXT_CHNL_L20: + default: /* 40M */ + prBssInfo->eBssSCO = CHNL_EXT_SCA; /* -2 */ + if (prTRSetting->rNetworkType == PARAM_NETWORK_TYPE_OFDM5) { + prBssInfo->ucPrimaryChannel -= 2; + } else { + /* For channel 11 / 14. testing U20 at channel 3. */ + if (prBssInfo->ucPrimaryChannel > 10) + prBssInfo->ucPrimaryChannel = 3; + } + break; + } + } else { + /* RF 20 */ + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + } + + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + + nicUpdateBss(prAdapter, prBssInfo->ucNetTypeIndex); + + prStaRec->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + switch (prTRSetting->u4FixedRate & 0xFF) { + case RATE_OFDM_54M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_54M_INDEX); + break; + case RATE_OFDM_48M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_48M_INDEX); + break; + case RATE_OFDM_36M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + case RATE_OFDM_24M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_24M_INDEX); + break; + case RATE_OFDM_6M: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_6M_INDEX); + break; + case RATE_CCK_11M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_11M_INDEX); + break; + case RATE_CCK_1M_LONG: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_1M_INDEX); + break; + case RATE_GF_MCS_0: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + case RATE_MM_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_HT_GF; +#if 0 /* Only for Current Measurement Mode. */ + prStaRec->u2HtCapInfo |= (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); +#endif + break; + case RATE_GF_MCS_7: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_HT_PHY_INDEX); + prStaRec->u2HtCapInfo |= HT_CAP_INFO_HT_GF; + break; + default: + prStaRec->u2DesiredNonHTRateSet = BIT(RATE_36M_INDEX); + break; + } + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + break; + case ENUM_MTK_SLT_FUNC_LP_SET: /* Reset LP Test Result. */ + { + P_PARAM_MTK_SLT_LP_TEST_STRUCT_T prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) NULL; + + ASSERT(prMtkSltInfo->u4FuncInfoLen == sizeof(PARAM_MTK_SLT_LP_TEST_STRUCT_T)); + + prLpSetting = (P_PARAM_MTK_SLT_LP_TEST_STRUCT_T) &prMtkSltInfo->unFuncInfoContent; + + if (prSltInfo->prPseudoBssDesc == NULL) { + /* Please initial SLT Mode first. */ + break; + } + prBssDesc = prSltInfo->prPseudoBssDesc; + + switch (prLpSetting->rLpTestMode) { + case ENUM_MTK_LP_TEST_NORMAL: + /* In normal mode, we would use target MAC address to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + prSltInfo->fgIsDUT = FALSE; + break; + case ENUM_MTK_LP_TEST_GOLDEN_SAMPLE: + /* 1. Lower AIFS of BCN queue. + * 2. Fixed Random Number tobe 0. + */ + prSltInfo->fgIsDUT = FALSE; + /* In LP test mode, we would use MAC address of Golden Sample to be the BSSID. */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssInfo->aucOwnMacAddr); + break; + case ENUM_MTK_LP_TEST_DUT: + /* 1. Enter Sleep Mode. + * 2. Fix random number a large value & enlarge AIFN of BCN queue. + */ + COPY_MAC_ADDR(prBssDesc->aucBSSID, prBssDesc->aucSrcAddr); + prSltInfo->u4BeaconReceiveCnt = 0; + prSltInfo->fgIsDUT = TRUE; + break; + } + + } + + break; + default: + break; + } + + return WLAN_STATUS_FAILURE; + + return rWlanStatus; +} /* wlanoidUpdateSLTMode */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query NVRAM value. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + UINT_16 u2Data; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidQueryNvramRead"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4QueryBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvQueryBuffer; + + if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_READ) { + /* change to byte offset */ + fgStatus = kalCfgDataRead16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, + &u2Data); + + if (fgStatus) { + prNvramRwInfo->u2EepromData = u2Data; + DBGLOG(OID, INFO, "NVRAM Read: index=%#X, data=%#02X\r\n", + prNvramRwInfo->ucEepromIndex, u2Data); + } else { + DBGLOG(OID, ERROR, "NVRAM Read Failed: index=%#x.\r\n", prNvramRwInfo->ucEepromIndex); + rStatus = WLAN_STATUS_FAILURE; + } + } else if (prNvramRwInfo->ucEepromMethod == PARAM_EEPROM_READ_METHOD_GETSIZE) { + prNvramRwInfo->u2EepromData = CFG_FILE_WIFI_REC_SIZE; + DBGLOG(OID, INFO, "EEPROM size =%d\r\n", prNvramRwInfo->u2EepromData); + } + + *pu4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + return rStatus; +} /* wlanoidQueryNvramRead */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to write NVRAM value. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T prNvramRwInfo; + BOOLEAN fgStatus; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + DEBUGFUNC("wlanoidSetNvramWrite"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNvramRwInfo = (P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T) pvSetBuffer; + + /* change to byte offset */ + fgStatus = kalCfgDataWrite16(prAdapter->prGlueInfo, + prNvramRwInfo->ucEepromIndex << 1, + prNvramRwInfo->u2EepromData); + + if (fgStatus == FALSE) { + DBGLOG(OID, ERROR, "NVRAM Write Failed.\r\n"); + rStatus = WLAN_STATUS_FAILURE; + } + + return rStatus; +} /* wlanoidSetNvramWrite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(ENUM_CFG_SRC_TYPE_T); + + if (kalIsConfigurationExist(prAdapter->prGlueInfo) == TRUE) + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_NVRAM; + else + *(P_ENUM_CFG_SRC_TYPE_T) pvQueryBuffer = CFG_SRC_TYPE_EEPROM; + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + ASSERT(prAdapter); + + *pu4QueryInfoLen = sizeof(P_ENUM_EEPROM_TYPE_T); + +#if CFG_SUPPORT_NIC_CAPABILITY + if (prAdapter->fgIsEepromUsed == TRUE) + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_PRESENT; + else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#else + *(P_ENUM_EEPROM_TYPE_T) pvQueryBuffer = EEPROM_TYPE_NO; +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get the config data source type. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_8 pucCountry; + UINT_16 u2CountryCode; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(u4SetBufferLen == 2); + + *pu4SetInfoLen = 2; + + pucCountry = pvSetBuffer; + u2CountryCode = (((UINT_16) pucCountry[0]) << 8) | ((UINT_16) pucCountry[1]); + + /* previous country code == FF : ignore country code, current country code == FE : resume */ + if (prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup == COUNTRY_CODE_FF) { + if (u2CountryCode != COUNTRY_CODE_FE) { + DBGLOG(OID, INFO, "Skip country code cmd (0x%04x)\n", u2CountryCode); + return WLAN_STATUS_SUCCESS; + } + DBGLOG(OID, INFO, "Resume handle country code cmd (0x%04x)\n", u2CountryCode); + } + + prAdapter->rWifiVar.rConnSettings.u2CountryCode = u2CountryCode; + prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + DBGLOG(OID, LOUD, "u2CountryCodeBakup=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCodeBakup); + + /* Force to re-search country code in country domains */ + prAdapter->prDomainInfo = NULL; + rlmDomainSendCmd(prAdapter, TRUE); + + /* Update supported channel list in channel table based on current country domain */ + wlanUpdateChannelTable(prAdapter->prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set BT profile or BT information and the +* driver will set the built-in PTA configuration into chip. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + P_PTA_IPC_T prPtaIpc; + + DEBUGFUNC("wlanoidSetBT.\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PTA_IPC_T); + if (u4SetBufferLen != sizeof(PTA_IPC_T)) { + WARNLOG(("Invalid length %u\n", u4SetBufferLen)); + return WLAN_STATUS_INVALID_LENGTH; + } + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set BT profile because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + prPtaIpc = (P_PTA_IPC_T) pvSetBuffer; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(OID, INFO, + "BCM BWCS CMD: BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]; + +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BWCS, + TRUE, FALSE, FALSE, NULL, NULL, sizeof(PTA_IPC_T), (PUINT_8) prPtaIpc, NULL, 0); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query current BT profile and BTCR values +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvQueryBuffer Pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ +/* P_PARAM_PTA_IPC_T prPtaIpc; */ +/* UINT_32 u4QueryBuffLen; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PTA_IPC_T); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(PTA_IPC_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); +/* prPtaIpc = (P_PTA_IPC_T)pvQueryBuffer; */ +/* prPtaIpc->ucCmd = BT_CMD_PROFILE; */ +/* prPtaIpc->ucLen = sizeof(prPtaIpc->u); */ +/* nicPtaGetProfile(prAdapter, (PUINT_8)&prPtaIpc->u, &u4QueryBuffLen); */ + + return WLAN_STATUS_SUCCESS; +} + +#if 0 +WLAN_STATUS +wlanoidQueryBtSingleAntenna(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4SingleAntenna; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4SingleAntenna = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgSingleAntenna) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 1\r\n")); */ + *pu4SingleAntenna = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Q Single Ant = 0\r\n")); */ + *pu4SingleAntenna = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetBtSingleAntenna(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + + PUINT_32 pu4SingleAntenna; + UINT_32 u4SingleAntenna; + P_PTA_INFO_T prPtaInfo; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + prPtaInfo = &prAdapter->rPtaInfo; + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set antenna because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4SingleAntenna = (PUINT_32) pvSetBuffer; + u4SingleAntenna = *pu4SingleAntenna; + + if (u4SingleAntenna == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 0\r\n")); */ + prPtaInfo->fgSingleAntenna = FALSE; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Single Ant = 1\r\n")); */ + prPtaInfo->fgSingleAntenna = TRUE; + } + ptaFsmRunEventSetConfig(prAdapter, &prPtaInfo->rPtaParam); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS +WLAN_STATUS +wlanoidQueryPta(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PTA_INFO_T prPtaInfo; + PUINT_32 pu4Pta; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + /* Check for query buffer length */ + if (u4QueryBufferLen != sizeof(UINT_32)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4QueryBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + ASSERT(pvQueryBuffer); + + prPtaInfo = &prAdapter->rPtaInfo; + pu4Pta = (PUINT_32) pvQueryBuffer; + + if (prPtaInfo->fgEnabled) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 1\r\n")); */ + *pu4Pta = 1; + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"PTA = 0\r\n")); */ + *pu4Pta = 0; + } + + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS +wlanoidSetPta(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + PUINT_32 pu4PtaCtrl; + UINT_32 u4PtaCtrl; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(UINT_32); + if (u4SetBufferLen != sizeof(UINT_32)) + return WLAN_STATUS_INVALID_LENGTH; + + if (IS_ARB_IN_RFTEST_STATE(prAdapter)) + return WLAN_STATUS_SUCCESS; + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(OID, WARN, "Fail to set BT setting because of ACPI_D3\n"); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pvSetBuffer); + pu4PtaCtrl = (PUINT_32) pvSetBuffer; + u4PtaCtrl = *pu4PtaCtrl; + + if (u4PtaCtrl == 0) { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 0\r\n")); */ + nicPtaSetFunc(prAdapter, FALSE); + } else { + /* DBGLOG(OID, INFO, (KERN_WARNING DRV_NAME"Set Pta= 1\r\n")); */ + nicPtaSetFunc(prAdapter, TRUE); + } + + return WLAN_STATUS_SUCCESS; +} +#endif + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Tx power profile. +* +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + /* P_SET_TXPWR_CTRL_T pTxPwr = (P_SET_TXPWR_CTRL_T)pvSetBuffer; */ + /* UINT_32 i; */ + WLAN_STATUS rStatus; + + DEBUGFUNC("wlanoidSetTxPower"); + DBGLOG(OID, LOUD, "\r\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + +#if 0 + DBGLOG(OID, INFO, "c2GLegacyStaPwrOffset=%d\n", pTxPwr->c2GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c2GHotspotPwrOffset=%d\n", pTxPwr->c2GHotspotPwrOffset); + DBGLOG(OID, INFO, "c2GP2pPwrOffset=%d\n", pTxPwr->c2GP2pPwrOffset); + DBGLOG(OID, INFO, "c2GBowPwrOffset=%d\n", pTxPwr->c2GBowPwrOffset); + DBGLOG(OID, INFO, "c5GLegacyStaPwrOffset=%d\n", pTxPwr->c5GLegacyStaPwrOffset); + DBGLOG(OID, INFO, "c5GHotspotPwrOffset=%d\n", pTxPwr->c5GHotspotPwrOffset); + DBGLOG(OID, INFO, "c5GP2pPwrOffset=%d\n", pTxPwr->c5GP2pPwrOffset); + DBGLOG(OID, INFO, "c5GBowPwrOffset=%d\n", pTxPwr->c5GBowPwrOffset); + DBGLOG(OID, INFO, "ucConcurrencePolicy=%d\n", pTxPwr->ucConcurrencePolicy); + + for (i = 0; i < 14; i++) + DBGLOG(OID, INFO, "acTxPwrLimit2G[%d]=%d\n", i, pTxPwr->acTxPwrLimit2G[i]); + + for (i = 0; i < 4; i++) + DBGLOG(OID, INFO, "acTxPwrLimit5G[%d]=%d\n", i, pTxPwr->acTxPwrLimit5G[i]); +#endif + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_TXPWR_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + TRUE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetBufferLen, /* u4SetQueryInfoLen */ + (PUINT_8) pvSetBuffer, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + return rStatus; + +} + +WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_CMD_DUMP_MEM prCmdDumpMem; + CMD_DUMP_MEM rCmdDumpMem; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4MemSize = PARAM_MEM_DUMP_MAX_SIZE; + + UINT_32 u4RemainLeng = 0; + UINT_32 u4CurAddr = 0; + UINT_8 ucFragNum = 0; + + prCmdDumpMem = &rCmdDumpMem; + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + + u4RemainLeng = prMemDumpInfo->u4RemainLength; + u4CurAddr = prMemDumpInfo->u4Address + prMemDumpInfo->u4Length; + ucFragNum = prMemDumpInfo->ucFragNum + 1; + + /* Query. If request length is larger than max length, do it as ping pong. + * Send a command and wait for a event. Send next command while the event is received. + * + */ + do { + UINT_32 u4CurLeng = 0; + + if (u4RemainLeng > u4MemSize) { + u4CurLeng = u4MemSize; + u4RemainLeng -= u4MemSize; + } else { + u4CurLeng = u4RemainLeng; + u4RemainLeng = 0; + } + + prCmdDumpMem->u4Address = u4CurAddr; + prCmdDumpMem->u4Length = u4CurLeng; + prCmdDumpMem->u4RemainLength = u4RemainLeng; + prCmdDumpMem->ucFragNum = ucFragNum; + + DBGLOG(OID, TRACE, "[%d] 0x%X, len %u, remain len %u\n", + ucFragNum, + prCmdDumpMem->u4Address, prCmdDumpMem->u4Length, prCmdDumpMem->u4RemainLength); + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_DUMP_MEM, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryMemDump, + nicOidCmdTimeoutCommon, + sizeof(CMD_DUMP_MEM), + (PUINT_8) prCmdDumpMem, pvQueryBuffer, u4QueryBufferLen); + + } while (FALSE); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to dump memory. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + + DEBUGFUNC("wlanoidQueryMemDump"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_32); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) pvQueryBuffer; + DBGLOG(OID, TRACE, "Dump 0x%X, len %u\n", prMemDumpInfo->u4Address, prMemDumpInfo->u4Length); + + prMemDumpInfo->u4RemainLength = prMemDumpInfo->u4Length; + prMemDumpInfo->u4Length = 0; + prMemDumpInfo->ucFragNum = 0; + + return wlanSendMemDumpCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen); + +} /* end of wlanoidQueryMcrRead() */ + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the p2p mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_PARAM_CUSTOM_P2P_SET_STRUCT_T prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) NULL; + /* P_MSG_P2P_NETDEV_REGISTER_T prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T)NULL; */ + DEBUGFUNC("wlanoidSetP2pMode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T); + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T)) { + DBGLOG(OID, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } + + prSetP2P = (P_PARAM_CUSTOM_P2P_SET_STRUCT_T) pvSetBuffer; + + DBGLOG(P2P, INFO, "Set P2P enable %p [%u] mode[%u]\n", prSetP2P, prSetP2P->u4Enable, prSetP2P->u4Mode); + + /* + * enable = 1, mode = 0 => init P2P network + * enable = 1, mode = 1 => init Soft AP network + * enable = 0 => uninit P2P/AP network + */ + + if (prSetP2P->u4Enable) { + p2pSetMode((prSetP2P->u4Mode == 1) ? TRUE : FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + + } else { + DBGLOG(P2P, TRACE, "prAdapter->fgIsP2PRegistered = %d\n", prAdapter->fgIsP2PRegistered); + + if (prAdapter->fgIsP2PRegistered) { + DBGLOG(P2P, INFO, "p2pRemove\n"); + p2pRemove(prAdapter->prGlueInfo); + } + + } + +#if 0 + prP2pNetdevRegMsg = (P_MSG_P2P_NETDEV_REGISTER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_NETDEV_REGISTER_T))); + + if (prP2pNetdevRegMsg == NULL) { + ASSERT(FALSE); + status = WLAN_STATUS_RESOURCES; + return status; + } + + prP2pNetdevRegMsg->rMsgHdr.eMsgId = MID_MNY_P2P_NET_DEV_REGISTER; + prP2pNetdevRegMsg->fgIsEnable = (prSetP2P->u4Enable == 1) ? TRUE : FALSE; + prP2pNetdevRegMsg->ucMode = (UINT_8) prSetP2P->u4Mode; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pNetdevRegMsg, MSG_SEND_METHOD_BUF); +#endif + + return status; +} +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query build date code information from firmware +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_GET_BUILD_DATE_CODE rCmdGetBuildDateCode; + + DEBUGFUNC("wlanoidQueryBuildDateCode"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(UINT_8) * 16; + + if (u4QueryBufferLen < sizeof(UINT_8) * 16) + return WLAN_STATUS_INVALID_LENGTH; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BUILD_DATE_CODE, + FALSE, + TRUE, + TRUE, + nicCmdEventBuildDateCode, + nicOidCmdTimeoutCommon, + sizeof(CMD_GET_BUILD_DATE_CODE), + (PUINT_8) &rCmdGetBuildDateCode, pvQueryBuffer, u4QueryBufferLen); + +} /* end of wlanoidQueryBuildDateCode() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query BSS info from firmware +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + EVENT_AIS_BSS_INFO_T rCmdBSSInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); + + if (u4QueryBufferLen < sizeof(EVENT_AIS_BSS_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + kalMemZero(&rCmdBSSInfo, sizeof(EVENT_AIS_BSS_INFO_T)); + /* + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BSS_INFO, + FALSE, + TRUE, + TRUE, + nicCmdEventGetBSSInfo, + nicOidCmdTimeoutCommon, + sizeof(P_EVENT_AIS_BSS_INFO_T), + (PUINT_8) &rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); + */ + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_BSS_INFO, + FALSE, + TRUE, + TRUE, + nicCmdEventGetBSSInfo, + nicOidCmdTimeoutCommon, + sizeof(EVENT_AIS_BSS_INFO_T), + (PUINT_8) & rCmdBSSInfo, pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} /* wlanoidSetWiFiWmmPsTest */ + +#if CFG_SUPPORT_BATCH_SCAN + +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define BATCHING_SET "SET" +#define BATCHING_GET "GET" +#define BATCHING_STOP "STOP" + +#define PARAM_SCANFREQ "SCANFREQ" +#define PARAM_MSCAN "MSCAN" +#define PARAM_BESTN "BESTN" +#define PARAM_CHANNEL "CHANNEL" +#define PARAM_RTT "RTT" + +WLAN_STATUS +batchSetCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4WritenLen) +{ + P_CHANNEL_INFO_T prRfChannelInfo; + CMD_BATCH_REQ_T rCmdBatchReq; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PCHAR head, p, p2; + UINT_32 tokens; + INT_32 scanfreq, mscan, bestn, rtt; + + DBGLOG(SCN, TRACE, "[BATCH] command=%s, len=%u\n", (PCHAR) pvSetBuffer, (UINT_32) u4SetBufferLen); + + if (!pu4WritenLen) + return -EINVAL; + *pu4WritenLen = 0; + + if (u4SetBufferLen < kalStrLen(CMD_WLS_BATCHING)) { + DBGLOG(SCN, TRACE, "[BATCH] invalid len %u\n", (UINT_32) u4SetBufferLen); + return -EINVAL; + } + + head = pvSetBuffer + kalStrLen(CMD_WLS_BATCHING) + 1; + kalMemSet(&rCmdBatchReq, 0, sizeof(CMD_BATCH_REQ_T)); + + if (!kalStrnCmp(head, BATCHING_SET, kalStrLen(BATCHING_SET))) { + + DBGLOG(SCN, TRACE, "XXX Start Batch Scan XXX\n"); + + head += kalStrLen(BATCHING_SET) + 1; + + /* SCANFREQ, MSCAN, BESTN */ + tokens = kalSScanf(head, "SCANFREQ=%d MSCAN=%d BESTN=%d", &scanfreq, &mscan, &bestn); + if (tokens != 3) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, SCANFREQ=%d MSCAN=%d BESTN=%d\n", + (UINT_32) tokens, scanfreq, mscan, bestn); + return -EINVAL; + } + /* RTT */ + p = kalStrStr(head, PARAM_RTT); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse RTT fail. head=%s\n", head); + return -EINVAL; + } + tokens = kalSScanf(p, "RTT=%d", &rtt); + if (tokens != 1) { + DBGLOG(SCN, TRACE, "[BATCH] Parse fail: tokens=%u, rtt=%d\n", (UINT_32) tokens, rtt); + return -EINVAL; + } + /* CHANNEL */ + p = kalStrStr(head, PARAM_CHANNEL); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(1)\n"); + return -EINVAL; + } + head = p; + p = kalStrChr(head, '>'); + if (!p) { + DBGLOG(SCN, TRACE, "[BATCH] Parse CHANNEL fail(2)\n"); + return -EINVAL; + } + /* else { + *p = '.'; // remove '>' because sscanf can not parse <%s> + }*/ + /*tokens = kalSScanf(head, "CHANNEL=<%s", c_channel); + if (tokens != 1) { + DBGLOG(SCN, TRACE, ("[BATCH] Parse fail: tokens=%d, CHANNEL=<%s>\n", + tokens, c_channel)); + return -EINVAL; + } */ + rCmdBatchReq.ucChannelType = SCAN_CHANNEL_SPECIFIED; + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + p = head + kalStrLen(PARAM_CHANNEL) + 2; /* c_channel; */ + while ((p2 = kalStrSep((char **)&p, ",")) != NULL) { + if (p2 == NULL || *p2 == 0) + break; + if (*p2 == '\0') + continue; + if (*p2 == 'A') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_2G4 ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_5G; + } else if (*p2 == 'B') { + rCmdBatchReq.ucChannelType = + rCmdBatchReq.ucChannelType == + SCAN_CHANNEL_5G ? SCAN_CHANNEL_FULL : SCAN_CHANNEL_2G4; + } else { + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = kalStrtol(p2, NULL, 0); + DBGLOG(SCN, TRACE, "Scanning Channel:%u, freq: %d\n", + (UINT_32) prRfChannelInfo->ucChannelNum, + (UINT_32) nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = prRfChannelInfo->ucChannelNum < 15 ? BAND_2G4 : BAND_5G; + + rCmdBatchReq.ucChannelListNum++; + if (rCmdBatchReq.ucChannelListNum >= 32) + break; + prRfChannelInfo++; + } + } + + /* set channel for test */ +#if 0 + rCmdBatchReq.ucChannelType = 4; /* SCAN_CHANNEL_SPECIFIED; */ + rCmdBatchReq.ucChannelListNum = 0; + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (i = 1; i <= 14; i++) { + + /* filter out some */ + if (i == 1 || i == 5 || i == 11) + continue; + + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo->ucChannelNum = i; + DBGLOG(SCN, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, + nicChannelNum2Freq(prRfChannelInfo->ucChannelNum)); + prRfChannelInfo->ucBand = BAND_2G4; + + rCmdBatchReq.ucChannelListNum++; + prRfChannelInfo++; + } +#endif +#if 0 + rCmdBatchReq.ucChannelType = 0; /* SCAN_CHANNEL_FULL; */ +#endif + + rCmdBatchReq.u4Scanfreq = scanfreq; + rCmdBatchReq.ucMScan = mscan > CFG_BATCH_MAX_MSCAN ? CFG_BATCH_MAX_MSCAN : mscan; + rCmdBatchReq.ucBestn = bestn; + rCmdBatchReq.ucRtt = rtt; + DBGLOG(SCN, TRACE, "[BATCH] SCANFREQ=%u MSCAN=%u BESTN=%u RTT=%u\n", + (UINT_32) rCmdBatchReq.u4Scanfreq, + (UINT_32) rCmdBatchReq.ucMScan, + (UINT_32) rCmdBatchReq.ucBestn, (UINT_32) rCmdBatchReq.ucRtt; + + if (rCmdBatchReq.ucChannelType != SCAN_CHANNEL_SPECIFIED) { + DBGLOG(SCN, TRACE, "[BATCH] CHANNELS = %s\n", + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_FULL ? "FULL" : + rCmdBatchReq.ucChannelType == SCAN_CHANNEL_2G4 ? "2.4G all" : "5G all"); + } else { + DBGLOG(SCN, TRACE, "[BATCH] CHANNEL list\n"); + prRfChannelInfo = &rCmdBatchReq.arChannelList[0]; + for (tokens = 0; tokens < rCmdBatchReq.ucChannelListNum; tokens++) { + DBGLOG(SCN, TRACE, "[BATCH] %s, %d\n", + prRfChannelInfo->ucBand == BAND_2G4 ? "2.4G" : "5G", + prRfChannelInfo->ucChannelNum); + prRfChannelInfo++; + } + } + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_START; + + *pu4WritenLen = kalSnprintf(pvSetBuffer, 3, "%d", rCmdBatchReq.ucMScan); + + } else if (!kalStrnCmp(head, BATCHING_STOP, kalStrLen(BATCHING_STOP))) { + + DBGLOG(SCN, TRACE, "XXX Stop Batch Scan XXX\n"); + + rCmdBatchReq.ucSeqNum = 1; + rCmdBatchReq.ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_STOP; + } else { + return -EINVAL; + } + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + TRUE, FALSE, TRUE, NULL, NULL, sizeof(CMD_BATCH_REQ_T), (PUINT_8) &rCmdBatchReq, NULL, 0); + + /* kalMemSet(pvSetBuffer, 0, u4SetBufferLen); */ + /* rStatus = kalSnprintf(pvSetBuffer, 2, "%s", "OK"); */ + + return rStatus; +} + +WLAN_STATUS +batchGetCmd(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + CMD_BATCH_REQ_T rCmdBatchReq; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pvQueryBuffer; + + DBGLOG(SCN, TRACE, "XXX Get Batch Scan Result (%u) XXX\n", (UINT_32) prEventBatchResult->ucScanCount); + + *pu4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + + rCmdBatchReq.ucSeqNum = 2; + rCmdBatchReq.ucCmd = SCAN_BATCH_REQ_RESULT; + rCmdBatchReq.ucMScan = prEventBatchResult->ucScanCount; /* Get which round result */ + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BATCH_REQ, + FALSE, + TRUE, + TRUE, + nicCmdEventBatchScanResult, + nicOidCmdTimeoutCommon, + sizeof(CMD_BATCH_REQ_T), + (PUINT_8) &rCmdBatchReq, (PVOID) pvQueryBuffer, u4QueryBufferLen); + + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + return batchSetCmd(prAdapter, pvSetBuffer, u4SetBufferLen, pu4SetInfoLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + return batchGetCmd(prAdapter, pvQueryBuffer, u4QueryBufferLen, pu4QueryInfoLen); + +} /* end of wlanoidQueryBatchScanResult() */ + +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request starting of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + + DEBUGFUNC("wlanoidSetStartSchedScan()"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set scheduled scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + ASSERT(pu4SetInfoLen); + *pu4SetInfoLen = 0; + + if (u4SetBufferLen != sizeof(PARAM_SCHED_SCAN_REQUEST)) { + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + return WLAN_STATUS_INVALID_DATA; + } else if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->fgEnOnlineScan == FALSE) { + return WLAN_STATUS_FAILURE; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) pvSetBuffer; + + if (scnFsmSchedScanRequest(prAdapter, + (UINT_8) (prSchedScanRequest->u4SsidNum), + prSchedScanRequest->arSsid, + prSchedScanRequest->u4IELength, + prSchedScanRequest->pucIE, prSchedScanRequest->u2ScanInterval) == TRUE) { + return WLAN_STATUS_SUCCESS; + } else { + return WLAN_STATUS_FAILURE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request termination of schedule scan +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + + /* ask SCN module to stop scan request */ + if (scnFsmSchedScanStopRequest(prAdapter) == TRUE) + return WLAN_STATUS_SUCCESS; + else + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a periodically scan action +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_SET_PSCAN_ENABLE prCmdPscnAction; + P_SCAN_INFO_T prScanInfo; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + DBGLOG(SCN, TRACE, "wlanoidSetGSCNAction\n"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(CMD_SET_PSCAN_ENABLE)) + return WLAN_STATUS_INVALID_LENGTH; + else if (pvSetBuffer == NULL) + return WLAN_STATUS_INVALID_DATA; + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, WARN, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdPscnAction = (P_CMD_SET_PSCAN_ENABLE) pvSetBuffer; + + if (prCmdPscnAction->ucPscanAct == ENABLE) { +#if 0 + DBGLOG(OID, INFO, "set PCSN ENABLE\n"); + if (scnFsmPSCNAction(prAdapter, (UINT_8) (prCmdPscnAction->ucPscanAct)) == TRUE) { + + DBGLOG(OID, INFO, "wlanoidSetGSCNAction < ---\n"); + return WLAN_STATUS_PENDING; + } + DBGLOG(OID, INFO, "wlanoidSetGSCNAction < ---\n"); + return WLAN_STATUS_FAILURE; + +#endif + scnPSCNFsm(prAdapter, PSCN_SCANNING, NULL, NULL, NULL, NULL, FALSE, FALSE, FALSE, TRUE); + } else if (prCmdPscnAction->ucPscanAct == DISABLE) { +#if 0 + DBGLOG(OID, INFO, "disable PCSN\n"); + scnFsmPSCNAction(prAdapter, (UINT_8) DISABLE); + + DBGLOG(OID, TRACE, "set new PCSN\n"); + scnCombineParamsIntoPSCN(prAdapter, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE); + + DBGLOG(OID, INFO, "ENABLE or disable PCSN\n"); + if (!prScanInfo->fgPscnOnnning) { + DBGLOG(OID, INFO, "ENABLE PCSN\n"); + scnFsmPSCNAction(prAdapter, ENABLE); + } else { + DBGLOG(OID, INFO, "All PCSN is disabled...\n"); + } +#endif + scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, NULL, FALSE, FALSE, TRUE, FALSE); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a periodically scan action +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetGSCNAParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam; + /*UINT_8 i, j = 0;*/ + DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam v1\n"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(P_PARAM_WIFI_GSCAN_CMD_PARAMS))\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prCmdGscnParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + /* KC-XXX memcpy(prCmdGscnParam, */ + /* (P_PARAM_WIFI_GSCAN_CMD_PARAMS)pvSetBuffer, */ + /* sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS) ); */ + DBGLOG(SCN, INFO, + "prCmdGscnParam : base_period[%u], max_ap_per_scan[%u] num_buckets[%u], report_threshold[%u]\n", + prCmdGscnParam->base_period, prCmdGscnParam->max_ap_per_scan, prCmdGscnParam->num_buckets, + prCmdGscnParam->report_threshold); +#if 0 + for (i = 0; i < prCmdGscnParam->num_buckets; i++) { + + DBGLOG(OID, INFO, + "prCmdGscnParam->buckets : band[%u], bucket[%u] num_buckets[%u], period[%u] report_events[%u]\n", + prCmdGscnParam->buckets[i].band, prCmdGscnParam->buckets[i].bucket, + prCmdGscnParam->buckets[i].num_channels, prCmdGscnParam->buckets[i].period, + prCmdGscnParam->buckets[i].report_events)); + DBGLOG(OID, INFO, "prCmdGscnParam->buckets[%d] has channel: ", i); + for (j = 0; j < prCmdGscnParam->buckets[i].num_channels; j++) + DBGLOG(OID, INFO, " %d, ", prCmdGscnParam->buckets[i].channels[j].channel); + DBGLOG(OID, INFO, "\n"); + } +#endif + if (scnSetGSCNParam(prAdapter, prCmdGscnParam) == TRUE) { + DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam --->scnSetGSCNParam\n"); + return WLAN_STATUS_PENDING; + } else { + return WLAN_STATUS_FAILURE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set configure gscan PARAMs +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +wlanoidSetGSCNAConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnScnConfigParam; + CMD_GSCN_SCN_COFIG_T rCmdGscnScnConfig; + + DBGLOG(SCN, INFO, "wlanoidSetGSCNAConfig v1\n"); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)) { + DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(CMD_GSCN_SCN_COFIG_T))\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); + return WLAN_STATUS_INVALID_DATA; + } + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + DBGLOG(SCN, INFO, "prCmdGscnScnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS)pvSetBuffer\n"); + prCmdGscnScnConfigParam = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer; + memcpy(prCmdGscnScnConfigParam, (P_PARAM_WIFI_GSCAN_CMD_PARAMS) pvSetBuffer, + sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + DBGLOG(SCN, INFO, "prCmdGscnScnConfigParam assign prCmdGscnScnConfig\n"); + rCmdGscnScnConfig.u4BufferThreshold = prCmdGscnScnConfigParam->report_threshold; + rCmdGscnScnConfig.ucNumApPerScn = prCmdGscnScnConfigParam->max_ap_per_scan; + rCmdGscnScnConfig.u4NumScnToCache = prCmdGscnScnConfigParam->num_scans; + DBGLOG(SCN, INFO, " report_threshold %d report_threshold %d num_scans %d\n", + rCmdGscnScnConfig.u4BufferThreshold, + rCmdGscnScnConfig.ucNumApPerScn, rCmdGscnScnConfig.u4NumScnToCache); + if (scnFsmSetGSCNConfig(prAdapter, &rCmdGscnScnConfig) == TRUE) { + DBGLOG(SCN, INFO, "wlanoidSetGSCNAParam --->scnSetGSCNParam\n"); + return WLAN_STATUS_PENDING; + } else { + return WLAN_STATUS_FAILURE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get a gscan result +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +* +* \note The setting buffer PARAM_SCHED_SCAN_REQUEST_EXT_T +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS prGetGscnScnResultParm; + CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; + + DEBUGFUNC("wlanoidGetGSCNResult()"); + DBGLOG(SCN, INFO, "wlanoidGetGSCNResult v1\n"); + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(SCN, WARN, "Fail in set Periodically Scan! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (u4SetBufferLen != sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS)) { + DBGLOG(SCN, WARN, "(u4SetBufferLen != sizeof(CMD_GSCN_SCN_COFIG_T))\n"); + return WLAN_STATUS_INVALID_LENGTH; + } else if (pvSetBuffer == NULL) { + DBGLOG(SCN, WARN, "(pvSetBuffer == NULL)\n"); + return WLAN_STATUS_INVALID_DATA; + } + + if (prAdapter->fgIsRadioOff) { + DBGLOG(SCN, INFO, "Return from BSSID list scan! (radio off). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_SUCCESS; + } + + prGetGscnScnResultParm = (P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) pvSetBuffer; + /* memcpy(&rGetGscnScnResultCmd, prGetGscnScnResultParm, sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS) ); */ + + rGetGscnScnResultCmd.u4Num = prGetGscnScnResultParm->get_num; + rGetGscnScnResultCmd.ucFlush = prGetGscnScnResultParm->flush; + rGetGscnScnResultCmd.ucVersion = PSCAN_VERSION; + kalMemZero(rGetGscnScnResultCmd.aucReserved, sizeof(rGetGscnScnResultCmd.aucReserved)); + + if (scnFsmGetGSCNResult(prAdapter, &rGetGscnScnResultCmd) == TRUE) { + DBGLOG(SCN, INFO, "wlanoidGetGSCNResult --->scnFsmGetGSCNResult\n"); + return WLAN_STATUS_PENDING; + } else { + return WLAN_STATUS_FAILURE; + } + +} + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by HS2.0 to set the assoc info, which is needed to add to +* Association request frame while join HS2.0 AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DEBUGFUNC("wlanoidSetHS20AssocInfo"); + DBGLOG(OID, LOUD, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pvSetBuffer; + + prAdapter->prGlueInfo->ucHotspotConfig = prHS20IndicationIe->ucHotspotConfig; + prAdapter->prGlueInfo->fgConnectHS20AP = TRUE; + + DBGLOG(SEC, TRACE, "HS20 IE sz %u\n", u4SetBufferLen); + + kalMemCopy(prAdapter->prGlueInfo->aucHS20AssocInfoIE, pvSetBuffer, u4SetBufferLen); + prAdapter->prGlueInfo->u2HS20AssocInfoIELen = (UINT_16) u4SetBufferLen; + DBGLOG(SEC, TRACE, "HS20 Assoc Info IE sz %u\n", u4SetBufferLen); + + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the assoc info, which is needed to add to +* Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_IE_INTERWORKING_T prInterWorkingIe; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + DEBUGFUNC("wlanoidSetInterworkingInfo"); + DBGLOG(OID, TRACE, "\r\n"); + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prInterWorkingIe = (P_IE_INTERWORKING_T) pvSetBuffer; + + prHS20Info->ucAccessNetworkOptions = prInterWorkingIe->ucAccNetOpt; + prHS20Info->ucVenueGroup = prInterWorkingIe->ucVenueGroup; + prHS20Info->ucVenueType = prInterWorkingIe->ucVenueType; + COPY_MAC_ADDR(prHS20Info->aucHESSID, prInterWorkingIe->aucHESSID); + + DBGLOG(SEC, TRACE, "IW IE sz %ld\n", u4SetBufferLen); +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called by WSC to set the Roaming Consortium IE info, which is needed to +* add to Association request frame while join WPS AP. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ +#if 0 + P_HS20_INFO_T prHS20Info = NULL; + P_PARAM_HS20_ROAMING_CONSORTIUM_INFO prRCInfo; + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* DEBUGFUNC("wlanoidSetRoamingConsortiumInfo"); */ + /* DBGLOG(HS2, TRACE, ("\r\n")); */ + + if (u4SetBufferLen == 0) + return WLAN_STATUS_INVALID_LENGTH; + + *pu4SetInfoLen = u4SetBufferLen; + prRCInfo = (P_PARAM_HS20_ROAMING_CONSORTIUM_INFO) pvSetBuffer; + + kalMemCopy(&(prHS20Info->rRCInfo), prRCInfo, sizeof(PARAM_HS20_ROAMING_CONSORTIUM_INFO)); + + /* DBGLOG(HS2, TRACE, ("RoamingConsortium IE sz %ld\n", u4SetBufferLen)); */ +#endif + return WLAN_STATUS_SUCCESS; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set_bssid_pool +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_HS20_SET_BSSID_POOL)) { + *pu4SetInfoLen = sizeof(PARAM_HS20_SET_BSSID_POOL); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + rWlanStatus = hs20SetBssidPool(prAdapter, pvSetBuffer, NETWORK_TYPE_AIS_INDEX); + + return rWlanStatus; +} /* end of wlanoidSendHS20GASRequest() */ + +#endif + +#if CFG_SUPPORT_ROAMING_ENC +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_ROAMING_INFO_T *prCmdRoamingInfo; + + DEBUGFUNC("wlanoidSetRoamingInfo"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_ROAMING_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_ROAMING_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdRoamingInfo = (CMD_ROAMING_INFO_T *) pvSetBuffer; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_ROAMING_INFO, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_ROAMING_INFO_T), (PUINT_8) prCmdRoamingInfo, NULL, 0); +} +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set chip +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T prChipConfigInfo; + CMD_CHIP_CONFIG_T rCmdChipConfig; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(prChipConfigInfo->aucCmd) == CHIP_CONFIG_RESP_SIZE); + DEBUGFUNC("wlanoidSetChipConfig"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prChipConfigInfo = (P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T) pvSetBuffer; + kalMemZero(&rCmdChipConfig, sizeof(rCmdChipConfig)); + + rCmdChipConfig.u2Id = prChipConfigInfo->u2Id; + rCmdChipConfig.ucType = prChipConfigInfo->ucType; + rCmdChipConfig.ucRespType = prChipConfigInfo->ucRespType; + rCmdChipConfig.u2MsgSize = prChipConfigInfo->u2MsgSize; + if (rCmdChipConfig.u2MsgSize > CHIP_CONFIG_RESP_SIZE) { + DBGLOG(OID, INFO, "Chip config Msg Size %u is not valid (set)\n", rCmdChipConfig.u2MsgSize); + rCmdChipConfig.u2MsgSize = CHIP_CONFIG_RESP_SIZE; + } + kalMemCopy(rCmdChipConfig.aucCmd, prChipConfigInfo->aucCmd, rCmdChipConfig.u2MsgSize); + + DBGLOG(OID, TRACE, "rCmdChipConfig.aucCmd=%s\n", rCmdChipConfig.aucCmd); +#if 1 + rWlanStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_CHIP_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CHIP_CONFIG_T), + (PUINT_8) &rCmdChipConfig, pvSetBuffer, u4SetBufferLen); +#endif + return rWlanStatus; +} /* wlanoidSetChipConfig */ + +WLAN_STATUS +wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_CMD_WFD_DEBUG_MODE_INFO_T prCmdWfdDebugModeInfo; + + DEBUGFUNC("wlanoidSetWFDDebugMode"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_WFD_DEBUG_MODE_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_WFD_DEBUG_MODE_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdWfdDebugModeInfo = (CMD_WFD_DEBUG_MODE_INFO_T *) pvSetBuffer; + + DBGLOG(OID, INFO, "New WFD Debug: %d mode and period=0x%x\n", prCmdWfdDebugModeInfo->ucDebugMode, + prCmdWfdDebugModeInfo->u2PeriodInteval); + + prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode = (UINT_8) prCmdWfdDebugModeInfo->ucDebugMode; + prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.u2WfdSNShowPeiroid = + (UINT_16) prCmdWfdDebugModeInfo->u2PeriodInteval; + + return WLAN_STATUS_SUCCESS; +} /*wlanoidSetWfdDebugMode */ + + +#if (CFG_SUPPORT_TXR_ENC == 1) +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to query the MAC address the NIC is currently using. +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvQueryBuf A pointer to the buffer that holds the result of the +* query buffer +* \param[in] u4QueryBufLen The length of the query buffer +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_BUFFER_TOO_SHORT +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetTxRateInfo( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen) +{ + CMD_RLM_INFO_T *prCmdTxRInfo; + + DEBUGFUNC("wlanoidSetTxRateInfo"); + DBGLOG(OID, LOUD, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(CMD_RLM_INFO_T); + + if (u4SetBufferLen < sizeof(CMD_RLM_INFO_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prCmdTxRInfo = (CMD_RLM_INFO_T *)pvSetBuffer; + + DBGLOG(OID, INFO, " command = %u %u %u %u %d %u %u\n", + prCmdTxRInfo->u4Version, + prCmdTxRInfo->fgIsErrRatioEnhanceApplied, + prCmdTxRInfo->ucErrRatio2LimitMinRate, + prCmdTxRInfo->ucMinLegacyRateIdx, + prCmdTxRInfo->cMinRssiThreshold, + prCmdTxRInfo->fgIsRtsApplied, + prCmdTxRInfo->ucRecoverTime)); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_TX_AR_ERR_CONFIG, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_RLM_INFO_T), + (PUINT_8)prCmdTxRInfo, + NULL, + 0 + ); +} +#endif /* CFG_SUPPORT_TXR_ENC */ + +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WIFI_SYSTEM_SUSPEND_CMD_T rSuspendCmd; + + if (!prAdapter || !pvSetBuffer) + return WLAN_STATUS_INVALID_DATA; + + rSuspendCmd.fgIsSystemSuspend = *(PBOOLEAN)pvSetBuffer; + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_SYSTEM_SUSPEND, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(BOOLEAN), + (PUINT_8)&rSuspendCmd, + NULL, + 0); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c new file mode 100644 index 0000000000000..7ca7ee48922e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/common/wlan_p2p.c @@ -0,0 +1,1654 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/common/wlan_p2p.c#8 +*/ + +/*! \file wlan_bow.c + \brief This file contains the Wi-Fi Direct commands processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_p2p.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 24 2011 yuche.tsai + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support + * for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channel Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 23 2011 yuche.tsai + * NULL + * Fix Multicast Issue of P2P. + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 wh.su + * [WCXRP00000571] [MT6620 Wi-Fi] [Driver] Not check the p2p role during set key + * Skip the p2p role for adding broadcast key issue. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * fixed compiling error while enable dbg. + * + * 03 08 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format + * issue[WCXRP00000509] [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix SD Request Query Length issue. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Service Discovery Request. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Wlan OID related function. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface + * for supporting Wi-Fi Direct Service Discovery ioctl implementations for P2P Service Discovery + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to + * ease physically continuous memory demands separate kalMemAlloc() into virtually-continuous + * and physically-continuous type to ease slab system pressure + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface + * for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T + * and replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * . + * + * 08 16 2010 george.huang + * NULL + * support wlanoidSetP2pPowerSaveProfile() in P2P + * + * 08 16 2010 george.huang + * NULL + * Support wlanoidSetNetworkAddress() for P2P + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * +** +*/ + +/****************************************************************************** +* C O M P I L E R F L A G S +******************************************************************************* +*/ + +/****************************************************************************** +* E X T E R N A L R E F E R E N C E S +******************************************************************************* +*/ +#include "precomp.h" +#include "gl_p2p_ioctl.h" + +/****************************************************************************** +* C O N S T A N T S +******************************************************************************* +*/ + +/****************************************************************************** +* D A T A T Y P E S +******************************************************************************* +*/ + +/****************************************************************************** +* P U B L I C D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* P R I V A T E D A T A +******************************************************************************* +*/ + +/****************************************************************************** +* M A C R O S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************* +*/ + +/****************************************************************************** +* F U N C T I O N S +******************************************************************************* +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief command packet generation utility +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucCID Command ID +* \param[in] fgSetQuery Set or Query +* \param[in] fgNeedResp Need for response +* \param[in] pfCmdDoneHandler Function pointer when command is done +* \param[in] u4SetQueryInfoLen The length of the set/query buffer +* \param[in] pucInfoBuffer Pointer to set/query buffer +* +* +* \retval WLAN_STATUS_PENDING +* \retval WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen) +{ + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + DEBUGFUNC("wlanoidSendSetQueryP2PCmd"); + DBGLOG(REQ, TRACE, "Command ID = 0x%08X\n", ucCID); + + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u4SetQueryInfoLen)); + + if (!prCmdInfo) { + DBGLOG(P2P, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = NETWORK_TYPE_P2P_INDEX; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u4SetQueryInfoLen); + prCmdInfo->pfCmdDoneHandler = pfCmdDoneHandler; + prCmdInfo->pfCmdTimeoutHandler = pfCmdTimeoutHandler; + prCmdInfo->fgIsOid = fgIsOid; + prCmdInfo->ucCID = ucCID; + prCmdInfo->fgSetQuery = fgSetQuery; + prCmdInfo->fgNeedResp = fgNeedResp; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u4SetQueryInfoLen; + prCmdInfo->pvInformationBuffer = pvSetQueryBuffer; + prCmdInfo->u4InformationBufferLength = u4SetQueryBufferLen; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + if (u4SetQueryInfoLen > 0 && pucInfoBuffer != NULL) + kalMemCopy(prWifiCmd->aucBuffer, pucInfoBuffer, u4SetQueryInfoLen); + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set a key to Wi-Fi Direct driver +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_802_11_KEY rCmdKey; + P_PARAM_KEY_T prNewKey; + + DEBUGFUNC("wlanoidSetAddP2PKey"); + DBGLOG(REQ, INFO, "\n"); + + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + prNewKey = (P_PARAM_KEY_T) pvSetBuffer; + + /* Verify the key structure length. */ + if (prNewKey->u4Length > u4SetBufferLen) { + DBGLOG(REQ, WARN, "Invalid key structure length (%d) greater than total buffer length (%d)\n", + (UINT_8) prNewKey->u4Length, (UINT_8) u4SetBufferLen); + + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_LENGTH; + } + /* Verify the key material length for key material buffer */ + else if (prNewKey->u4KeyLength > prNewKey->u4Length - OFFSET_OF(PARAM_KEY_T, aucKeyMaterial)) { + DBGLOG(REQ, WARN, "Invalid key material length (%d)\n", (UINT_8) prNewKey->u4KeyLength); + *pu4SetInfoLen = u4SetBufferLen; + return WLAN_STATUS_INVALID_DATA; + } + /* Exception check */ + else if (prNewKey->u4KeyIndex & 0x0fffff00) + return WLAN_STATUS_INVALID_DATA; + /* Exception check, pairwise key must with transmit bit enabled */ + else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == IS_UNICAST_KEY) { + return WLAN_STATUS_INVALID_DATA; + } else if (!(prNewKey->u4KeyLength == CCMP_KEY_LEN) && !(prNewKey->u4KeyLength == TKIP_KEY_LEN)) { + return WLAN_STATUS_INVALID_DATA; + } + /* Exception check, pairwise key must with transmit bit enabled */ + else if ((prNewKey->u4KeyIndex & BITS(30, 31)) == BITS(30, 31)) { + if (((prNewKey->u4KeyIndex & 0xff) != 0) || + ((prNewKey->arBSSID[0] == 0xff) && (prNewKey->arBSSID[1] == 0xff) && (prNewKey->arBSSID[2] == 0xff) + && (prNewKey->arBSSID[3] == 0xff) && (prNewKey->arBSSID[4] == 0xff) + && (prNewKey->arBSSID[5] == 0xff))) { + return WLAN_STATUS_INVALID_DATA; + } + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* fill CMD_802_11_KEY */ + kalMemZero(&rCmdKey, sizeof(CMD_802_11_KEY)); + rCmdKey.ucAddRemove = 1; /* add */ + rCmdKey.ucTxKey = ((prNewKey->u4KeyIndex & IS_TRANSMIT_KEY) == IS_TRANSMIT_KEY) ? 1 : 0; + rCmdKey.ucKeyType = ((prNewKey->u4KeyIndex & IS_UNICAST_KEY) == IS_UNICAST_KEY) ? 1 : 0; + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + COPY_MAC_ADDR(rCmdKey.aucPeerAddr, prNewKey->arBSSID); + rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; + if (prNewKey->u4KeyLength == CCMP_KEY_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_CCMP; /* AES */ + else if (prNewKey->u4KeyLength == TKIP_KEY_LEN) + rCmdKey.ucAlgorithmId = CIPHER_SUITE_TKIP; /* TKIP */ + rCmdKey.ucKeyId = (UINT_8) (prNewKey->u4KeyIndex & 0xff); + rCmdKey.ucKeyLen = (UINT_8) prNewKey->u4KeyLength; + kalMemCopy(rCmdKey.aucKeyMaterial, (PUINT_8) prNewKey->aucKeyMaterial, rCmdKey.ucKeyLen); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to request Wi-Fi Direct driver to remove keys +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_802_11_KEY rCmdKey; + P_PARAM_REMOVE_KEY_T prRemovedKey; + + DEBUGFUNC("wlanoidSetRemoveP2PKey"); + ASSERT(prAdapter); + + if (u4SetBufferLen < sizeof(PARAM_REMOVE_KEY_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + prRemovedKey = (P_PARAM_REMOVE_KEY_T) pvSetBuffer; + + /* Check bit 31: this bit should always 0 */ + if (prRemovedKey->u4KeyIndex & IS_TRANSMIT_KEY) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* Check bits 8 ~ 29 should always be 0 */ + if (prRemovedKey->u4KeyIndex & BITS(8, 29)) { + /* Bit 31 should not be set */ + DBGLOG(REQ, ERROR, "invalid key index: 0x%08x\n", prRemovedKey->u4KeyIndex); + return WLAN_STATUS_INVALID_DATA; + } + + /* There should not be any key operation for P2P Device */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 0) + ; /* return WLAN_STATUS_NOT_ACCEPTED; */ + + kalMemZero((PUINT_8) &rCmdKey, sizeof(CMD_802_11_KEY)); + + rCmdKey.ucAddRemove = 0; /* remove */ + if (kalP2PGetRole(prAdapter->prGlueInfo) == 1) { /* group client */ + rCmdKey.ucIsAuthenticator = 0; + } else { /* group owner */ + rCmdKey.ucIsAuthenticator = 1; + } + kalMemCopy(rCmdKey.aucPeerAddr, (PUINT_8) prRemovedKey->arBSSID, MAC_ADDR_LEN); + rCmdKey.ucNetType = NETWORK_TYPE_P2P_INDEX; + rCmdKey.ucKeyId = (UINT_8) (prRemovedKey->u4KeyIndex & 0x000000ff); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_ADD_REMOVE_KEY, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + NULL, + sizeof(CMD_802_11_KEY), (PUINT_8) &rCmdKey, pvSetBuffer, u4SetBufferLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setting the IP address for pattern search function. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +* \return WLAN_STATUS_ADAPTER_NOT_READY +* \return WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + + DEBUGFUNC("wlanoidSetP2pNetworkAddress"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to query the power save profile. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuf A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen != 0) { + ASSERT(pvQueryBuffer); + + *(PPARAM_POWER_MODE) pvQueryBuffer = + (PARAM_POWER_MODE) (prAdapter->rWlanInfo.arPowerSaveMode[NETWORK_TYPE_P2P_INDEX].ucPsProfile); + *pu4QueryInfoLen = sizeof(PARAM_POWER_MODE); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + PARAM_POWER_MODE ePowerMode; + + DEBUGFUNC("wlanoidSetP2pPowerSaveProfile"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_POWER_MODE); + if (u4SetBufferLen < sizeof(PARAM_POWER_MODE)) { + DBGLOG(REQ, WARN, "Invalid length %u\n", u4SetBufferLen); + return WLAN_STATUS_INVALID_LENGTH; + } else if (*(PPARAM_POWER_MODE) pvSetBuffer >= Param_PowerModeMax) { + WARNLOG(("Invalid power mode %d\n", *(PPARAM_POWER_MODE) pvSetBuffer)); + return WLAN_STATUS_INVALID_DATA; + } + + ePowerMode = *(PPARAM_POWER_MODE) pvSetBuffer; + + if (prAdapter->fgEnCtiaPowerMode) { + if (ePowerMode == Param_PowerModeCAM) { + /*Todo:: Nothing*/ + /*Todo:: Nothing*/ + } else { + /* User setting to PS mode (Param_PowerModeMAX_PSP or Param_PowerModeFast_PSP) */ + + if (prAdapter->u4CtiaPowerMode == 0) { + /* force to keep in CAM mode */ + ePowerMode = Param_PowerModeCAM; + } else if (prAdapter->u4CtiaPowerMode == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (prAdapter->u4CtiaPowerMode == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } + } + } + + status = nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_P2P_INDEX, ePowerMode, TRUE); + return status; +} /* end of wlanoidSetP2pPowerSaveProfile() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the power save profile. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 i, j; + P_CMD_SET_NETWORK_ADDRESS_LIST prCmdNetworkAddressList; + P_PARAM_NETWORK_ADDRESS_LIST prNetworkAddressList = (P_PARAM_NETWORK_ADDRESS_LIST) pvSetBuffer; + P_PARAM_NETWORK_ADDRESS prNetworkAddress; + P_PARAM_NETWORK_ADDRESS_IP prNetAddrIp; + UINT_32 u4IpAddressCount, u4CmdSize; + PUINT_8 pucBuf = (PUINT_8) pvSetBuffer; + + DEBUGFUNC("wlanoidSetP2pSetNetworkAddress"); + DBGLOG(P2P, TRACE, "\n"); + DBGLOG(P2P, INFO, "wlanoidSetP2pSetNetworkAddress (%d)\n", (INT_16) u4SetBufferLen); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = 4; + + if (u4SetBufferLen < sizeof(PARAM_NETWORK_ADDRESS_LIST)) + return WLAN_STATUS_INVALID_DATA; + + *pu4SetInfoLen = 0; + u4IpAddressCount = 0; + + prNetworkAddress = prNetworkAddressList->arAddress; + for (i = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + u4IpAddressCount++; + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress))); + } + + /* construct payload of command packet */ + u4CmdSize = OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress) + + sizeof(IPV4_NETWORK_ADDRESS) * u4IpAddressCount; + + if (u4IpAddressCount == 0) + u4CmdSize = sizeof(CMD_SET_NETWORK_ADDRESS_LIST); + + prCmdNetworkAddressList = (P_CMD_SET_NETWORK_ADDRESS_LIST) kalMemAlloc(u4CmdSize, VIR_MEM_TYPE); + + if (prCmdNetworkAddressList == NULL) + return WLAN_STATUS_FAILURE; + + /* fill P_CMD_SET_NETWORK_ADDRESS_LIST */ + prCmdNetworkAddressList->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + + /* only to set IP address to FW once ARP filter is enabled */ + if (prAdapter->fgEnArpFilter) { + prCmdNetworkAddressList->ucAddressCount = (UINT_8) u4IpAddressCount; + prNetworkAddress = prNetworkAddressList->arAddress; + + DBGLOG(P2P, INFO, "u4IpAddressCount (%u)\n", u4IpAddressCount); + for (i = 0, j = 0; i < prNetworkAddressList->u4AddressCount; i++) { + if (prNetworkAddress->u2AddressType == PARAM_PROTOCOL_ID_TCP_IP && + prNetworkAddress->u2AddressLength == sizeof(PARAM_NETWORK_ADDRESS_IP)) { + prNetAddrIp = (P_PARAM_NETWORK_ADDRESS_IP) prNetworkAddress->aucAddress; + + kalMemCopy(prCmdNetworkAddressList->arNetAddress[j].aucIpAddr, + &(prNetAddrIp->in_addr), sizeof(UINT_32)); + + j++; + + pucBuf = (PUINT_8) &prNetAddrIp->in_addr; + DBGLOG(P2P, INFO, "prNetAddrIp->in_addr:%d:%d:%d:%d\n", + (UINT_8) pucBuf[0], (UINT_8) pucBuf[1], + (UINT_8) pucBuf[2], (UINT_8) pucBuf[3]); + } + + prNetworkAddress = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prNetworkAddress + + (ULONG) (prNetworkAddress->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + } + + } else { + prCmdNetworkAddressList->ucAddressCount = 0; + } + + rStatus = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_IP_ADDRESS, + TRUE, + FALSE, + TRUE, + nicCmdEventSetIpAddress, + nicOidCmdTimeoutCommon, + u4CmdSize, (PUINT_8) prCmdNetworkAddressList, pvSetBuffer, u4SetBufferLen); + + kalMemFree(prCmdNetworkAddressList, VIR_MEM_TYPE, u4CmdSize); + return rStatus; +} /* end of wlanoidSetP2pSetNetworkAddress() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Multicast Address List. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + CMD_MAC_MCAST_ADDR rCmdMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + /* The data must be a multiple of the Ethernet address size. */ + if ((u4SetBufferLen % MAC_ADDR_LEN)) { + DBGLOG(REQ, WARN, "Invalid MC list length %u\n", u4SetBufferLen); + + *pu4SetInfoLen = (((u4SetBufferLen + MAC_ADDR_LEN) - 1) / MAC_ADDR_LEN) * MAC_ADDR_LEN; + + return WLAN_STATUS_INVALID_LENGTH; + } + + *pu4SetInfoLen = u4SetBufferLen; + + /* Verify if we can support so many multicast addresses. */ + if ((u4SetBufferLen / MAC_ADDR_LEN) > MAX_NUM_GROUP_ADDR) { + DBGLOG(REQ, WARN, "Too many MC addresses\n"); + + return WLAN_STATUS_MULTICAST_FULL; + } + + /* NOTE(Kevin): Windows may set u4SetBufferLen == 0 && + * pvSetBuffer == NULL to clear exist Multicast List. + */ + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, "Fail in set multicast list! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + rCmdMacMcastAddr.u4NumOfGroupAddr = u4SetBufferLen / MAC_ADDR_LEN; + rCmdMacMcastAddr.ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + kalMemCopy(rCmdMacMcastAddr.arAddress, pvSetBuffer, u4SetBufferLen); + + /* This CMD response is no need to complete the OID. Or the event would unsync. */ + return wlanoidSendSetQueryP2PCmd(prAdapter, CMD_ID_MAC_MCAST_ADDR, TRUE, FALSE, FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_MAC_MCAST_ADDR), + (PUINT_8) &rCmdMacMcastAddr, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetP2PMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_REQUEST)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDRequest(prAdapter, (P_PARAM_P2P_SEND_SD_REQUEST)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidSendP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + if (u4SetBufferLen < sizeof(PARAM_P2P_SEND_SD_RESPONSE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_SEND_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } +/* rWlanStatus = p2pFsmRunEventSDResponse(prAdapter, (P_PARAM_P2P_SEND_SD_RESPONSE)pvSetBuffer); */ + + return rWlanStatus; +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Request +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*PUINT_8 pucPacketBuffer = NULL, pucTA = NULL;*/ +/* PUINT_8 pucChannelNum = NULL; */ + /*PUINT_16 pu2PacketLength = NULL;*/ + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /*UINT_8 ucVersionNum = 0;*/ +/* UINT_8 ucChannelNum = 0, ucSeqNum = 0; */ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_REQUEST)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_REQUEST); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Request\n"); +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_REQUEST prP2pGetSdReq = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + + pucPacketBuffer = prP2pGetSdReq->aucPacketContent; + pu2PacketLength = &prP2pGetSdReq->u2PacketLength; + pucTA = &prP2pGetSdReq->rTransmitterAddr; + } else { + P_PARAM_P2P_GET_SD_REQUEST_EX prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST_EX) NULL; + + prP2pGetSdReqEx = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketBuffer = prP2pGetSdReqEx->aucPacketContent; + pu2PacketLength = &prP2pGetSdReqEx->u2PacketLength; + pucTA = &prP2pGetSdReqEx->rTransmitterAddr; + pucChannelNum = &prP2pGetSdReqEx->ucChannelNum; + ucSeqNum = prP2pGetSdReqEx->ucSeqNum; + } + + rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, + pucPacketBuffer, + (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_REQUEST)), + (PUINT_32) pu2PacketLength, pucChannelNum, ucSeqNum); +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + /* + prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketBuffer; + + kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + + if (pu4QueryInfoLen) { + if (ucVersionNum == 0) + *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST) + (*pu2PacketLength)); + else + *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_REQUEST_EX) + (*pu2PacketLength)); + + } + + return rWlanStatus; + */ +} /* end of wlanoidGetP2PSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get GAS frame for P2P Service Discovery Response +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /*P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL;*/ + /* UINT_8 ucSeqNum = 0, */ + /*UINT_8 ucVersionNum = 0;*/ + /*PUINT_8 pucPacketContent = (PUINT_8) NULL, pucTA = (PUINT_8) NULL;*/ + /*PUINT_16 pu2PacketLength = (PUINT_16) NULL;*/ + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen < sizeof(PARAM_P2P_GET_SD_RESPONSE)) { + *pu4QueryInfoLen = sizeof(PARAM_P2P_GET_SD_RESPONSE); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + DBGLOG(P2P, TRACE, "Get Service Discovery Response\n"); + +#if 0 + ucVersionNum = p2pFuncGetVersionNumOfSD(prAdapter); + if (ucVersionNum == 0) { + P_PARAM_P2P_GET_SD_RESPONSE prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_RESPONSE) NULL; + + prP2pGetSdRsp = (P_PARAM_P2P_GET_SD_REQUEST) pvQueryBuffer; + pucPacketContent = prP2pGetSdRsp->aucPacketContent; + pucTA = &prP2pGetSdRsp->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRsp->u2PacketLength; + } else { + P_PARAM_P2P_GET_SD_RESPONSE_EX prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) NULL; + + prP2pGetSdRspEx = (P_PARAM_P2P_GET_SD_RESPONSE_EX) pvQueryBuffer; + pucPacketContent = prP2pGetSdRspEx->aucPacketContent; + pucTA = &prP2pGetSdRspEx->rTransmitterAddr; + pu2PacketLength = &prP2pGetSdRspEx->u2PacketLength; + ucSeqNum = prP2pGetSdRspEx->ucSeqNum; + } + +/* rWlanStatus = p2pFuncGetServiceDiscoveryFrame(prAdapter, */ +/* pucPacketContent, */ +/* (u4QueryBufferLen - sizeof(PARAM_P2P_GET_SD_RESPONSE)), */ +/* (PUINT_32)pu2PacketLength, */ +/* NULL, */ +/* ucSeqNum); */ +#else + *pu4QueryInfoLen = 0; + return rWlanStatus; +#endif + /* + prWlanHdr = (P_WLAN_MAC_HEADER_T) pucPacketContent; + + kalMemCopy(pucTA, prWlanHdr->aucAddr2, MAC_ADDR_LEN); + + if (pu4QueryInfoLen) { + if (ucVersionNum == 0) + *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE) + *pu2PacketLength); + else + *pu4QueryInfoLen = (UINT_32) (sizeof(PARAM_P2P_GET_SD_RESPONSE_EX) + *pu2PacketLength); + } + + return rWlanStatus; + */ +} /* end of wlanoidGetP2PSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to terminate P2P Service Discovery Phase +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_PARAM_P2P_TERMINATE_SD_PHASE prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) NULL; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) + break; + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) + break; + + if (u4SetBufferLen < sizeof(PARAM_P2P_TERMINATE_SD_PHASE)) { + *pu4SetInfoLen = sizeof(PARAM_P2P_TERMINATE_SD_PHASE); + rWlanStatus = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + prP2pTerminateSD = (P_PARAM_P2P_TERMINATE_SD_PHASE) pvSetBuffer; + + if (EQUAL_MAC_ADDR(prP2pTerminateSD->rPeerAddr, aucNullAddr)) { + DBGLOG(P2P, TRACE, "Service Discovery Version 2.0\n"); +/* p2pFuncSetVersionNumOfSD(prAdapter, 2); */ + } + /* rWlanStatus = p2pFsmRunEventSDAbort(prAdapter); */ + + } while (FALSE); + + return rWlanStatus; +} /* end of wlanoidSetP2PTerminateSDPhase() */ + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (u4SetBufferLen) + ASSERT(pvSetBuffer); + + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SEC_CHECK, + FALSE, + TRUE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + u4SetBufferLen, (PUINT_8) pvSetBuffer, pvSetBuffer, u4SetBufferLen); + +} /* end of wlanoidSetSecCheckRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[out] pvQueryBuffer A pointer to the buffer that holds the result of +* the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_ADAPTER_NOT_READY +* \retval WLAN_STATUS_MULTICAST_FULL +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + /* P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T)NULL; */ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = prAdapter->prGlueInfo; + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + if (u4QueryBufferLen > 256) + u4QueryBufferLen = 256; + + *pu4QueryInfoLen = u4QueryBufferLen; + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); +#endif + kalMemCopy((PUINT_8) (pvQueryBuffer + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer)), + prGlueInfo->prP2PInfo->aucSecCheckRsp, u4QueryBufferLen); + + return rWlanStatus; +} /* end of wlanoidGetSecCheckResponse() */ +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam; + CMD_CUSTOM_NOA_PARAM_STRUCT_T rCmdNoaParam; + + DEBUGFUNC("wlanoidSetNoaParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdNoaParam, sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T)); + rCmdNoaParam.u4NoaDurationMs = prNoaParam->u4NoaDurationMs; + rCmdNoaParam.u4NoaIntervalMs = prNoaParam->u4NoaIntervalMs; + rCmdNoaParam.u4NoaCount = prNoaParam->u4NoaCount; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_NOA_PARAM_STRUCT_T), + (PUINT_8) &rCmdNoaParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam; + CMD_CUSTOM_OPPPS_PARAM_STRUCT_T rCmdOppPsParam; + + DEBUGFUNC("wlanoidSetOppPsParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdOppPsParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdOppPsParam.u4CTwindowMs = prOppPsParam->u4CTwindowMs; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_OPPPS_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_NOA_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdOppPsParam, pvSetBuffer, u4SetBufferLen); + +#endif + +} + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T prUapsdParam; + CMD_CUSTOM_UAPSD_PARAM_STRUCT_T rCmdUapsdParam; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("wlanoidSetUApsdParam"); + DBGLOG(P2P, TRACE, "\n"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T); + + if (u4SetBufferLen < sizeof(PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvSetBuffer); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prUapsdParam = (P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T) pvSetBuffer; + + kalMemZero(&rCmdUapsdParam, sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T)); + rCmdUapsdParam.fgEnAPSD = prUapsdParam->fgEnAPSD; + prAdapter->rWifiVar.fgSupportUAPSD = prUapsdParam->fgEnAPSD; + + rCmdUapsdParam.fgEnAPSD_AcBe = prUapsdParam->fgEnAPSD_AcBe; + rCmdUapsdParam.fgEnAPSD_AcBk = prUapsdParam->fgEnAPSD_AcBk; + rCmdUapsdParam.fgEnAPSD_AcVo = prUapsdParam->fgEnAPSD_AcVo; + rCmdUapsdParam.fgEnAPSD_AcVi = prUapsdParam->fgEnAPSD_AcVi; + prPmProfSetupInfo->ucBmpDeliveryAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + prPmProfSetupInfo->ucBmpTriggerAC = + ((prUapsdParam->fgEnAPSD_AcBe << 0) | + (prUapsdParam->fgEnAPSD_AcBk << 1) | + (prUapsdParam->fgEnAPSD_AcVi << 2) | (prUapsdParam->fgEnAPSD_AcVo << 3)); + + rCmdUapsdParam.ucMaxSpLen = prUapsdParam->ucMaxSpLen; + prPmProfSetupInfo->ucUapsdSp = prUapsdParam->ucMaxSpLen; + +#if 0 + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); +#else + return wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_UAPSD_PARAM, + TRUE, + FALSE, + TRUE, + NULL, + nicOidCmdTimeoutCommon, + sizeof(CMD_CUSTOM_OPPPS_PARAM_STRUCT_T), + (PUINT_8) &rCmdUapsdParam, pvSetBuffer, u4SetBufferLen); + +#endif +} + +WLAN_STATUS +wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +/* PUINT_8 pucOpChnl = (PUINT_8)pvQueryBuffer; */ + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } +#if 0 + if (!p2pFuncGetCurrentOpChnl(prAdapter, pucOpChnl)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } +#else + rResult = WLAN_STATUS_INVALID_DATA; + break; +#endif + /* + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_SUCCESS; + */ + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pOpChannel */ + +WLAN_STATUS +wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; +/* PUINT_8 pucVersionNum = (PUINT_8)pvQueryBuffer; */ + + do { + if ((prAdapter == NULL) || (pu4QueryInfoLen == NULL)) + break; + + if ((u4QueryBufferLen) && (pvQueryBuffer == NULL)) + break; + + if (u4QueryBufferLen < sizeof(UINT_8)) { + *pu4QueryInfoLen = sizeof(UINT_8); + rResult = WLAN_STATUS_BUFFER_TOO_SHORT; + break; + } + + } while (FALSE); + + return rResult; +} /* wlanoidQueryP2pVersion */ + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rResult = WLAN_STATUS_FAILURE; + UINT_8 ucVersionNum; + + do { + if ((prAdapter == NULL) || (pu4SetInfoLen == NULL)) { + + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + if ((u4SetBufferLen) && (pvSetBuffer == NULL)) { + rResult = WLAN_STATUS_INVALID_DATA; + break; + } + + *pu4SetInfoLen = sizeof(UINT_8); + + if (u4SetBufferLen < sizeof(UINT_8)) { + rResult = WLAN_STATUS_INVALID_LENGTH; + break; + } + + ucVersionNum = *((PUINT_8) pvSetBuffer); + + rResult = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rResult; +} /* wlanoidSetP2pSupplicantVersion */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set the WPS mode. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS status; + UINT_32 u4IsWPSmode = 0; + + DEBUGFUNC("wlanoidSetP2pWPSmode"); + + ASSERT(prAdapter); + ASSERT(pu4SetInfoLen); + + if (pvSetBuffer) + u4IsWPSmode = *(PUINT_32) pvSetBuffer; + else + u4IsWPSmode = 0; + + if (u4IsWPSmode) + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 1; + else + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = 0; + + status = nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + return status; +} /* end of wlanoidSetP2pWPSmode() */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + DEBUGFUNC("wlanoidQueryP2pRssi"); + + ASSERT(prAdapter); + ASSERT(pu4QueryInfoLen); + if (u4QueryBufferLen) + ASSERT(pvQueryBuffer); + + *pu4QueryInfoLen = sizeof(PARAM_RSSI); + + /* Check for query buffer length */ + if (u4QueryBufferLen < *pu4QueryInfoLen) { + DBGLOG(REQ, WARN, "Too short length %u\n", u4QueryBufferLen); + return WLAN_STATUS_BUFFER_TOO_SHORT; + } + + if (prAdapter->fgIsP2pLinkQualityValid == TRUE && + (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) <= CFG_LINK_QUALITY_VALID_PERIOD) { + PARAM_RSSI rRssi; + + rRssi = (PARAM_RSSI) prAdapter->rP2pLinkQuality.cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + + kalMemCopy(pvQueryBuffer, &rRssi, sizeof(PARAM_RSSI)); + return WLAN_STATUS_SUCCESS; + } +#ifdef LINUX + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, + *pu4QueryInfoLen, pvQueryBuffer, pvQueryBuffer, u4QueryBufferLen); +#else + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_LINK_QUALITY, + FALSE, + TRUE, + TRUE, + nicCmdEventQueryLinkQuality, + nicOidCmdTimeoutCommon, 0, NULL, pvQueryBuffer, u4QueryBufferLen); + +#endif +} /* wlanoidQueryP2pRssi */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h new file mode 100644 index 0000000000000..89de18c89c1cc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/CFG_Wifi_File.h @@ -0,0 +1,238 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/CFG_Wifi_File.h#1 +*/ + +/*! \file CFG_Wifi_File.h + \brief Collection of NVRAM structure used for YuSu project + + In this file we collect all compiler flags and detail the driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + +/* +** Log: CFG_Wifi_File.h + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 09 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * update NVRAM data structure definition. + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition + * follow-up for CMD_5G_PWR_OFFSET_T definition change + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * +*/ + +#ifndef _CFG_WIFI_FILE_H +#define _CFG_WIFI_FILE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* duplicated from nic_cmd_event.h to avoid header dependency */ +typedef struct _TX_PWR_PARAM_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[3]; /* form MT6628 acReserved[0]=cTxPwr2G4Dsss */ + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} TX_PWR_PARAM_T, *P_TX_PWR_PARAM_T; + +typedef struct _PWR_5G_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} PWR_5G_OFFSET_T, *P_PWR_5G_OFFSET_T; + +typedef struct _PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} PWR_PARAM_T, *P_PWR_PARAM_T; + +typedef struct _MT6620_CFG_PARAM_STRUCT { + /* 256 bytes of MP data */ + UINT_16 u2Part1OwnVersion; + UINT_16 u2Part1PeerVersion; + UINT_8 aucMacAddress[6]; + UINT_8 aucCountryCode[2]; + TX_PWR_PARAM_T rTxPwr; + UINT_8 aucEFUSE[144]; + UINT_8 ucTxPwrValid; + UINT_8 ucSupport5GBand; + UINT_8 fg2G4BandEdgePwrUsed; + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + + UINT_8 ucRegChannelListMap; + UINT_8 ucRegChannelListIndex; + UINT_8 aucRegSubbandInfo[36]; + + UINT_8 aucReserved2[256 - 240]; + + /* 256 bytes of function data */ + UINT_16 u2Part2OwnVersion; + UINT_16 u2Part2PeerVersion; + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 aucPreTailReserved; + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 fgRssiCompensationValidbit; + UINT_8 ucRxAntennanumber; + UINT_8 aucTailReserved[256 - 12]; +} MT6620_CFG_PARAM_STRUCT, *P_MT6620_CFG_PARAM_STRUCT, WIFI_CFG_PARAM_STRUCT, *P_WIFI_CFG_PARAM_STRUCT; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +#define CFG_FILE_WIFI_REC_SIZE sizeof(WIFI_CFG_PARAM_STRUCT) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static inline VOID nvramOffsetCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion) == 256); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(WIFI_CFG_PARAM_STRUCT) == 512); + + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) & 0x0001) == 0); + + DATA_STRUCT_INSPECTING_ASSERT((OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) & 0x0001) == 0); +} +#endif + +#endif /* _CFG_WIFI_FILE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h new file mode 100644 index 0000000000000..a52053d5752db --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/config.h @@ -0,0 +1,1628 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/config.h#2 +*/ + +/*! \file "config.h" + \brief This file includes the various configurable parameters for customers + + This file ncludes the configurable parameters except the parameters indicate the turning-on/off of some features +*/ + +/* +** Log: config.h + * + * 07 13 2012 cp.wu + * [WCXRP00001259] [MT6620 Wi-Fi][Driver][Firmware] Send a signal to firmware for + * termination after SDIO error has happened + * [driver domain] add force reset by host-to-device interrupt mechanism + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 06 05 2012 tsaiyuan.hsu + * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" + * resolve build waring for "WNM_UNIT_TEST not defined".. + * + * 06 04 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * discussed with WH, privacy bit in associate response is not necessary to be checked, + * and identified as association failure when mismatching with beacon/probe response + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 23 2011 cp.wu + * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection + * add compile option to disable beacon content change detection. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 10 28 2011 cp.wu + * [MT6620 Wi-Fi][Win32 Driver] Enable 5GHz support as default + * enable 5GHz as default for DaVinci trunk and V2.1 driver release . + * + * 10 18 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * surpress compiler warning for MT6628 build + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * enable divided firmware downloading. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 28 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * enlarge window size only by 4. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 12 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. + * + * 08 09 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS definition for MT6620. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Refine compile flag. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 06 24 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * increase RX buffer number to have a 2:1 ping-pong ratio + * + * 06 23 2011 eddie.chen + * [WCXRP00000810] [MT5931][DRV/FW] Adjust TxRx Buffer number and Rx buffer size + * 1. Different TX RX buffer + * 2. Enlarge RX buffer and increase the number 8->11 + * 3. Separate the WINSZIE and RX buffer number + * 4. Fix RX maximum size in MAC + * + * 06 20 2011 terry.wu + * NULL + * Add BoW Rate Limitation. + * + * 06 17 2011 terry.wu + * NULL + * . + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add compile flag for persistent group support. + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Limit AIS to fixed channel same with BOW + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * Enable RX STBC capability + * + * 04 11 2011 george.huang + * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF + * . + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. correction: RX aggregation is not limited to SDIO but for all host interface options + * 2. add forward declarations for DBG-only symbols + * + * 04 06 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port + * 2. update perm_addr as well for MAC address + * 3. not calling check_mem_region() anymore for eHPI + * 4. correct MSC_CS macro for 0-based notation + * + * 04 01 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface + * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR + * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with + * user space process for RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 18 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the Anti_piracy check at driver . + * + * 03 17 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * enable roaming feature. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one + * to reduce physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 03 01 2011 george.huang + * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames + * Fix compile issue + * + * 02 25 2011 george.huang + * [WCXRP00000497] [MT6620 Wi-Fi][FW] Change default UAPSD AC assignment + * Assign all AC default to be U-APSD enabled. + * + * 02 14 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * Let the privacy check at hotspot mode default enable. + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 02 08 2011 cp.wu + * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number + * change version number to v1.2.0.0 for preparing v1.2 software package release. + * + * 02 01 2011 yarco.yang + * [WCXRP00000417] [MT6620 Driver] Change CFG_HANDLE_IST_IN_SDIO_CALLBACK from 1 to 0 for Interoperability + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 19 2011 wh.su + * [WCXRP00000370] [MT6620 Wi-Fi][Driver] Disable Rx RDG for workaround pre-N ccmp issue + * Not announce support Rx RDG for wokaround pre-N ccmp construct AAD issue.. + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause + * hardware header translation needs such information + * fill mac header length information for 802.1x frames. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW only for Linux. + * + * 01 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Enable BOW and 4 physical links. + * + * 01 08 2011 yuche.tsai + * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, + * but the SSID length is still invalid. + * Modify CFG_SLT_SUPPORT default value. + * + * 01 08 2011 yuche.tsai + * [WCXRP00000341] [MT6620][SLT] Create Branch for SLT SW. + * Update configure flag. + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 15 2010 yuche.tsai + * NULL + * Update SLT Descriptor number configure in driver. + * + * 12 13 2010 chinglan.wang + * NULL + * Add WPS 1.0 feature flag to enable the WPS 1.0 function. + * + * 11 23 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Enable PM function by default + * + * 11 15 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * use config.mk WAPI config define. + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * use the config.mk define. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add option for enable/disable TX PWR gain adjustment (default: off) + * + * 10 20 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * enable the WAPI compiling flag as default + * + * 10 19 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 14 2010 wh.su + * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * Add a define CFG_TEST_ANDROID_DIRECT_GO compiling flag + * + * 10 08 2010 cm.chang + * NULL + * Remove unused compiling flags (TX_RDG and TX_SGI) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 05 2010 yarco.yang + * [WCXRP00000082] [MT6620 Wi-Fi][Driver]High throughput performance tuning + * Change CFG_IST_LOOP_COUNT from 2 to 1 to reduce unnecessary SDIO bus access + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 20 2010 cm.chang + * NULL + * Disable RX STBC by BB HEC based on MT6620E1_PHY_BUG v05.docx + * + * 09 17 2010 chinglan.wang + * NULL + * Add performance test option + * + * 09 10 2010 chinglan.wang + * NULL + * Modify for Software Migration Phase 2.10 for E2 FPGA + * + * 09 07 2010 yuche.tsai + * NULL + * Add a CFG for max common IE buffer size. + * + * 09 01 2010 cp.wu + * NULL + * restore configuration as before. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 chinglan.wang + * NULL + * Enable the MT6620_FPGA_BWCS value. + * + * 08 30 2010 chinglan.wang + * NULL + * Disable the FW encryption. + * + * 08 27 2010 chinglan.wang + * NULL + * Update configuration for MT6620_E1_PRE_ALPHA_1832_0827_2010 + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 cp.wu + * NULL + * add option for enabling AIS 5GHz scan + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cp.wu + * NULL + * 1) initialize variable for enabling short premable/short time slot. + * 2) add compile option for disabling online scan + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 23 2010 chinghwa.yu + * NULL + * Disable BOW Test. + * + * 08 23 2010 jeffrey.chang + * NULL + * fix config.h typo + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 21 2010 jeffrey.chang + * NULL + * 1) add sdio two setting + * 2) bug fix of sdio glue + * + * 08 09 2010 wh.su + * NULL + * let the firmware download default enabled. + * + * 08 07 2010 wh.su + * NULL + * adding the privacy related code for P2P network + * + * 08 05 2010 yuche.tsai + * NULL + * Add a configure flag for P2P unitest. + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 cp.wu + * + * 1) enable Ad-Hoc + * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 yuche.tsai + * + * Add for SLT support. + * + * 07 16 2010 cp.wu + * + * remove work-around in case SCN is not available. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor + * underflow under concurrent network operation + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * for first connection, if connecting failed do not enter into scan state. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add SCN compilation option. + * 2) when SCN is not turned on, BSSID_SCAN will generate a fake entry for 1st connection + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * set default compiling flag for security disable. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add config option for cfg80211. + * + * 05 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * set ATIMwindow default value to zero. + * + * 05 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add option for FPGA_BWCS & FPGA_V5 + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) enable CMD/EVENT ver 0.9 definition. + * 2) abandon use of ENUM_MEDIA_STATE + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change firmware name to WIFI_RAM_CODE. + * + * 05 07 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * disable bt-over-wifi configuration, turn it on after firmware finished implementation + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * re-enable power management + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable TCP/IP checksum offloading by default. + * + * 04 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * set CFG_ENABLE_FULL_PM to 1 as default to + * 1) acquire own before hardware access + * 2) set own back after hardware access + * + * 04 15 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * change firmware name + * + * 04 07 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * disable RX-enhanced response temporally, it seems the CQ is not resolved yet. + * + * 04 06 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * re-enable RX enhanced mode as WPD00003827 is resolved. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * turn off RX_ENHANCE mode by default. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) eliminate unused definitions + * * 2) ready bit will be polled for limited iteration + * + * 04 02 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * firmware download: Linux uses different firmware path + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load address & start address are now configured from config.h + * * due to the different configurations on FPGA and ASIC + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add options for full PM support. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * turn on FW-DOWNLOAD as default for release. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 05 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * change CFG_NUM_OF_QM_RX_PKT_NUM to 120 + * + * 03 04 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * . + * + * 03 04 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * increase RX buffer number to avoid RX buffer starvation. + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed the number of STA_RECs to 20 + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * and result is retrieved by get ATInfo instead + * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-16 22:12:28 GMT mtk02752 +** enable interrupt enhanced response, TX/RX Aggregation as default +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:38:43 GMT mtk02752 +** eliminate compile options which are obsolete or for emulation purpose +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 13:56:26 GMT MTK02468 +** Added RX buffer reordering configurations +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-12-04 12:09:09 GMT mtk02752 +** once enhanced intr/rx response is taken, RX must be access in aggregated basis +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 17:54:50 GMT mtk02752 +** correct a typo +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:47 GMT mtk01084 +** add defines +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:33:37 GMT mtk02752 +** add coalescing buffer definition for SD1_SD3_DATAPATH_INTEGRATION +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 20:32:40 GMT mtk02752 +** add CFG_TX_MAX_PKT_NUM for limiting queued TX packet +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 13:34:44 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION define for source control +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-13 13:54:11 GMT mtk01084 +** enable INT enhance mode by default +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-30 18:17:14 GMT mtk01084 +** add new define +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-10-29 19:47:36 GMT mtk01084 +** not use HIF loopback mode +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-10-13 21:58:33 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-09-09 17:26:08 GMT mtk01084 +** add CFG_TEST_WITH_MT5921 +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:02:30 GMT mtk01426 +** Update CFG_RX_COALESCING_BUFFER_SIZE +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-21 09:35:51 GMT mtk01461 +** Add CFG_TX_DBG_MGT_BUF to debug MGMT Buffer depth +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:52:21 GMT mtk01426 +** Add OOB_DATA_PRE_FIXED_LEN define +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-08 16:51:08 GMT mtk01084 +** update for FW download part +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:33:37 GMT mtk01461 +** Add SW pre test flag CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 00:29:18 GMT mtk01461 +** Fix CFG_COALESCING_BUFFER_SIZE if enable the CFG_TX_FRAGMENT +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-18 20:58:34 GMT mtk01426 +** Add CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-17 20:17:36 GMT mtk01426 +** Add CMD/Response related configure +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:21 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:21 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _CONFIG_H +#define _CONFIG_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#ifdef MT6620 +#undef MT6620 +#endif + +#ifndef MT6628 +#define MT6628 +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 2 Flags for OS capability */ + +#define MTK_WCN_SINGLE_MODULE 0 /* 1: without WMT */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define MTK_WCN_HIF_SDIO 0 +#else +#define MTK_WCN_HIF_SDIO 0 /* samp */ +#endif +#else +#define MTK_WCN_HIF_SDIO 0 +#endif + +#if (CFG_SUPPORT_AEE == 1) +#define CFG_ENABLE_AEE_MSG 1 +#else +#define CFG_ENABLE_AEE_MSG 0 +#endif + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +/* 2 Flags for Driver Features */ +#define CFG_TX_FRAGMENT 1 /*!< 1: Enable TX fragmentation + 0: Disable */ +#define CFG_SUPPORT_PERFORMANCE_TEST 0 /*Only for performance Test */ + +#define CFG_COUNTRY_CODE NULL /* "US" */ + +#ifndef LINUX +#define CFG_FW_FILENAME L"WIFI_RAM_CODE" +#define CFG_FW_FILENAME_E6 L"WIFI_RAM_CODE_E6" +#else +#define CFG_FW_FILENAME "WIFI_RAM_CODE" +#endif +#ifndef LINUX +#define CFG_SUPPORT_CFG_FILE 0 +#else +#define CFG_SUPPORT_CFG_FILE 1 +#endif + +#define CFG_SUPPORT_CE_FCC_TXPWR_LIMIT 0 /* Support CE FCC Tx Power limit */ + +#define CFG_SUPPORT_802_11D 1 /*!< 1(default): Enable 802.11d + 0: Disable */ + +#define CFG_SUPPORT_RRM 0 /* Radio Reasource Measurement (802.11k) */ +#define CFG_SUPPORT_DFS 1 /* DFS (802.11h) */ + +#if (CFG_SUPPORT_DFS == 1) /* Add by Enlai */ +#define CFG_SUPPORT_QUIET 1 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 1 /* Spectrum Management (802.11h): TPC and DFS */ +#else +#define CFG_SUPPORT_QUIET 0 /* Quiet (802.11h) */ +#define CFG_SUPPORT_SPEC_MGMT 0 /* Spectrum Management (802.11h): TPC and DFS */ +#endif + +#define CFG_SUPPORT_RX_RDG 0 /* 11n feature. RX RDG capability */ +#define CFG_SUPPORT_MFB 0 /* 802.11n MCS Feedback responder */ +#define CFG_SUPPORT_RX_STBC 1 /* 802.11n RX STBC (1SS) */ +#define CFG_SUPPORT_RX_SGI 1 /* 802.11n RX short GI for both 20M and 40M BW */ +#define CFG_SUPPORT_RX_HT_GF 1 /* 802.11n RX HT green-field capability */ + +#define CFG_SUPPORT_ROAMING_ENC 0 /* enahnced roaming */ + +#define CFG_SUPPORT_TDLS 1 /* IEEE802.11z TDLS */ +#define CFG_SUPPORT_TDLS_DBG 0 /* TDLS debug */ +#define CFG_SUPPORT_STATISTICS 1 +#define CFG_SUPPORT_DBG_POWERMODE 1 /* for debugging power always active mode */ + +#define CFG_SUPPORT_GSCN 1 + +#define CFG_SUPPORT_TXR_ENC 0 /* enhanced tx rate switch */ + +#define CFG_SUPPORT_PERSIST_NETDEV 0 /* create NETDEV when system bootup */ + +#define CFG_FORCE_USE_20BW 1 +/*------------------------------------------------------------------------------ + * SLT Option + *------------------------------------------------------------------------------ + */ +#define CFG_SLT_SUPPORT 0 + +#define MTK_AUTO_CHANNEL_SEL_SUPPORT_ENABLE 0 + +#if defined(MTK_AUTO_CHANNEL_SEL_SUPPORT_ENABLE) +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 1 +#else +#define CFG_AUTO_CHANNEL_SEL_SUPPORT 0 +#endif + +#ifdef NDIS60_MINIPORT +#define CFG_NATIVE_802_11 1 + +#define CFG_TX_MAX_PKT_SIZE 2304 +#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 /* !< 1: Enable TCP/IP header checksum offload + 0: Disable */ +#define CFG_TCP_IP_CHKSUM_OFFLOAD 0 +#define CFG_WHQL_DOT11_STATISTICS 1 +#define CFG_WHQL_ADD_REMOVE_KEY 1 +#define CFG_WHQL_CUSTOM_IE 1 +#define CFG_WHQL_SAFE_MODE_ENABLED 1 + +#else +#define CFG_TCP_IP_CHKSUM_OFFLOAD 1 /* !< 1: Enable TCP/IP header checksum offload + 0: Disable */ +#define CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 0 +#define CFG_TX_MAX_PKT_SIZE 1600 +#define CFG_NATIVE_802_11 0 +#endif + +/* 2 Flags for Driver Parameters */ +/*------------------------------------------------------------------------------ + * Flags for EHPI Interface in Colibri Platform + *------------------------------------------------------------------------------ + */ +#define CFG_EHPI_FASTER_BUS_TIMING 0 /*!< 1: Do workaround for faster bus timing + 0(default): Disable */ + +/*------------------------------------------------------------------------------ + * Flags for HIFSYS Interface + *------------------------------------------------------------------------------ + */ +#ifdef _lint +#define _HIF_SDIO 0 /* samp */ +#endif + +#define CFG_SDIO_INTR_ENHANCE 1 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode + 0: Disable */ +#define CFG_SDIO_RX_ENHANCE 0 /*!< 1(default): Enable SDIO ISR & TX/RX status enhance mode + 0: Disable */ +#define CFG_SDIO_TX_AGG 1 /*!< 1: Enable SDIO TX enhance + mode(Multiple frames in single BLOCK CMD) + 0(default): Disable */ + +#define CFG_SDIO_RX_AGG 1 /*!< 1: Enable SDIO RX enhance + mode(Multiple frames in single BLOCK CMD) + 0(default): Disable */ + +#if (CFG_SDIO_RX_AGG == 1) && (CFG_SDIO_INTR_ENHANCE == 0) +#error "CFG_SDIO_INTR_ENHANCE should be 1 once CFG_SDIO_RX_AGG equals to 1" +#elif (CFG_SDIO_INTR_ENHANCE == 1 || CFG_SDIO_RX_ENHANCE == 1) && (CFG_SDIO_RX_AGG == 0) +#error "CFG_SDIO_RX_AGG should be 1 once CFG_SDIO_INTR_ENHANCE and/or CFG_SDIO_RX_ENHANCE equals to 1" +#endif + +#define CFG_SDIO_MAX_RX_AGG_NUM 0 /*!< 1: Setting the maximum RX aggregation number + 0(default): no limited */ + +#ifdef WINDOWS_CE +#define CFG_SDIO_PATHRU_MODE 1 /*!< 1: Support pass through (PATHRU) mode + 0: Disable */ +#else +#define CFG_SDIO_PATHRU_MODE 0 /*!< 0: Always disable if WINDOWS_CE is not defined */ +#endif + +#define CFG_MAX_RX_ENHANCE_LOOP_COUNT 3 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Integration + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) +#define MT6620_FPGA_BWCS 0 +#define MT6620_FPGA_V5 0 + +#if (MT6620_FPGA_BWCS == 1) && (MT6620_FPGA_V5 == 1) +#error +#endif + +#if (MTK_WCN_HIF_SDIO == 1) +#define CFG_MULTI_ECOVER_SUPPORT 1 +#elif !defined(LINUX) +#define CFG_MULTI_ECOVER_SUPPORT 1 +#else +#define CFG_MULTI_ECOVER_SUPPORT 0 +#endif + +#define CFG_ENABLE_CAL_LOG 0 +#define CFG_REPORT_RFBB_VERSION 0 + +#elif defined(MT6628) + +#define CFG_MULTI_ECOVER_SUPPORT 0 + +#define CFG_ENABLE_CAL_LOG 1 +#define CFG_REPORT_RFBB_VERSION 1 + +#endif + +#define CFG_CHIP_RESET_SUPPORT 1 + +#if defined(MT6628) +#define CFG_EMBED_FIRMWARE_BUILD_DATE_CODE 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags for workaround + *------------------------------------------------------------------------------ + */ +#if defined(MT6620) && (MT6620_FPGA_BWCS == 0) && (MT6620_FPGA_V5 == 0) +#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#else +#define MT6620_E1_ASIC_HIFSYS_WORKAROUND 0 +#endif + +/* SPM issue: suspend current is higher than deep idle */ +#define CFG_SPM_WORKAROUND_FOR_HOTSPOT 1 + +/*------------------------------------------------------------------------------ + * Flags for driver version + *------------------------------------------------------------------------------ + */ +#define CFG_DRV_OWN_VERSION \ + ((UINT_16)((NIC_DRIVER_MAJOR_VERSION << 8) | (NIC_DRIVER_MINOR_VERSION))) +#define CFG_DRV_PEER_VERSION ((UINT_16)0x0000) + +/*------------------------------------------------------------------------------ + * Flags for TX path which are OS dependent + *------------------------------------------------------------------------------ + */ +/*! NOTE(Kevin): If the Network buffer is non-scatter-gather like structure(without + * NETIF_F_FRAGLIST in LINUX), then we can set CFG_TX_BUFFER_IS_SCATTER_LIST to "0" + * for zero copy TX packets. + * For scatter-gather like structure, we set "1", driver will do copy frame to + * internal coalescing buffer before write it to FIFO. + */ +#if defined(LINUX) +#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 /*!< 1: Do frame copy before write to TX FIFO. + Used when Network buffer is scatter-gather. + 0(default): Do not copy frame */ +#else /* WINDOWS/WINCE */ +#define CFG_TX_BUFFER_IS_SCATTER_LIST 1 +#endif /* LINUX */ + +#if CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST +#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE * NIC_TX_BUFF_SUM) +#else +#define CFG_COALESCING_BUFFER_SIZE (CFG_TX_MAX_PKT_SIZE) +#endif /* CFG_SDIO_TX_AGG || CFG_TX_BUFFER_IS_SCATTER_LIST */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for TX path + *------------------------------------------------------------------------------ + */ + +/*! Maximum number of SW TX packet queue */ +#define CFG_TX_MAX_PKT_NUM 512 /* 256 must >= CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD * 2; + or wmm will fail when queue is full */ + +/*! Maximum number of SW TX CMD packet buffer */ +#define CFG_TX_MAX_CMD_PKT_NUM 32 + +/*! Maximum number of associated STAs */ +#define CFG_NUM_OF_STA_RECORD 20 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for RX path + *------------------------------------------------------------------------------ + */ + +/*! Max. descriptor number - sync. with firmware */ +#if CFG_SLT_SUPPORT +#define CFG_NUM_OF_RX0_HIF_DESC 42 +#else +#define CFG_NUM_OF_RX0_HIF_DESC 16 +#endif +#define CFG_NUM_OF_RX1_HIF_DESC 2 + +/*! Max. buffer hold by QM */ +#define CFG_NUM_OF_QM_RX_PKT_NUM 120 + +/*! Maximum number of SW RX packet buffer */ +#define CFG_RX_MAX_PKT_NUM ((CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC) * 3 \ + + CFG_NUM_OF_QM_RX_PKT_NUM) + +#define CFG_RX_REORDER_Q_THRESHOLD 8 + +#ifndef LINUX +#define CFG_RX_RETAINED_PKT_THRESHOLD \ + (CFG_NUM_OF_RX0_HIF_DESC + CFG_NUM_OF_RX1_HIF_DESC + CFG_NUM_OF_QM_RX_PKT_NUM) +#else +#define CFG_RX_RETAINED_PKT_THRESHOLD 0 +#endif + +/*! Maximum RX packet size, if exceed this value, drop incoming packet */ +/* 7.2.3 Maganement frames */ +#define CFG_RX_MAX_PKT_SIZE (28 + 2312 + 12 /*HIF_RX_HEADER_T*/) /* TODO: it should be + 4096 under emulation mode */ + +/*! Minimum RX packet size, if lower than this value, drop incoming packet */ +#define CFG_RX_MIN_PKT_SIZE 10 /*!< 802.11 Control Frame is 10 bytes */ + +#if CFG_SDIO_RX_AGG + /* extra size for CS_STATUS and enhanced response */ +#define CFG_RX_COALESCING_BUFFER_SIZE ((CFG_NUM_OF_RX0_HIF_DESC + 1) \ + * CFG_RX_MAX_PKT_SIZE) +#else +#define CFG_RX_COALESCING_BUFFER_SIZE (CFG_RX_MAX_PKT_SIZE) +#endif + +/*! RX BA capability */ +#define CFG_NUM_OF_RX_BA_AGREEMENTS 8 +#define CFG_RX_BA_MAX_WINSIZE 16 +#define CFG_RX_BA_INC_SIZE 4 +#define CFG_RX_MAX_BA_TID_NUM 8 +#define CFG_RX_REORDERING_ENABLED 1 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for CMD/RESPONSE + *------------------------------------------------------------------------------ + */ +#define CFG_RESPONSE_POLLING_TIMEOUT 512 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Protocol Stack + *------------------------------------------------------------------------------ + */ +/*! Maximum number of BSS in the SCAN list */ +#define CFG_MAX_NUM_BSS_LIST 64 + +#define CFG_MAX_COMMON_IE_BUF_LEN ((1500 * CFG_MAX_NUM_BSS_LIST) / 3) + +/*! Maximum size of Header buffer of each SCAN record */ +#define CFG_RAW_BUFFER_SIZE 1024 + +/*! Maximum size of IE buffer of each SCAN record */ +#define CFG_IE_BUFFER_SIZE 512 + +/*! Maximum number of STA records */ +#define CFG_MAX_NUM_STA_RECORD 32 + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Power management + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FULL_PM 1 +#define CFG_ENABLE_WAKEUP_ON_LAN 0 +#if defined(CONFIG_ARCH_MT6755) || defined(CONFIG_ARCH_MT6735) || defined(CONFIG_ARCH_MT6735M) || \ + defined(CONFIG_ARCH_MT6753) || defined(CONFIG_ARCH_MT6580) +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 1 /* debug which packet wake up host */ +#else +#define CFG_SUPPORT_WAKEUP_REASON_DEBUG 0 /* debug which packet wake up host */ +#endif +#define CFG_INIT_POWER_SAVE_PROF ENUM_PSP_FAST_SWITCH + +#define CFG_INIT_ENABLE_PATTERN_FILTER_ARP 0 + +#define CFG_INIT_UAPSD_AC_BMP 0 /* (BIT(3) | BIT(2) | BIT(1) | BIT(0)) */ + +/* #define CFG_SUPPORT_WAPI 0 */ +#define CFG_SUPPORT_WPS 1 +#define CFG_SUPPORT_WPS2 1 + +/*------------------------------------------------------------------------------ + * 802.11i RSN Pre-authentication PMKID cahce maximun number + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_PMKID_CACHE 16 /*!< max number of PMKID cache + 16(default) : The Max PMKID cache */ +/*------------------------------------------------------------------------------ + * Auto Channel Selection Maximun Channel Number + *------------------------------------------------------------------------------ + */ + +#define MAX_AUTO_CHAL_NUM 23 /* Ch1~Ch14,Ch36,Ch40,Ch44, + Ch48,Ch149,Ch153,Ch157,Ch161 */ +/*------------------------------------------------------------------------------ + * FAST SCAN + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FAST_SCAN 0 +#define CFG_CN_SUPPORT_CLASS121 0 /* Add Class 121, 5470-5725MHz, support for China domain */ +#if CFG_ENABLE_FAST_SCAN + #define CFG_FAST_SCAN_DWELL_TIME 40 + #define CFG_FAST_SCAN_REG_DOMAIN_DEF_IDX 10 +#endif +/*------------------------------------------------------------------------------ + * Flags and Parameters for Ad-Hoc + *------------------------------------------------------------------------------ + */ +#define CFG_INIT_ADHOC_FREQ (2462000) +#define CFG_INIT_ADHOC_MODE AD_HOC_MODE_MIXED_11BG +#define CFG_INIT_ADHOC_BEACON_INTERVAL (100) +#define CFG_INIT_ADHOC_ATIM_WINDOW (0) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Maximum Scan SSID number + *------------------------------------------------------------------------------ + */ +#define CFG_SCAN_SSID_MAX_NUM (4) +#define CFG_SCAN_SSID_MATCH_MAX_NUM (16) + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Load Setup Default + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags for enable 802.11A Band setting + *------------------------------------------------------------------------------ + */ + +/*------------------------------------------------------------------------------ + * Flags and Parameters for Interrupt Process + *------------------------------------------------------------------------------ + */ +#if defined(_HIF_SDIO) && defined(WINDOWS_CE) +#define CFG_IST_LOOP_COUNT 8 +#else +#define CFG_IST_LOOP_COUNT 8 +#endif /* _HIF_SDIO */ + +#define CFG_INT_WRITE_CLEAR 0 + +#if defined(LINUX) +#define CFG_DBG_GPIO_PINS 0 /* if 1, use MT6516 GPIO pin to log TX behavior */ +#endif + +/* 2 Flags for Driver Debug Options */ +/*------------------------------------------------------------------------------ + * Flags of TX Debug Option. NOTE(Kevin): Confirm with SA before modifying following flags. + *------------------------------------------------------------------------------ + */ +#define CFG_DBG_MGT_BUF 1 /*!< 1: Debug statistics usage of MGMT Buffer + 0: Disable */ + +#define CFG_HIF_STATISTICS 0 + +#define CFG_HIF_RX_STARVATION_WARNING 0 + +#define CFG_STARTUP_DEBUG 0 + +#define CFG_RX_PKTS_DUMP 1 + +/*------------------------------------------------------------------------------ + * Flags of Firmware Download Option. + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_FW_DOWNLOAD 1 + +#define CFG_ENABLE_FW_DOWNLOAD_ACK 1 +#define CFG_ENABLE_FW_ENCRYPTION 1 + +#if defined(MT6628) +#define CFG_ENABLE_FW_DOWNLOAD_AGGREGATION 0 +#define CFG_ENABLE_FW_DIVIDED_DOWNLOAD 1 +#endif + +#if defined(MT6620) +#if MT6620_FPGA_BWCS +#define CFG_FW_LOAD_ADDRESS 0x10014000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10014001 +#elif MT6620_FPGA_V5 +#define CFG_FW_LOAD_ADDRESS 0x10008000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10008001 +#else +#define CFG_FW_LOAD_ADDRESS 0x10008000 +#define CFG_OVERRIDE_FW_START_ADDRESS 0 +#define CFG_FW_START_ADDRESS 0x10008001 +#endif +#elif defined(MT6628) +#define CFG_FW_LOAD_ADDRESS 0x00060000 +#define CFG_OVERRIDE_FW_START_ADDRESS 1 +#define CFG_FW_START_ADDRESS 0x00060000 +#define CFG_START_ADDRESS_IS_1ST_SECTION_ADDR 1 +#endif + +/*------------------------------------------------------------------------------ + * Flags of Bluetooth-over-WiFi (BT 3.0 + HS) support + *------------------------------------------------------------------------------ + */ + +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_BT_OVER_WIFI 0 +#else +#define CFG_ENABLE_BT_OVER_WIFI 1 +#endif +#else +#define CFG_ENABLE_BT_OVER_WIFI 0 +#endif + +#define CFG_BOW_SEPARATE_DATA_PATH 1 + +#define CFG_BOW_PHYSICAL_LINK_NUM 4 + +#define CFG_BOW_TEST 0 + +#define CFG_BOW_LIMIT_AIS_CHNL 1 + +#define CFG_BOW_SUPPORT_11N 0 + +#define CFG_BOW_RATE_LIMITATION 1 + +/*------------------------------------------------------------------------------ + * Flags of Wi-Fi Direct support + *------------------------------------------------------------------------------ + */ +#ifdef LINUX +#ifdef CONFIG_X86 +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 +#else +#define CFG_ENABLE_WIFI_DIRECT 1 +#define CFG_SUPPORT_802_11W 0 /*!< 0(default): Disable 802.11W */ +#endif +#else +#define CFG_ENABLE_WIFI_DIRECT 0 +#define CFG_SUPPORT_802_11W 0 /* Not support at WinXP */ +#endif + +#define CFG_SUPPORT_PERSISTENT_GROUP 0 + +#define CFG_TEST_WIFI_DIRECT_GO 0 + +#define CFG_TEST_ANDROID_DIRECT_GO 0 + +#define CFG_UNITEST_P2P 0 + +/* + * Enable cfg80211 option after Android 2.2(Froyo) is suggested, + * cfg80211 on linux 2.6.29 is not mature yet + */ +#define CFG_ENABLE_WIFI_DIRECT_CFG_80211 1 + +#define CFG_SUPPORT_HOTSPOT_OPTIMIZATION 1 +#define CFG_HOTSPOT_OPTIMIZATION_BEACON_INTERVAL 300 +#define CFG_HOTSPOT_OPTIMIZATION_DTIM 1 + +/*------------------------------------------------------------------------------ + * Configuration Flags (Linux Only) + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_EXT_CONFIG 0 + +/*------------------------------------------------------------------------------ + * Statistics Buffering Mechanism + *------------------------------------------------------------------------------ + */ +#if CFG_SUPPORT_PERFORMANCE_TEST +#define CFG_ENABLE_STATISTICS_BUFFERING 1 +#else +#define CFG_ENABLE_STATISTICS_BUFFERING 0 +#endif +#define CFG_STATISTICS_VALID_CYCLE 2000 +#define CFG_LINK_QUALITY_VALID_PERIOD 5000 + +/*------------------------------------------------------------------------------ + * Migration Option + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_ADHOC 0 +#define CFG_SUPPORT_AAA 1 + +#define CFG_SUPPORT_BCM 0 +#define CFG_SUPPORT_BCM_BWCS 0 +#define CFG_SUPPORT_BCM_BWCS_DEBUG 0 + +#define CFG_SUPPORT_RDD_TEST_MODE 0 + +#define CFG_SUPPORT_PWR_MGT 1 + +#define CFG_RSN_MIGRATION 1 + +#define CFG_PRIVACY_MIGRATION 1 + +#define CFG_ENABLE_HOTSPOT_PRIVACY_CHECK 1 + +#define CFG_MGMT_FRAME_HANDLING 1 + +#define CFG_MGMT_HW_ACCESS_REPLACEMENT 0 + +#if CFG_SUPPORT_PERFORMANCE_TEST + +#else + +#endif + +#define CFG_SUPPORT_AIS_5GHZ 1 +#define CFG_SUPPORT_BEACON_CHANGE_DETECTION 0 + +/*------------------------------------------------------------------------------ + * Option for NVRAM and Version Checking + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_NVRAM 1 +#define CFG_NVRAM_EXISTENCE_CHECK 1 +#define CFG_SW_NVRAM_VERSION_CHECK 1 +#define CFG_SUPPORT_NIC_CAPABILITY 1 + +/*------------------------------------------------------------------------------ + * CONFIG_TITLE : Stress Test Option + * OWNER : Puff Wen + * Description : For stress test only. DO NOT enable it while normal operation + *------------------------------------------------------------------------------ + */ +#define CFG_STRESS_TEST_SUPPORT 0 + +/*------------------------------------------------------------------------------ + * Flags for LINT + *------------------------------------------------------------------------------ + */ +#define LINT_SAVE_AND_DISABLE /*lint -save -e* */ + +#define LINT_RESTORE /*lint -restore */ + +#define LINT_EXT_HEADER_BEGIN LINT_SAVE_AND_DISABLE + +#define LINT_EXT_HEADER_END LINT_RESTORE + +/*------------------------------------------------------------------------------ + * Flags of Features + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_QOS 1 /* Enable/disable QoS TX, AMPDU */ +#define CFG_SUPPORT_AMPDU_TX 1 +#define CFG_SUPPORT_AMPDU_RX 1 +#define CFG_SUPPORT_TSPEC 0 /* Enable/disable TS-related Action frames handling */ +#define CFG_SUPPORT_UAPSD 1 +#define CFG_SUPPORT_UL_PSMP 0 + +#define CFG_SUPPORT_ROAMING 1 /* Roaming System */ +#define CFG_SUPPORT_SWCR 1 + +#define CFG_SUPPORT_ANTI_PIRACY 1 + +#define CFG_SUPPORT_OSC_SETTING 1 + +#define CFG_SUPPORT_P2P_RSSI_QUERY 0 + +#define CFG_SHOW_MACADDR_SOURCE 1 + +#define CFG_SUPPORT_802_11V 0 /* Support 802.11v Wireless Network Management */ +#define CFG_SUPPORT_802_11V_TIMING_MEASUREMENT 0 +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (CFG_SUPPORT_802_11V == 0) +#error "CFG_SUPPORT_802_11V should be 1 once CFG_SUPPORT_802_11V_TIMING_MEASUREMENT equals to 1" +#endif +#if (CFG_SUPPORT_802_11V == 0) +#define WNM_UNIT_TEST 0 +#endif + +#define CFG_DRIVER_COMPOSE_ASSOC_REQ 1 + +#define CFG_STRICT_CHECK_CAPINFO_PRIVACY 0 + +#define CFG_SUPPORT_WFD 1 + +#define CFG_SUPPORT_WFD_COMPOSE_IE 1 + +/*------------------------------------------------------------------------------ + * Flags of Packet Lifetime Profiling Mechanism + *------------------------------------------------------------------------------ + */ +#define CFG_ENABLE_PKT_LIFETIME_PROFILE 1 + +#define CFG_ENABLE_PER_STA_STATISTICS 1 + +#define CFG_PRINT_RTP_PROFILE 0 /* If want to enable WFD Debug, please change it to 1. */ +#define CFG_PRINT_RTP_SN_SKIP 0 + +#define CFG_SUPPORT_PWR_LIMIT_COUNTRY 1 +/*------------------------------------------------------------------------------ + * Flags of bus error tolerance + *------------------------------------------------------------------------------ + */ +#define CFG_FORCE_RESET_UNDER_BUS_ERROR 0 + +/*------------------------------------------------------------------------------ + * Build Date Code Integration + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BUILD_DATE_CODE 1 + +/*------------------------------------------------------------------------------ + * Flags for prepare the FW compile flag + *------------------------------------------------------------------------------ + */ +#define COMPILE_FLAG0_GET_STA_LINK_STATUS (1<<0) +#define COMPILE_FLAG0_WFD_ENHANCEMENT_PROTECT (1<<1) + +/*------------------------------------------------------------------------------ + * Flags of Batch Scan SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_BATCH_SCAN 0 +#define CFG_BATCH_MAX_MSCAN 2 + +/*------------------------------------------------------------------------------ + * Flags of Channel Environment SUPPORT + *------------------------------------------------------------------------------ + */ +#define CFG_SUPPORT_GET_CH_ENV 1 + +/*------------------------------------------------------------------------------ + * Flags of THERMO_THROTTLING SUPPORT + *------------------------------------------------------------------------------ + */ + +#define CFG_SUPPORT_THERMO_THROTTLING 1 +#define WLAN_INCLUDE_PROC 1 + +#define CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE 1 +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _CONFIG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h new file mode 100644 index 0000000000000..af586063c21af --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/debug.h @@ -0,0 +1,466 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/debug.h#1 +*/ + +/*! \file debug.h + \brief Definition of SW debugging level. + + In this file, it describes the definition of various SW debugging levels and + assert functions. +*/ + +/* +** Log: debug.h + * + * 12 16 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * fixed the Windows DDK free build compiling error. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 07 2011 wh.su + * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * . + * + * 09 23 2010 cp.wu + * NULL + * add BOW index for debugging message and passing compilation + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add one more debug moduel for P2P. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add debug module index for cnm and ais. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add CFG_STARTUP_DEBUG for debugging starting up issue. + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-29 19:47:50 GMT mtk01084 +** add emu category +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-17 18:12:04 GMT mtk01426 +** Don't use dynamic memory allocate for debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:29 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _DEBUG_H +#define _DEBUG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#ifndef BUILD_QA_DBG +#define BUILD_QA_DBG 0 +#endif + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +extern UINT_8 aucDebugModule[]; +extern UINT_32 u4DebugModule; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define debug category (class): + * (1) ERROR (2) WARN (3) STATE (4) EVENT (5) TRACE (6) INFO (7) LOUD (8) TEMP + */ +#define DBG_CLASS_ERROR BIT(0) +#define DBG_CLASS_WARN BIT(1) +#define DBG_CLASS_STATE BIT(2) +#define DBG_CLASS_EVENT BIT(3) +#define DBG_CLASS_TRACE BIT(4) +#define DBG_CLASS_INFO BIT(5) +#define DBG_CLASS_LOUD BIT(6) +#define DBG_CLASS_TEMP BIT(7) +#define DBG_CLASS_MASK BITS(0, 7) + +#if defined(LINUX) +#define DBG_PRINTF_64BIT_DEC "lld" + +#else /* Windows */ +#define DBG_PRINTF_64BIT_DEC "I64d" + +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Define debug module index */ +typedef enum _ENUM_DBG_MODULE_T { + DBG_INIT_IDX = 0, /* For driver initial */ + DBG_HAL_IDX, /* For HAL(HW) Layer */ + DBG_INTR_IDX, /* For Interrupt */ + DBG_REQ_IDX, + DBG_TX_IDX, + DBG_RX_IDX, + DBG_RFTEST_IDX, /* For RF test mode */ + DBG_EMU_IDX, /* Developer specific */ + + DBG_SW1_IDX, /* Developer specific */ + DBG_SW2_IDX, /* Developer specific */ + DBG_SW3_IDX, /* Developer specific */ + DBG_SW4_IDX, /* Developer specific */ + + DBG_HEM_IDX, /* HEM */ + DBG_AIS_IDX, /* AIS */ + DBG_RLM_IDX, /* RLM */ + DBG_MEM_IDX, /* RLM */ + DBG_CNM_IDX, /* CNM */ + DBG_RSN_IDX, /* RSN */ + DBG_BSS_IDX, /* BSS */ + DBG_SCN_IDX, /* SCN */ + DBG_SAA_IDX, /* SAA */ + DBG_AAA_IDX, /* AAA */ + DBG_P2P_IDX, /* P2P */ + DBG_QM_IDX, /* QUE_MGT */ + DBG_SEC_IDX, /* SEC */ + DBG_BOW_IDX, /* BOW */ + DBG_WAPI_IDX, /* WAPI */ + DBG_ROAMING_IDX, /* ROAMING */ + DBG_TDLS_IDX, /* TDLS *//* CFG_SUPPORT_TDLS */ + DBG_OID_IDX, + DBG_NIC_IDX, + + DBG_MODULE_NUM /* Notice the XLOG check */ +} ENUM_DBG_MODULE_T; + +/* XLOG */ +/* #define XLOG_DBG_MODULE_IDX 28 */ /* DBG_MODULE_NUM */ +/* #if (XLOG_DBG_MODULE_IDX != XLOG_DBG_MODULE_IDX) */ +/* #error "Please modify the DBG_MODULE_NUM and make sure this include at XLOG" */ +/* #endif */ + +/* Define who owns developer specific index */ +#define DBG_YARCO_IDX DBG_SW1_IDX +#define DBG_KEVIN_IDX DBG_SW2_IDX +#define DBG_CMC_IDX DBG_SW3_IDX +#define DBG_GEORGE_IDX DBG_SW4_IDX + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Debug print format string for the OS system time */ +#define OS_SYSTIME_DBG_FORMAT "0x%08x" + +/* Debug print argument for the OS system time */ +#define OS_SYSTIME_DBG_ARGUMENT(systime) (systime) + +/* Debug print format string for the MAC Address */ +#define MACSTR "%pM" +/* "%02x:%02x:%02x:%02x:%02x:%02x" */ + +/* Debug print argument for the MAC Address */ +#define MAC2STR(a) a +/* ((PUINT_8)a)[0], ((PUINT_8)a)[1], ((PUINT_8)a)[2], ((PUINT_8)a)[3], ((PUINT_8)a)[4], ((PUINT_8)a)[5] */ + +/* The pre-defined format to dump the value of a varaible with its name shown. */ +#define DUMPVAR(variable, format) (#variable " = " format "\n", variable) + +/* The pre-defined format to dump the MAC type value with its name shown. */ +#define DUMPMACADDR(addr) (#addr " = %pM\n", (addr)) + +/* Basiclly, we just do renaming of KAL functions although they should + * be defined as "Nothing to do" if DBG=0. But in some compiler, the macro + * syntax does not support #define LOG_FUNC(x,...) + * + * A caller shall not invoke these three macros when DBG=0. + */ + +/*LOG_FUNC("[wlan]%s:(" #_Module " " #_Class ") "_Fmt, __func__, ##__VA_ARGS__);*/ + +#define LOG_FUNC kalPrint + +#if defined(LINUX) +#define DBGLOG(_Module, _Class, _Fmt, ...) \ + do { \ + if ((aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) == 0) \ + break; \ + LOG_FUNC("%s:(" #_Module " " #_Class ")"_Fmt, __func__, ##__VA_ARGS__); \ + } while (0) +#else +#define DBGLOG(_Module, _Class, _Fmt) +#endif + +#if DBG + +#define TMP_BUF_LEN 256 +#define TMP_WBUF_LEN (TMP_BUF_LEN * 2) + +extern PINT_16 g_wbuf_p; +extern PINT_8 g_buf_p; + + /* If __FUNCTION__ is already defined by compiler, we just use it. */ +#if defined(__func__) +#define DEBUGFUNC(_Func) +#else +#define DEBUGFUNC(_Func) \ + static const char __func__[] = _Func +#endif + +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __func__); \ + dumpMemory8((PUINT_8) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) \ + { \ + if (aucDebugModule[DBG_##_Module##_IDX] & DBG_CLASS_##_Class) { \ + LOG_FUNC("%s: (" #_Module " " #_Class ")\n", __func__); \ + dumpMemory32((PUINT_32) (_StartAddr), (UINT_32) (_Length)); \ + } \ + } + /*lint -restore */ + + /*lint -save -e961 use of '#undef' is discouraged */ +#undef ASSERT + /*lint -restore */ + +#ifdef _lint +#define ASSERT(_exp) \ + { \ + if (!(_exp)) { \ + do {} while (1); \ + } \ + } +#else +#define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } +#endif /* _lint */ + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d %s\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } + +#define DISP_STRING(_str) _str + +#else /* !DBG */ + +#define DEBUGFUNC(_Func) +#define INITLOG(_Fmt) +#define ERRORLOG(_Fmt) +#define WARNLOG(_Fmt) + +#define DBGLOG_MEM8(_Module, _Class, _StartAddr, _Length) +#define DBGLOG_MEM32(_Module, _Class, _StartAddr, _Length) + +#undef ASSERT + +#if BUILD_QA_DBG +#if defined(LINUX) /* For debugging in Linux w/o GDB */ +#define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + kalBreakPoint(); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Assertion failed: %s:%d (%s)\n", __FILE__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + kalBreakPoint(); \ + } \ + } +#else +#ifdef WINDOWS_CE +#define UNICODE_TEXT(_msg) TEXT(_msg) +#define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + TCHAR rUbuf[256]; \ + kalBreakPoint(); \ + _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ + UNICODE_TEXT(__FILE__), \ + __LINE__, \ + UNICODE_TEXT(#_exp)); \ + MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + TCHAR rUbuf[256]; \ + kalBreakPoint(); \ + _stprintf(rUbuf, TEXT("Assertion failed: %s:%d %s\n"), \ + UNICODE_TEXT(__FILE__), \ + __LINE__, \ + UNICODE_TEXT(#_exp)); \ + MessageBox(NULL, rUbuf, TEXT("ASSERT!"), MB_OK); \ + } \ + } +#else +#define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + kalBreakPoint(); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + kalBreakPoint(); \ + } \ + } +#endif /* WINDOWS_CE */ +#endif /* LINUX */ +#else +#define ASSERT(_exp) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ + } \ + } + +#define ASSERT_REPORT(_exp, _fmt) \ + { \ + if (!(_exp) && !fgIsBusAccessFailed) { \ + LOG_FUNC("Warning at %s:%d (%s)\n", __func__, __LINE__, #_exp); \ + LOG_FUNC _fmt; \ + } \ + } +#endif /* BUILD_QA_DBG */ + +#define DISP_STRING(_str) "" + +#endif /* DBG */ + +#if CFG_STARTUP_DEBUG +#if defined(LINUX) +#define DBGPRINTF kalPrint +#else +#define DBGPRINTF DbgPrint +#endif +#else +#define DBGPRINTF(...) +#endif + +/* The following macro is used for debugging packed structures. */ +#ifndef DATA_STRUCT_INSPECTING_ASSERT +#define DATA_STRUCT_INSPECTING_ASSERT(expr) \ +{ \ + switch (0) {case 0: case (expr): default:; } \ +} +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID dumpMemory8(IN PUINT_8 pucStartAddr, IN UINT_32 u4Length); + +VOID dumpMemory32(IN PUINT_32 pu4StartAddr, IN UINT_32 u4Length); + +VOID wlanDebugInit(VOID); +VOID wlanDebugUninit(VOID); +VOID wlanTraceReleaseTcRes(P_ADAPTER_T prAdapter, PUINT_8 aucTxRlsCnt, UINT_8 ucAvailable); +VOID wlanTraceTxCmd(P_CMD_INFO_T prCmd); +VOID wlanDumpTcResAndTxedCmd(PUINT_8 pucBuf, UINT_32 maxLen); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _DEBUG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h new file mode 100644 index 0000000000000..108860c80e2d4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/link.h @@ -0,0 +1,368 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/link.h#1 +*/ + +/*! \file link.h + \brief Definition for simple doubly linked list operations. + + In this file we define the simple doubly linked list data structure and its + operation MACROs and INLINE functions. +*/ + +/* +** Log: link.h + * + * 08 05 2010 yuche.tsai + * NULL + * Modify a MACRO of LINK_FOR_EACH_SAFE for compile error. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833] [MT6620 and MT5931] Driver migration + * . + * + * + * + * + * May 4 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * add WIFI to BORA source control +** \main\maintrunk.MT5921\8 2008-10-16 15:57:11 GMT mtk01461 +** Update driver to fix lint warning +** \main\maintrunk.MT5921\7 2008-08-10 18:47:53 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\6 2007-12-11 00:09:00 GMT mtk01461 +** Add macro for checking valid list +** \main\maintrunk.MT5921\5 2007-11-13 14:27:01 GMT mtk01461 +** Add LINK_IS_INVALID macro +** Revision 1.1.1.1 2007/06/22 08:09:05 MTK01461 +** no message +** +*/ + +#ifndef _LINK_H +#define _LINK_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* May cause page fault & unalignment issue (data abort) */ +#define INVALID_LINK_POISON1 ((VOID *) 0x00100101) +/* Used to verify that nonbody uses non-initialized link entries. */ +#define INVALID_LINK_POISON2 ((VOID *) 0x00100201) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Simple Doubly Linked List Structures - Entry Part */ +typedef struct _LINK_ENTRY_T { + struct _LINK_ENTRY_T *prNext, *prPrev; +} LINK_ENTRY_T, *P_LINK_ENTRY_T; + +/* Simple Doubly Linked List Structures - List Part */ +typedef struct _LINK_T { + P_LINK_ENTRY_T prNext; + P_LINK_ENTRY_T prPrev; + UINT_32 u4NumElem; +} LINK_T, *P_LINK_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#if 0 /* No one use it, temporarily mark it for [Lint - Info 773] */ +#define LINK_ADDR(rLink) { (P_LINK_ENTRY_T)(&(rLink)), (P_LINK_ENTRY_T)(&(rLink)), 0 } + +#define LINK_DECLARATION(rLink) \ + struct _LINK_T rLink = LINK_ADDR(rLink) +#endif + +#define LINK_INITIALIZE(prLink) \ + do { \ + ((P_LINK_T)(prLink))->prNext = (P_LINK_ENTRY_T)(prLink); \ + ((P_LINK_T)(prLink))->prPrev = (P_LINK_ENTRY_T)(prLink); \ + ((P_LINK_T)(prLink))->u4NumElem = 0; \ + } while (0) + +#define LINK_ENTRY_INITIALIZE(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)NULL; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)NULL; \ + } while (0) + +#define LINK_ENTRY_INVALID(prEntry) \ + do { \ + ((P_LINK_ENTRY_T)(prEntry))->prNext = (P_LINK_ENTRY_T)INVALID_LINK_POISON1; \ + ((P_LINK_ENTRY_T)(prEntry))->prPrev = (P_LINK_ENTRY_T)INVALID_LINK_POISON2; \ + } while (0) + +#define LINK_IS_EMPTY(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)(prLink)) + +/* NOTE: We should do memory zero before any LINK been initiated, so we can check + * if it is valid before parsing the LINK. + */ +#define LINK_IS_INVALID(prLink) (((P_LINK_T)(prLink))->prNext == (P_LINK_ENTRY_T)NULL) + +#define LINK_IS_VALID(prLink) (((P_LINK_T)(prLink))->prNext != (P_LINK_ENTRY_T)NULL) + +#define LINK_ENTRY(ptr, type, member) ENTRY_OF(ptr, type, member) + +/* Insert an entry into a link list's head */ +#define LINK_INSERT_HEAD(prLink, prEntry) \ + { \ + linkAdd(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + +/* Append an entry into a link list's tail */ +#define LINK_INSERT_TAIL(prLink, prEntry) \ + { \ + linkAddTail(prEntry, prLink); \ + ((prLink)->u4NumElem)++; \ + } + +/* Peek head entry, but keep still in link list */ +#define LINK_PEEK_HEAD(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prNext, _type, _member) \ + ) + +/* Peek tail entry, but keep still in link list */ +#define LINK_PEEK_TAIL(prLink, _type, _member) \ + ( \ + LINK_IS_EMPTY(prLink) ? \ + NULL : LINK_ENTRY((prLink)->prPrev, _type, _member) \ + ) + +/* Get first entry from a link list */ +/* NOTE: We assume the link entry located at the beginning of "prEntry Type", + * so that we can cast the link entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define LINK_REMOVE_HEAD(prLink, prEntry, _P_TYPE) \ + { \ + ASSERT(prLink); \ + if (LINK_IS_EMPTY(prLink)) { \ + prEntry = (_P_TYPE)NULL; \ + } \ + else { \ + prEntry = (_P_TYPE)(((P_LINK_T)(prLink))->prNext); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } \ + } + +/* Assume the link entry located at the beginning of prEntry Type. + * And also decrease the total entry count. + */ +#define LINK_REMOVE_KNOWN_ENTRY(prLink, prEntry) \ + { \ + ASSERT(prLink); \ + ASSERT(prEntry); \ + linkDel((P_LINK_ENTRY_T)prEntry); \ + ((prLink)->u4NumElem)--; \ + } + +/* Iterate over a link list */ +#define LINK_FOR_EACH(prEntry, prLink) \ + for (prEntry = (prLink)->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prNext) + +/* Iterate over a link list backwards */ +#define LINK_FOR_EACH_PREV(prEntry, prLink) \ + for (prEntry = (prLink)->prPrev; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = (P_LINK_ENTRY_T)prEntry->prPrev) + +/* Iterate over a link list safe against removal of link entry */ +#define LINK_FOR_EACH_SAFE(prEntry, prNextEntry, prLink) \ + for (prEntry = (prLink)->prNext, prNextEntry = prEntry->prNext; \ + prEntry != (P_LINK_ENTRY_T)(prLink); \ + prEntry = prNextEntry, prNextEntry = prEntry->prNext) + +/* Iterate over a link list of given type */ +#define LINK_FOR_EACH_ENTRY(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember)) + +/* Iterate backwards over a link list of given type */ +#define LINK_FOR_EACH_ENTRY_PREV(prObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prPrev, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = LINK_ENTRY(prObj->rMember.prPrev, _TYPE, rMember)) + +/* Iterate over a link list of given type safe against removal of link entry */ +#define LINK_FOR_EACH_ENTRY_SAFE(prObj, prNextObj, prLink, rMember, _TYPE) \ + for (prObj = LINK_ENTRY((prLink)->prNext, _TYPE, rMember), \ + prNextObj = LINK_ENTRY(prObj->rMember.prNext, _TYPE, rMember); \ + &prObj->rMember != (P_LINK_ENTRY_T)(prLink); \ + prObj = prNextObj, \ + prNextObj = LINK_ENTRY(prNextObj->rMember.prNext, _TYPE, rMember)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prNew Pointer of new link head +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID __linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prNew; + prNew->prNext = prNext; + prNew->prPrev = prPrev; + prPrev->prNext = prNew; + +} /* end of __linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry after the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkAdd(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, (P_LINK_ENTRY_T) prLink, prLink->prNext); + +} /* end of linkAdd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will add a new entry before the specified link head. +* +* \param[in] prNew New entry to be added +* \param[in] prHead Specified link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkAddTail(IN P_LINK_ENTRY_T prNew, IN P_LINK_T prLink) +{ + __linkAdd(prNew, prLink->prPrev, (P_LINK_ENTRY_T) prLink); + +} /* end of linkAddTail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is only for internal link list manipulation. +* +* \param[in] prPrev Pointer of previous link head +* \param[in] prNext Pointer of next link head +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID __linkDel(IN P_LINK_ENTRY_T prPrev, IN P_LINK_ENTRY_T prNext) +{ + prNext->prPrev = prPrev; + prPrev->prNext = prNext; + +} /* end of __linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list. +* NOTE: the entry is in an initial state. +* +* \param prEntry Specified link head(entry) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkDel(IN P_LINK_ENTRY_T prEntry) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + + LINK_ENTRY_INITIALIZE(prEntry); + +} /* end of linkDel() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* after the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it after +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkMove(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAdd(prEntry, prLink); + +} /* end of linkMove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will delete a specified entry from link list and then add it +* before the specified link head. +* +* \param[in] prEntry Specified link head(entry) +* \param[in] prOtherHead Another link head to add it before +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID linkMoveTail(IN P_LINK_ENTRY_T prEntry, IN P_LINK_T prLink) +{ + __linkDel(prEntry->prPrev, prEntry->prNext); + linkAddTail(prEntry, prLink); + +} /* end of linkMoveTail() */ + +#endif /* _LINK_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h new file mode 100644 index 0000000000000..fd83c79ffe103 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/aa_fsm.h @@ -0,0 +1,188 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/aa_fsm.h#1 +*/ + +/*! \file aa_fsm.h + \brief Declaration of functions and finite state machine for SAA/AAA Module. + + Declaration of functions and finite state machine for SAA/AAA Module. +*/ + +/* +** Log: aa_fsm.h + * + * 10 13 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS + * 1. short join failure count limit to 2 + * 2. treat join timeout as kind of join failure as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _AA_FSM_H +#define _AA_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Retry interval for retransmiting authentication-request MMPDU. */ +#define TX_AUTHENTICATION_RETRY_TIMEOUT_TU 100 /* TU. */ + +/* Retry interval for retransmiting association-request MMPDU. */ +#define TX_ASSOCIATION_RETRY_TIMEOUT_TU 100 /* TU. */ + +/* Wait for a response to a transmitted authentication-request MMPDU. */ +#define DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ + +/* Wait for a response to a transmitted association-request MMPDU. */ +#define DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU 512 /* TU. */ + +/* The maximum time to wait for JOIN process complete. */ +#define JOIN_FAILURE_TIMEOUT_BEACON_INTERVAL 20 /* Beacon Interval, 20 * 100TU = 2 sec. */ + +/* Retry interval for next JOIN request. */ +#define JOIN_RETRY_INTERVAL_SEC 10 /* Seconds */ + +/* Maximum Retry Count for accept a JOIN request. */ +#define JOIN_MAX_RETRY_FAILURE_COUNT 2 /* Times */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_AA_STATE_T { + AA_STATE_IDLE = 0, + SAA_STATE_SEND_AUTH1, + SAA_STATE_WAIT_AUTH2, + SAA_STATE_SEND_AUTH3, + SAA_STATE_WAIT_AUTH4, + SAA_STATE_SEND_ASSOC1, + SAA_STATE_WAIT_ASSOC2, + AAA_STATE_SEND_AUTH2, + AAA_STATE_SEND_AUTH4, /* We may not use, because P2P GO didn't support WEP and 11r */ + AAA_STATE_SEND_ASSOC2, + AA_STATE_RESOURCE, /* A state for debugging the case of out of msg buffer. */ + AA_STATE_NUM +} ENUM_AA_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in saa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmSteps(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN ENUM_AA_STATE_T eNextState, IN P_SW_RFB_T prRetainedSwRfb); + +WLAN_STATUS +saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, + WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb); + +VOID saaFsmRunEventStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS +saaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID saaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID saaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS saaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID saaFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Routines in aaa_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AA_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h new file mode 100644 index 0000000000000..b771bdacf2c62 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/ais_fsm.h @@ -0,0 +1,573 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/ais_fsm.h#1 +*/ + +/*! \file ais_fsm.h + \brief Declaration of functions and finite state machine for AIS Module. + + Declaration of functions and finite state machine for AIS Module. +*/ + +/* +** Log: ais_fsm.h + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition + * from synchronous to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS + * is in Normal TR state without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 04 25 2011 cp.wu + * [WCXRP00000676] [MT6620 Wi-Fi][Driver] AIS to reduce request channel period from 5 seconds to 2 seconds + * channel interval for joining is shortened to 2 seconds to avoid interruption of concurrent operating network. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 02 22 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with + * a queue-based approach to improve response time for scanning request + * handle SCAN and RECONNECT with a FIFO approach. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 14 2011 cp.wu + * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent + * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. + * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 25 2010 cp.wu + * NULL + * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, RLM/CNM will handle + * the channel switching when BSS information is updated + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 26 2010 cp.wu + * + * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, + * just pend it til 5-sec. period finishes + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 cp.wu + * + * separate AIS-FSM states into different cases of channel request. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Refine AIS-FSM by divided into more states + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, + * other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 23 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * reduce the background ssid idle time min and max value + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * and will send Null frame to diagnose connection + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Support dynamic channel selection + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Media disconnect indication and related postpone functions + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmRunEventJoinComplete() + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Virtual CMD & RESP for testing CMD PATH + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * add aisFsmInitializeConnectionSettings() + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_MGMT_FSM for aisFsmTest() + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function prototype of aisFsmInit() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _AIS_FSM_H +#define _AIS_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ +#define AIS_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ + +#define AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4 2 /* 2.4G scan need about 0.5s, so delay 2s to reconnect is enough */ +#define AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND 5 /* 2.4G scan need about 3.3s, so delay 5s to reconnect is enough */ + +#define AIS_IBSS_ALONE_TIMEOUT_SEC 20 /* seconds */ + +#define AIS_BEACON_TIMEOUT_COUNT_ADHOC 30 +#define AIS_BEACON_TIMEOUT_COUNT_INFRA 10 +#define AIS_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define AIS_BEACON_MAX_TIMEOUT_TU 100 +#define AIS_BEACON_MIN_TIMEOUT_TU 5 +#define AIS_BEACON_MAX_TIMEOUT_VALID TRUE +#define AIS_BEACON_MIN_TIMEOUT_VALID TRUE + +#define AIS_BMC_MAX_TIMEOUT_TU 100 +#define AIS_BMC_MIN_TIMEOUT_TU 5 +#define AIS_BMC_MAX_TIMEOUT_VALID TRUE +#define AIS_BMC_MIN_TIMEOUT_VALID TRUE + +#define AIS_JOIN_CH_GRANT_THRESHOLD 10 +#define AIS_JOIN_CH_REQUEST_INTERVAL 3000 + +#define AIS_SCN_DONE_TIMEOUT_SEC 30 /* 15 for 2.4G + 5G */ /* 5 */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_AIS_STATE_T { + AIS_STATE_IDLE = 0, + AIS_STATE_SEARCH, + AIS_STATE_SCAN, + AIS_STATE_ONLINE_SCAN, + AIS_STATE_LOOKING_FOR, + AIS_STATE_WAIT_FOR_NEXT_SCAN, + AIS_STATE_REQ_CHANNEL_JOIN, + AIS_STATE_JOIN, + AIS_STATE_IBSS_ALONE, + AIS_STATE_IBSS_MERGE, + AIS_STATE_NORMAL_TR, + AIS_STATE_DISCONNECTING, + AIS_STATE_REQ_REMAIN_ON_CHANNEL, + AIS_STATE_REMAIN_ON_CHANNEL, + AIS_STATE_NUM +} ENUM_AIS_STATE_T; + +typedef struct _MSG_AIS_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; +} MSG_AIS_ABORT_T, *P_MSG_AIS_ABORT_T; + +typedef struct _MSG_AIS_IBSS_PEER_FOUND_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + BOOLEAN fgIsMergeIn; /* TRUE: Merge In, FALSE: Merge Out */ + P_STA_RECORD_T prStaRec; +} MSG_AIS_IBSS_PEER_FOUND_T, *P_MSG_AIS_IBSS_PEER_FOUND_T; + +typedef enum _ENUM_AIS_REQUEST_TYPE_T { + AIS_REQUEST_SCAN, + AIS_REQUEST_RECONNECT, + AIS_REQUEST_ROAMING_SEARCH, + AIS_REQUEST_ROAMING_CONNECT, + AIS_REQUEST_REMAIN_ON_CHANNEL, + AIS_REQUEST_NUM +} ENUM_AIS_REQUEST_TYPE_T; + +typedef struct _AIS_REQ_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_AIS_REQUEST_TYPE_T eReqType; +} AIS_REQ_HDR_T, *P_AIS_REQ_HDR_T; + +typedef struct _AIS_REQ_CHNL_INFO { + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} AIS_REQ_CHNL_INFO, *P_AIS_REQ_CHNL_INFO; + +typedef struct _AIS_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} AIS_MGMT_TX_REQ_INFO_T, *P_AIS_MGMT_TX_REQ_INFO_T; + +typedef struct _AIS_FSM_INFO_T { + ENUM_AIS_STATE_T ePreviousState; + ENUM_AIS_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + +#if CFG_SUPPORT_ROAMING + BOOLEAN fgIsRoamingScanPending; +#endif /* CFG_SUPPORT_ROAMING */ + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + P_STA_RECORD_T prTargetStaRec; /* For JOIN Abort */ + + UINT_32 u4SleepInterval; + + TIMER_T rBGScanTimer; + + TIMER_T rIbssAloneTimer; + + TIMER_T rIndicationOfDisconnectTimer; + + TIMER_T rJoinTimeoutTimer; + + TIMER_T rChannelTimeoutTimer; + + TIMER_T rScanDoneTimer; + + TIMER_T rDeauthDoneTimer; + + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfScanReq; + + UINT_32 u4ChGrantedInterval; + + UINT_8 ucConnTrialCount; + + UINT_8 ucScanSSIDLen; + UINT_8 aucScanSSID[ELEM_MAX_LEN_SSID]; + + UINT_32 u4ScanIELength; + UINT_8 aucScanIEBuf[MAX_IE_LENGTH]; + + /* Pending Request List */ + LINK_T rPendingReqList; + + /* Join Request Timestamp */ + OS_SYSTIME rJoinReqTime; + + /* for cfg80211 REMAIN_ON_CHANNEL support */ + AIS_REQ_CHNL_INFO rChReqInfo; + + /* Mgmt tx related. */ + AIS_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Packet filter for AIS module. */ + UINT_32 u4AisPacketFilter; + +} AIS_FSM_INFO_T, *P_AIS_FSM_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define aisChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState = (_eNewMediaState)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +VOID aisFsmInit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication); + +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter); + +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter); +#if 0 +VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState); +#endif +VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Handling for Ad-Hoc Network */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Handling of Incoming Mailbox Message from CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +/*----------------------------------------------------------------------------*/ +/* Generating Outgoing Mailbox Message to CNM */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Event Indication */ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb); + +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter); + +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +/*----------------------------------------------------------------------------*/ +/* Disconnection Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication); + +/*----------------------------------------------------------------------------*/ +/* Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter); + +VOID aisBssSecurityChanged(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_SUPPORT_ROAMING +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan); + +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec); + +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); +#endif /*CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/* Timeout Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength); + +/*----------------------------------------------------------------------------*/ +/* Internal State Checking */ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove); + +P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType); + +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +VOID aisTest(VOID); +#endif /* CFG_TEST_MGMT_FSM */ +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AIS_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h new file mode 100644 index 0000000000000..70b32bca102bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/assoc.h @@ -0,0 +1,112 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/assoc.h#1 +*/ + +/*! \file assoc.h + \brief This file contains the ASSOC REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: assoc.h + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add assocCheckTxReAssocRespFrame() proto type for P2P usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _ASSOC_H +#define _ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in assoc.c */ +/*----------------------------------------------------------------------------*/ +UINT_16 assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode); + +WLAN_STATUS +assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); + +WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ASSOC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h new file mode 100644 index 0000000000000..4f76f03324dde --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/auth.h @@ -0,0 +1,125 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/auth.h#1 +*/ + +/*! \file auth.h + \brief This file contains the authentication REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: auth.h + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _AUTH_H +#define _AUTH_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in auth.c */ +/*----------------------------------------------------------------------------*/ +VOID authAddIEChallengeText(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo); + +#if !CFG_SUPPORT_AAA +WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum); +#else +WLAN_STATUS +authSendAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_SW_RFB_T prFalseAuthSwRfb, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode); +#endif /* CFG_SUPPORT_AAA */ + +WLAN_STATUS authCheckTxAuthFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2TransactionSeqNum); + +WLAN_STATUS authCheckRxAuthFrameTransSeq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +authCheckRxAuthFrameStatus(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_16 u2TransactionSeqNum, OUT PUINT_16 pu2StatusCode); + +VOID authHandleIEChallengeText(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr); + +WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +authSendDeauthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode); + +WLAN_STATUS +authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _AUTH_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h new file mode 100644 index 0000000000000..5995d133a6cdf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bow_fsm.h @@ -0,0 +1,184 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/bow_fsm.h#1 +*/ + +/*! \file bow_fsm.h + \brief Declaration of functions and finite state machine for BOW Module. + + Declaration of functions and finite state machine for BOW Module. +*/ + +/* +** Log: bow_fsm.h + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Submit missing BoW header files. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add channel previledge into _BOW_FSM_INFO_T. + * + * 09 16 2010 chinghwa.yu + * NULL + * update bowChangeMediaState. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + */ + +#ifndef _BOW_FSM_H +#define _BOW_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOW_BG_SCAN_INTERVAL_MIN_SEC 2 /* 30 // exponential to 960 */ +#define BOW_BG_SCAN_INTERVAL_MAX_SEC 2 /* 960 // 16min */ + +#define BOW_DELAY_TIME_OF_DISCONNECT_SEC 10 + +#define BOW_BEACON_TIMEOUT_COUNT_STARTING 10 +#define BOW_BEACON_TIMEOUT_GUARD_TIME_SEC 1 /* Second */ + +#define BOW_BEACON_MAX_TIMEOUT_TU 100 +#define BOW_BEACON_MIN_TIMEOUT_TU 5 +#define BOW_BEACON_MAX_TIMEOUT_VALID TRUE +#define BOW_BEACON_MIN_TIMEOUT_VALID TRUE + +#define BOW_BMC_MAX_TIMEOUT_TU 100 +#define BOW_BMC_MIN_TIMEOUT_TU 5 +#define BOW_BMC_MAX_TIMEOUT_VALID TRUE +#define BOW_BMC_MIN_TIMEOUT_VALID TRUE + +#define BOW_JOIN_CH_GRANT_THRESHOLD 10 +#define BOW_JOIN_CH_REQUEST_INTERVAL 2000 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_BOW_STATE_T { + BOW_STATE_IDLE = 0, + BOW_STATE_SEARCH, + BOW_STATE_SCAN, + BOW_STATE_ONLINE_SCAN, + BOW_STATE_LOOKING_FOR, + BOW_STATE_WAIT_FOR_NEXT_SCAN, + BOW_STATE_REQ_CHANNEL_JOIN, + BOW_STATE_REQ_CHANNEL_ALONE, + BOW_STATE_REQ_CHANNEL_MERGE, + BOW_STATE_JOIN, + BOW_STATE_IBSS_ALONE, + BOW_STATE_IBSS_MERGE, + BOW_STATE_NORMAL_TR, + BOW_STATE_NUM +} ENUM_BOW_STATE_T; + +typedef struct _BOW_FSM_INFO_T { + ENUM_BOW_STATE_T ePreviousState; + ENUM_BOW_STATE_T eCurrentState; + + BOOLEAN fgTryScan; + + /* Channel Privilege */ + + BOOLEAN fgIsInfraChannelFinished; + BOOLEAN fgIsChannelRequested; + BOOLEAN fgIsChannelGranted; + BOOLEAN fgIsScanPending; + UINT_32 u4ChGrantedInterval; + + UINT_8 ucPrimaryChannel; + ENUM_BAND_T eBand; + UINT_16 u2BeaconInterval; + + ENUM_BOW_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + ENUM_BOW_STATE_T eForwardState; /* Step to next state if ACTION frame is TX successfully. */ + + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + P_BSS_DESC_T prTargetBssDesc; /* For destination */ + + UINT_8 aucPeerAddress[6]; + + UINT_8 ucRole; + + BOOLEAN fgSupportQoS; + + BOOLEAN fgIsRsponseProbe; /* Indicate if BOW can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfChReq; + UINT_8 ucSeqNumOfReqMsg; + UINT_8 ucSeqNumOfScnMsg; + UINT_8 ucSeqNumOfScanReq; + + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + + /* Timer */ + TIMER_T rStartingBeaconTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rStartingDiscoveryTimer; + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + TIMER_T rIndicationOfDisconnectTimer; + TIMER_T rChGrantedTimer; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + +} BOW_FSM_INFO_T, *P_BOW_FSM_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define bowChangeMediaState(_prAdapter, _eNewMediaState) \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].eConnectionState = (_eNewMediaState)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h new file mode 100644 index 0000000000000..0597132b970ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/bss.h @@ -0,0 +1,265 @@ +/* +** Id: @(#) bss.h +*/ + +/*! \file "bss.h" + \brief In this file we define the function prototype used in BSS/IBSS. + + The file contains the function declarations and defines for used in BSS/IBSS. +*/ + +/* +** Log: bss.h + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 02 23 2011 eddie.chen + * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap + * Fix parsing WMM INFO and bmp delivery bitmap definition. + * + * 01 31 2011 george.huang + * [WCXRP00000333] [MT5931][FW] support SRAM power control drivers + * Extend TIM PVB, from 2 to 3 octets. + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for + * initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 12 2010 kevin.huang + * NULL + * Update bssProcessProbeRequest() and bssSendBeaconProbeResponse() declarations + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add CTRL FLAGS for Probe Response. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Remove unused typedef. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix file merge error + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * and will send Null frame to diagnose connection + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add DTIM count update while TX Beacon + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +#ifndef _BSS_H +#define _BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* NOTE(Kevin): change define for george */ +/* #define MAX_LEN_TIM_PARTIAL_BMP (((MAX_ASSOC_ID + 1) + 7) / 8) */ /* Required bits = (MAX_ASSOC_ID + 1) */ +#define MAX_LEN_TIM_PARTIAL_BMP ((CFG_STA_REC_NUM + 7) / 8) +/* reserve length greater than maximum size of STA_REC */ /* obsoleted: Assume we only use AID:1~15 */ + +/* CTRL FLAGS for Probe Response */ +#define BSS_PROBE_RESP_USE_P2P_DEV_ADDR BIT(0) +#define BSS_PROBE_RESP_INCLUDE_P2P_IE BIT(1) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define bssAssignAssocID(_prStaRec) ((_prStaRec)->ucIndex + 1) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc); + +VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec); + +VOID +bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP); + +WLAN_STATUS +bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +WLAN_STATUS +bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID +bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr); + +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo); + +WLAN_STATUS +bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags); + +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec); + +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI); + +WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate); + +VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId); + +P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr); + +/*link function to p2p module for txBcnIETable*/ + +/* WMM-2.2.2 WMM ACI to AC coding */ +typedef enum _ENUM_ACI_T { + ACI_BE = 0, + ACI_BK = 1, + ACI_VI = 2, + ACI_VO = 3, + ACI_NUM +} ENUM_ACI_T, *P_ENUM_ACI_T; + +typedef enum _ENUM_AC_PRIORITY_T { + AC_BK_PRIORITY = 0, + AC_BE_PRIORITY, + AC_VI_PRIORITY, + AC_VO_PRIORITY +} ENUM_AC_PRIORITY_T, *P_ENUM_AC_PRIORITY_T; + +#endif /* _BSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h new file mode 100644 index 0000000000000..81b16b5888672 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm.h @@ -0,0 +1,258 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm.h#1 +*/ + +/*! \file "cnm.h" + \brief +*/ + +/* +** Log: cnm.h + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 01 12 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Provide function to decide if BSS can be activated or not + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 13 2010 cm.chang + * + * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Need bandwidth info when requesting channel privilege + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add a new function to send abort message + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support partial part about cmd basic configuration + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add prototype of cnmFsmEventInit() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_H +#define _CNM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _ENUM_CH_REQ_TYPE_T { + CH_REQ_TYPE_JOIN, + CH_REQ_TYPE_P2P_LISTEN, + + CH_REQ_TYPE_NUM +} ENUM_CH_REQ_TYPE_T, *P_ENUM_CH_REQ_TYPE_T; + +typedef struct _MSG_CH_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucBSSID[6]; + UINT_8 aucReserved[2]; +} MSG_CH_REQ_T, *P_MSG_CH_REQ_T; + +typedef struct _MSG_CH_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; +} MSG_CH_ABORT_T, *P_MSG_CH_ABORT_T; + +typedef struct _MSG_CH_GRANT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; + UINT_32 u4GrantInterval; /* In unit of ms */ +} MSG_CH_GRANT_T, *P_MSG_CH_GRANT_T; + +typedef struct _MSG_CH_REOCVER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucPrimaryChannel; + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + ENUM_CH_REQ_TYPE_T eReqType; +} MSG_CH_RECOVER_T, *P_MSG_CH_RECOVER_T; + +typedef struct _CNM_INFO_T { + UINT_32 u4Reserved; +} CNM_INFO_T, *P_CNM_INFO_T; + +#if CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +typedef struct _DEVICE_TYPE_T { + UINT_16 u2CategoryId; /* Category ID */ + UINT_8 aucOui[4]; /* OUI */ + UINT_16 u2SubCategoryId; /* Sub Category ID */ +} __KAL_ATTRIB_PACKED__ DEVICE_TYPE_T, *P_DEVICE_TYPE_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cnmInit(P_ADAPTER_T prAdapter); + +VOID cnmUninit(P_ADAPTER_T prAdapter); + +VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent); + +BOOLEAN +cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO); + +BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); + +VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter); + +BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter); + +BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); +#if CFG_P2P_LEGACY_COEX_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* We don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this to guarantee the same member order in different structures + * to simply handling effort in some functions. + */ +static inline VOID cnmMsgDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, rMsgHdr) == OFFSET_OF(MSG_CH_RECOVER_T, rMsgHdr)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucNetTypeIndex) == + OFFSET_OF(MSG_CH_RECOVER_T, ucNetTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucTokenID) == OFFSET_OF(MSG_CH_RECOVER_T, ucTokenID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, ucPrimaryChannel) == + OFFSET_OF(MSG_CH_RECOVER_T, ucPrimaryChannel)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfSco) == OFFSET_OF(MSG_CH_RECOVER_T, eRfSco)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eRfBand) == OFFSET_OF(MSG_CH_RECOVER_T, eRfBand)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSG_CH_GRANT_T, eReqType) == OFFSET_OF(MSG_CH_RECOVER_T, eReqType)); + +} +#endif /* _lint */ + +#endif /* _CNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h new file mode 100644 index 0000000000000..c8f25b1b29a9f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_mem.h @@ -0,0 +1,1164 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_mem.h#1 +*/ + +/*! \file "cnm_mem.h" + \brief In this file we define the structure of the control unit of + packet buffer and MGT/MSG Memory Buffer. +*/ + +/* +** Log: cnm_mem.h + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 03 17 2011 yuche.tsai + * NULL + * Resize the Secondary Device Type array when WiFi Direct is enabled. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Add per STA flow control when STA is in PS mode + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for + * initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD + * when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 12 2010 cp.wu + * + * SAA will take a record for tracking request sequence number. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error for P2P related defination. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related fields. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [BORA00000678] [MT6620]WiFi LP integration + * 1. add u8TimeStamp in MSDU_INFO + * 2. move fgIsRxTSFUpdated/fgIsTxTSFUpdated from static to BSS_INFO + * 3. add new member for supporting PM in STA_RECORD, which is for AP PS mode + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support checking of duplicated buffer free + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 19 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fixed MAC RX Desc be overwritten issue + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 10 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support Rx header translation for A-MSDU subframe + * + * 05 07 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * add more sanity check about setting timer + * + * 04 29 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * modify the compiling flag for RAM usage + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Modified some MQM-related data structures (SN counter, TX/RX BA table) + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Added new TX/RX BA tables in STA_REC + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 09 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * [BORA00000644] WiFi phase 4 integration + * Added per-TID SN cache in STA_REC + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support power control + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 11 2010 yuche.tsai + * [BORA00000343][MT6620] Emulation For TX + * . + * + * 03 05 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove Emulation definition + * + * 03 04 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * eliminate HIF_EMULATION in cnm_mem.h + * + * 03 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add cnmStaRecChangeState() declaration. + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning for some emulation flags + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, + * and modify the security related callback function prototype. + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * To store field AMPDU Parameters in STA_REC + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsWmmSupported in STA_RECORD_T. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsUapsdSupported in STA_RECORD_T + * + * 02 13 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added arTspecTable in STA_REC for TSPEC management + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable mgmt buffer debug by default + * + * 02 12 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added BUFFER_SOURCE_BCN + * + * 02 10 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Renamed MSDU_INFO.ucFixedRateIndex as MSDU_INFO.ucFixedRateCode + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 02 02 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added SN info in MSDU_INFO_T + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h + * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem + * 3) use cnmMemAlloc() instead to allocate SRAM buffer + * + * 12 31 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) surpress debug message emitted from hal_hif.c + * 2) add two set of field for recording buffer process time + * + * 12 31 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1. move wifi task initialization from wifi_task.c(rom) to wifi_init.c (TCM) for integrating F/W download later + * * * * * 2. WIFI_Event_Dispatcher() prototype changed to return to suspend mode from normal operation mode + * * * * * 2. HIF emulation logic revised + * + * 12 29 2009 yuche.tsai + * [BORA00000343][MT6620] Emulation For TX + * .Using global buffer declaring by SD1 instead of using another one. + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * MQM: BA handling + * * TXM: Macros updates + * * RXM: Macros/Duplicate Removal updates + * + * 12 24 2009 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 23 2009 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * allocating SRAM for emulation purpose by ruducing MEM_BANK3_BUF_SZ + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove individual DATA_BUF_BLOCK_NUM definition for emulation compiling flagsu1rwduu`wvpghlqg|fh+fmdkb + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support several data buffer banks. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * .For new FPGA memory size + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 17 2009 george.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 17 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Modified the DATA_BLOCK_SIZE from 1620 to 2048 + * + * Dec 16 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_SEC_EMULATION flag + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add HT cap to sta record + * + * Dec 9 2009 mtk02752 + * [BORA00000368] Integrate HIF part into BORA + * add cnmDataPktFree() for emulation loopback purpose + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the buffer for key handshake 1x and cmd key order issue + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * move the tx call back function proto type to typedef.h + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add cnmGetStaRecByAddress() and modify variable in STA_RECORD_T + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the port block flag + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add variables to STA_RECORD_T for assoc/auth + * + * Nov 23 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed the value of STA_WAIT_QUEUE_NUM (from 7 to 5) + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed u2FrameLength from SW_RFB + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed indenting + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Updated MSDU_INFO and SW_RFB + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * update the variable for security + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove the variable to make the compiler ok + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the variable for security module + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo in define of MSG_BUF_BLOCK_SIZE + * + * Nov 13 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Let typedef STA_REC_T precede typedef MSDU_INFO_T and SW_RFB_T + * + * Nov 13 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Modified MSDU_INFO and STA_REC for TXM and MQM + * + * Nov 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename STA_REC_T to STA_RECORD_T and add ucIndex member + * + * Nov 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Make sure ucBufferSource the same offset in MSDU_INFO and SW_RFB + * + * Nov 6 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Nov 5 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comment + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add draft content of MSDU_INFO_T and SW_RFB_T + * + * Oct 30 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 21 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_RX_EMULATION flag + * + * Oct 20 2009 mtk01426 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 9 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added field ucTC to MSDU_INFO_T and field pucHifRxPacket to SW_RFB_T + * + * Oct 8 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_MEM_H +#define _CNM_MEM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef POWER_OF_2 +#define POWER_OF_2(n) BIT(n) +#endif + +/* Size of a basic management buffer block in power of 2 */ +#define MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2 7 /* 7 to the power of 2 = 128 */ +#define MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2 5 /* 5 to the power of 2 = 32 */ + +/* Size of a basic management buffer block */ +#define MGT_BUF_BLOCK_SIZE POWER_OF_2(MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCK_SIZE POWER_OF_2(MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Total size of (n) basic management buffer blocks */ +#define MGT_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2) +#define MSG_BUF_BLOCKS_SIZE(n) ((UINT_32)(n) << MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2) + +/* Number of management buffer block */ +#define MAX_NUM_OF_BUF_BLOCKS 32 /* Range: 1~32 */ + +/* Size of overall management frame buffer */ +#define MGT_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MGT_BUF_BLOCK_SIZE) +#define MSG_BUFFER_SIZE (MAX_NUM_OF_BUF_BLOCKS * MSG_BUF_BLOCK_SIZE) + +/* STA_REC related definitions */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE +#define STA_WAIT_QUEUE_NUM 5 /* Number of SW queues in each STA_REC: AC0~AC4 */ +#define SC_CACHE_INDEX_NUM 5 /* Number of SC caches in each STA_REC: AC0~AC4 */ + +/* P2P related definitions */ +#ifdef CFG_ENABLE_WIFI_DIRECT +/* Moved from p2p_fsm.h */ +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if ((MAX_NUM_OF_BUF_BLOCKS > 32) || (MAX_NUM_OF_BUF_BLOCKS <= 0)) +#error > #define MAX_NUM_OF_MGT_BUF_BLOCKS : Out of boundary ! +#elif MAX_NUM_OF_BUF_BLOCKS > 16 +typedef UINT_32 BUF_BITMAP; +#elif MAX_NUM_OF_BUF_BLOCKS > 8 +typedef UINT_16 BUF_BITMAP; +#else +typedef UINT_8 BUF_BITMAP; +#endif /* MAX_NUM_OF_MGT_BUF_BLOCKS */ + +/* Control variable of TX management memory pool */ +typedef struct _BUF_INFO_T { + PUINT_8 pucBuf; + +#if CFG_DBG_MGT_BUF + UINT_32 u4AllocCount; + UINT_32 u4FreeCount; + UINT_32 u4AllocNullCount; +#endif /* CFG_DBG_MGT_BUF */ + + BUF_BITMAP rFreeBlocksBitmap; + UINT_8 aucAllocatedBlockNum[MAX_NUM_OF_BUF_BLOCKS]; +} BUF_INFO_T, *P_BUF_INFO_T; + +/* Wi-Fi divides RAM into three types + * MSG: Mailbox message (Small size) + * BUF: HW DMA buffers (HIF/MAC) + */ +typedef enum _ENUM_RAM_TYPE_T { + RAM_TYPE_MSG = 0, + RAM_TYPE_BUF +} ENUM_RAM_TYPE_T, P_ENUM_RAM_TYPE_T; + +typedef enum _ENUM_BUFFER_SOURCE_T { + BUFFER_SOURCE_HIF_TX0 = 0, + BUFFER_SOURCE_HIF_TX1, + BUFFER_SOURCE_MAC_RX, + BUFFER_SOURCE_MNG, + BUFFER_SOURCE_BCN, + BUFFER_SOURCE_NUM +} ENUM_BUFFER_SOURCE_T, *P_ENUM_BUFFER_SOURCE_T; + +typedef enum _ENUM_SEC_STATE_T { + SEC_STATE_INIT, + SEC_STATE_INITIATOR_PORT_BLOCKED, + SEC_STATE_RESPONDER_PORT_BLOCKED, + SEC_STATE_CHECK_OK, + SEC_STATE_SEND_EAPOL, + SEC_STATE_SEND_DEAUTH, + SEC_STATE_COUNTERMEASURE, + SEC_STATE_NUM +} ENUM_SEC_STATE_T; + +typedef struct _TSPEC_ENTRY_T { + UINT_8 ucStatus; + UINT_8 ucToken; /* Dialog Token in ADDTS_REQ or ADDTS_RSP */ + UINT_16 u2MediumTime; + UINT_32 u4TsInfo; + /* PARAM_QOS_TS_INFO rParamTsInfo; */ + /* Add other retained QoS parameters below */ +} TSPEC_ENTRY_T, *P_TSPEC_ENTRY_T, TSPEC_TABLE_ENTRY_T, *P_TSPEC_TABLE_ENTRY_T; + +typedef struct _SEC_INFO_T { + + ENUM_SEC_STATE_T ePreviousState; + ENUM_SEC_STATE_T eCurrentState; + + BOOLEAN fg2nd1xSend; + BOOLEAN fgKeyStored; + + UINT_8 aucStoredKey[64]; + + BOOLEAN fgAllowOnly1x; +} SEC_INFO_T, *P_SEC_INFO_T; + +#define MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS 3 + +#define UPDATE_BSS_RSSI_INTERVAL_SEC 3 /* Seconds */ + +/* Fragment information structure */ +typedef struct _FRAG_INFO_T { + UINT_16 u2NextFragSeqCtrl; + PUINT_8 pucNextFragStart; + P_SW_RFB_T pr1stFrag; + OS_SYSTIME rReceiveLifetimeLimit; /* The receive time of 1st fragment */ +} FRAG_INFO_T, *P_FRAG_INFO_T; + +typedef struct _STAT_CNT_INFO_FW_T { + UINT32 u4NumOfTx; /* number of packets sent from host */ + UINT32 u4NumOfTxOK; /* number of packets sent to air OK */ + UINT32 u4NumOfTxRetry; /* number of packets sent to air RETRY */ + UINT32 u4TxDoneAirTimeMax; /* maximum tx done air time */ + + UINT32 u4NumOfPtiRspTxOk; /* number of PTI RSP sent to air OK */ + UINT32 u4NumOfPtiRspTxErr; /* number of PTI RSP sent to air ERROR */ + + UINT32 u4NumOfTxErr; /* number of packets sent to air ERROR */ + + UINT32 u4NumOfRx; /* number of received packets */ + UINT32 u4NumOfPtiRspRx; /* number of PTI RSP rcv */ + +#define STAT_CNT_INFO_TX_ERR_FLUSHED 0x00000001 +#define STAT_CNT_INFO_TX_ERR_AGE_TIMEOUT 0x00000002 +#define STAT_CNT_INFO_TX_ERR_MPDU 0x00000004 +#define STAT_CNT_INFO_TX_ERR_RTS 0x00000010 +#define STAT_CNT_INFO_TX_ERR_LIFETIME 0x00000020 +#define STAT_CNT_INFO_TX_ERR_UNKNOWN 0x80000000 + UINT32 u4TxErrBitmap; /* TX error type */ + +#define STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM 10 /* TX OK history */ + UINT8 aucTxRateOkHis[STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM][2]; + UINT32 u4TxRateOkHisId; + +#define STAT_CNT_INFO_MAX_RATE_ID (32) /* MCS0 ~ MCS31 */ + UINT32 aucTxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; + UINT32 aucRxRateMap[STAT_CNT_INFO_MAX_RATE_ID]; + + UINT8 aucStateHis[100][3]; /* State history */ + UINT32 u4StateHisId; /* history ID */ +} STAT_CNT_INFO_FW_T; + +typedef struct _STAT_CNT_INFO_DRV_T { + + UINT32 u4NumOfTxFromOs; /* number of packets sent from OS */ + UINT32 u4NumOfTxQueFull; /* number of packets dropped due to queue full */ + UINT32 u4NumOfTxToFw; /* number of packets sent to firmware */ + + STAT_CNT_INFO_FW_T rFw; +} STAT_CNT_INFO_DRV_T; + +/* Define STA record structure */ +struct _STA_RECORD_T { + LINK_ENTRY_T rLinkEntry; + UINT_8 ucIndex; /* Not modify it except initializing */ + + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; /* MAC address */ + + /* SAA/AAA */ + ENUM_AA_STATE_T eAuthAssocState; /* Store STATE Value used in SAA/AAA */ + UINT_8 ucAuthAssocReqSeqNum; + + ENUM_STA_TYPE_T eStaType; /* Indicate the role of this STA in + * the network (for example, P2P GO) + */ + + UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ + + UINT_8 ucStaState; /* STATE_1,2,3 */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (may deduced from received BSS_DESC_T) + */ + UINT_8 ucDesiredPhyTypeSet; /* The match result by AND operation of peer's + * PhyTypeSet and ours. + */ + BOOLEAN fgHasBasicPhyType; /* A flag to indicate a Basic Phy Type which + * is used to generate some Phy Attribute IE + * (e.g. capability, MIB) during association. + */ + UINT_8 ucNonHTBasicPhyType; /* The Basic Phy Type chosen among the + * ucDesiredPhyTypeSet. + */ + + UINT_16 u2CapInfo; /* For Infra Mode, to store Capability Info. from Association Resp(SAA). + * For AP Mode, to store Capability Info. from Association Req(AAA). + */ + UINT_16 u2AssocId; /* For Infra Mode, to store AID from Association Resp(SAA). + * For AP Mode, to store the Assigned AID(AAA). + */ + + UINT_16 u2ListenInterval; /* Listen Interval from STA(AAA) */ + + UINT_16 u2DesiredNonHTRateSet; /* Our Current Desired Rate Set after + * match with STA's Operational Rate Set + */ + + UINT_16 u2OperationalRateSet; /* Operational Rate Set of peer BSS */ + UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of peer BSS */ + + BOOLEAN fgIsMerging; /* For IBSS Mode, to indicate that Merge is ongoing */ + + BOOLEAN fgDiagnoseConnection; /* For Infra/AP Mode, to diagnose the Connection with + * this peer by sending ProbeReq/Null frame */ + + /*------------------------------------------------------------------------------------------*/ + /* 802.11n HT capabilities when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) is true */ + /* They have the same definition with fields of information element */ + /*------------------------------------------------------------------------------------------*/ + UINT_8 ucMcsSet; /* MCS0~7 rate set of peer BSS */ + BOOLEAN fgSupMcs32; /* MCS32 is supported by peer BSS */ + UINT_16 u2HtCapInfo; /* HT cap info field by HT cap IE */ + UINT_8 ucAmpduParam; /* Field A-MPDU Parameters in HT cap IE */ + UINT_16 u2HtExtendedCap; /* HT extended cap field by HT cap IE */ + UINT_32 u4TxBeamformingCap; /* TX beamforming cap field by HT cap IE */ + UINT_8 ucAselCap; /* ASEL cap field by HT cap IE */ + + UINT_8 ucRCPI; /* RCPI of peer */ + + UINT_8 ucDTIMPeriod; /* Target BSS's DTIM Period, we use this + * value for setup Listen Interval + * TODO(Kevin): TBD + */ + UINT_8 ucAuthAlgNum; /* For Infra/AP Mode, the Auth Algorithm Num used in Authentication(SAA/AAA) */ + BOOLEAN fgIsReAssoc; /* For Infra/AP Mode, to indicate ReAssoc Frame was in used(SAA/AAA) */ + + UINT_8 ucTxAuthAssocRetryCount; /* For Infra Mode, the Retry Count of TX Auth/Assod Frame(SAA) */ + UINT_8 ucTxAuthAssocRetryLimit; /* For Infra Mode, the Retry Limit of TX Auth/Assod Frame(SAA) */ + + UINT_16 u2StatusCode; /* Status of Auth/Assoc Req */ + UINT_16 u2ReasonCode; /* Reason that been Deauth/Disassoc */ + + P_IE_CHALLENGE_TEXT_T prChallengeText; /* Point to an allocated buffer for storing Challenge Text + * for Shared Key Authentication + */ + + TIMER_T rTxReqDoneOrRxRespTimer; /* For Infra Mode, a timer used to send a timeout event + * while waiting for TX request done or RX response. + */ + + /*------------------------------------------------------------------------------------------*/ + /* Power Management related fields (for STA/ AP/ P2P/ BOW power saving mode) */ + /*------------------------------------------------------------------------------------------*/ + BOOLEAN fgSetPwrMgtBit; /* For Infra Mode, to indicate that outgoing frame need toggle + * the Pwr Mgt Bit in its Frame Control Field. + */ + + BOOLEAN fgIsInPS; /* For AP Mode, to indicate the client PS state(PM). + * TRUE: In PS Mode; FALSE: In Active Mode. */ + + BOOLEAN fgIsInPsPollSP; /* For Infra Mode, to indicate we've sent a PS POLL to AP and start + * the PS_POLL Service Period(LP) + */ + + BOOLEAN fgIsInTriggerSP; /* For Infra Mode, to indicate we've sent a Trigger Frame to AP and start + * the Delivery Service Period(LP) + */ + + UINT_8 ucBmpDeliveryAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + UINT_8 ucBmpTriggerAC; /* 0: AC0, 1: AC1, 2: AC2, 3: AC3 */ + + UINT_8 ucUapsdSp; /* Max SP length */ + + /*------------------------------------------------------------------------------------------*/ + + BOOLEAN fgIsRtsEnabled; + + OS_SYSTIME rUpdateTime; /* (4) System Timestamp of Successful TX and RX */ + + OS_SYSTIME rLastJoinTime; /* (4) System Timestamp of latest JOIN process */ + + UINT_8 ucJoinFailureCount; /* Retry Count of JOIN process */ + + LINK_T arStaWaitQueue[STA_WAIT_QUEUE_NUM]; /* For TXM to defer pkt forwarding to MAC TX DMA */ + + UINT_16 au2CachedSeqCtrl[TID_NUM + 1]; /* Duplicate removal for HT STA on a per-TID basis + * ("+1" is for MMPDU and non-QoS) + */ + +#if 0 + /* RXM */ + P_RX_BA_ENTRY_T aprRxBaTable[TID_NUM]; + + /* TXM */ + P_TX_BA_ENTRY_T aprTxBaTable[TID_NUM]; +#endif + + FRAG_INFO_T rFragInfo[MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS]; + + SEC_INFO_T rSecInfo; /* The security state machine */ + + BOOLEAN fgPortBlock; /* The 802.1x Port Control flag */ + + BOOLEAN fgTransmitKeyExist; /* Unicast key exist for this STA */ + + UINT_8 ucWTEntry; + + BOOLEAN fgTxAmpduEn; /* Enable TX AMPDU for this Peer */ + BOOLEAN fgRxAmpduEn; /* Enable RX AMPDU for this Peer */ + + PUINT_8 pucAssocReqIe; + UINT_16 u2AssocReqIeLen; + /*------------------------------------------------------------------------------------------*/ + /* WMM/QoS related fields */ + /*------------------------------------------------------------------------------------------*/ + BOOLEAN fgIsQoS; /* If the STA is associated as a QSTA or QAP (for TX/RX) */ + BOOLEAN fgIsWmmSupported; /* If the peer supports WMM, set to TRUE (for association) */ + BOOLEAN fgIsUapsdSupported; /* Set according to the scan result (for association) */ + + /*------------------------------------------------------------------------------------------*/ + /* P2P related fields */ + /*------------------------------------------------------------------------------------------*/ +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 u2DevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + + UINT_16 u2ConfigMethods; + + UINT_8 ucDeviceCap; + + UINT_8 ucSecondaryDevTypeCount; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT]; +#endif /* CFG_SUPPORT_P2P */ + + /*------------------------------------------------------------------------------------------*/ + /* QM related fields */ + /*------------------------------------------------------------------------------------------*/ + + UINT_8 ucFreeQuota; /* Per Sta flow controal. Valid when fgIsInPS is TRUE. + Change it for per Queue flow control */ + /* UINT_8 aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES]; */ /* used in future */ + UINT_8 ucFreeQuotaForDelivery; + UINT_8 ucFreeQuotaForNonDelivery; +#if CFG_ENABLE_PKT_LIFETIME_PROFILE && CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4TotalTxPktsNumber; + UINT_32 u4TotalTxPktsTime; + UINT_32 u4TotalTxPktsHifTime; + + UINT_32 u4MaxTxPktsTime; + UINT_32 u4MaxTxPktsHifTime; + + UINT_32 u4ThresholdCounter; + UINT_32 u4EnqeueuCounter; + UINT_32 u4DeqeueuCounter; + UINT_32 u4PrevIntCount; + UINT_32 u4ThisIntCount; + UINT_32 u4NoTcResource; +#endif + +#if 1 + /*------------------------------------------------------------------------------------------*/ + /* To be removed, this is to make que_mgt compilation success only */ + /*------------------------------------------------------------------------------------------*/ + /* When this STA_REC is in use, set to TRUE. */ + BOOLEAN fgIsValid; + + /* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ + QUE_T arTxQueue[NUM_OF_PER_STA_TX_QUEUES]; + + /* When this STA is in PS Mode, set to TRUE. */ + /* BOOLEAN fgIsPS; */ + + /* When this STA enters Power-Saving, FW will notify the driver with a Session ID */ + UINT_8 ucPsSessionID; + + BOOLEAN fgIsAp; + + /* Reorder Parameter reference table */ + P_RX_BA_ENTRY_T aprRxReorderParamRefTbl[CFG_RX_MAX_BA_TID_NUM]; +#endif + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + TIMINGMSMT_PARAM_T rWNMTimingMsmt; +#endif + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ + + BOOLEAN flgTdlsIsInitiator; /* TRUE: the peer is the initiator */ + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + BOOLEAN fgTdlsInSecurityMode; /* TRUE: security mode */ + PARAM_KEY_T rTdlsKeyTemp; /* temp to queue the key information */ + +#define TDLS_SETUP_TIMEOUT_SEC 5 /* unit: second */ + OS_SYSTIME rTdlsSetupStartTime; /* time when link setup is started */ + + OS_SYSTIME rTdlsTxQuotaEmptyTime; /* time when TX quota is 0 */ + + STAT_CNT_INFO_DRV_T rTdlsStatistics; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_STATISTICS == 1) +#define STATS_ENV_TIMEOUT_SEC 10 /* unit: second */ + OS_SYSTIME rStatsEnvTxPeriodLastTime; + +#define STATS_ENV_TX_CNT_REPORT_TRIGGER 2500 /* 6Mbps */ +#define STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC 5 /* unit: second */ + OS_SYSTIME rStatsEnvTxLastTime; + UINT32 u4StatsEnvTxCnt; + + UINT32 u4NumOfNoTxQuota; + + UINT32 u4RxReorderFallAheadCnt; + UINT32 u4RxReorderFallBehindCnt; + UINT32 u4RxReorderHoleCnt; + UINT32 u4RxReorderHoleTimeoutCnt; + + UINT32 u4StatsRxPassToOsCnt; + + /* delay from HIF to pass to OS: us */ +#define STATS_STAY_INT_BYTE_THRESHOLD 500 + UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; + + UINT8 ucStatsGenDisplayCnt; +#endif /* CFG_SUPPORT_STATISTICS */ +}; + +#if 0 +/* use nic_tx.h instead */ +/* MSDU_INFO and SW_RFB structure */ +typedef struct _MSDU_INFO_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + /* TODO: move flags to ucControlFlag */ + + BOOLEAN fgIs1xFrame; /* Set to TRUE for 802.1x frame */ + + /* TXM: For TX Done handling, callback function & parameter (5) */ + BOOLEAN fgIsTxFailed; /* Set to TRUE if transmission failure */ + + PFN_TX_DONE_HANDLER pfTxDoneHandler; + + UINT_64 u8TimeStamp; /* record the TX timestamp */ + + /* TXM: For PS forwarding control (per-STA flow control) */ + UINT_8 ucPsForwardingType; /* Delivery-enabled, non-delivery-enabled, non-PS */ + UINT_8 ucPsSessionID; /* The Power Save session id for PS forwarding control */ + + /* TXM: For MAC TX DMA operations */ + UINT_8 ucMacTxQueIdx; /* MAC TX queue: AC0-AC6, BCM, or BCN */ + BOOLEAN fgNoAck; /* Set to true if Ack is not required for this packet */ + BOOLEAN fgBIP; /* Set to true if BIP is used for this packet */ + UINT_8 ucFragTotalCount; + UINT_8 ucFragFinishedCount; + UINT_16 u2FragThreshold; /* Fragmentation threshold without WLAN Header & FCS */ + BOOLEAN fgFixedRate; /* If a fixed rate is used, set to TRUE. */ + UINT_8 ucFixedRateCode; /* The rate code copied to MAC TX Desc */ + UINT_8 ucFixedRateRetryLimit; /* The retry limit when a fixed rate is used */ + BOOLEAN fgIsBmcQueueEnd; /* Set to true if this packet is the end of BMC */ + + /* TXM: For flushing ACL frames */ + UINT_16 u2PalLLH; /* 802.11 PAL LLH */ + /* UINT_16 u2LLH; */ + UINT_16 u2ACLSeq; /* u2LLH+u2ACLSeq for AM HCI flush ACL frame */ + + /* TXM for retransmitting a flushed packet */ + BOOLEAN fgIsSnAssigned; + UINT_16 u2SequenceNumber; /* To remember the Sequence Control field of this MPDU */ + +} MSDU_INFO_T, *P_MSDU_INFO_T; +#endif + +#if 0 +/* nic_rx.h */ +typedef struct _SW_RFB_T { + + /* 4 ----------------MSDU_INFO and SW_RFB Common Fields------------------ */ + + LINK_ENTRY_T rLinkEntry; + PUINT_8 pucBuffer; /* Pointer to the associated buffer */ + + UINT_8 ucBufferSource; /* HIF TX0, HIF TX1, MAC RX, or MNG Pool */ + UINT_8 ucNetworkTypeIndex; /* Network type index that this TX packet is assocaited with */ + UINT_8 ucTC; /* 0 to 5 (used by HIF TX to increment the corresponding TC counter) */ + UINT_8 ucTID; /* Traffic Identification */ + + BOOLEAN fgIs802_11Frame; /* Set to TRUE for 802.11 frame */ + UINT_8 ucMacHeaderLength; + UINT_16 u2PayloadLength; + PUINT_8 pucMacHeader; /* 802.11 header */ + PUINT_8 pucPayload; /* 802.11 payload */ + + OS_SYSTIME rArrivalTime; /* System Timestamp (4) */ + P_STA_RECORD_T prStaRec; + +#if CFG_PROFILE_BUFFER_TRACING + ENUM_BUFFER_ACTIVITY_TYPE_T eActivity[2]; + UINT_32 rActivityTime[2]; +#endif +#if DBG && CFG_BUFFER_FREE_CHK + BOOLEAN fgBufferInSource; +#endif + + UINT_8 ucControlFlag; /* For specify some Control Flags, e.g. Basic Rate */ + + /* 4 -----------------------Non-Common ------------------------- */ + + /* For composing the HIF RX Header (TODO: move flags to ucControlFlag) */ + PUINT_8 pucHifRxPacket; /* Pointer to the Response packet to HIF RX0 or RX1 */ + UINT_16 u2HifRxPacketLength; + UINT_8 ucHeaderOffset; + UINT_8 ucHifRxPortIndex; + + UINT_16 u2SequenceControl; + BOOLEAN fgIsA4Frame; /* (For MAC RX packet parsing) set to TRUE if 4 addresses are present */ + BOOLEAN fgIsBAR; + BOOLEAN fgIsQoSData; + BOOLEAN fgIsAmsduSubframe; /* Set to TRUE for A-MSDU Subframe */ + + /* For HIF RX DMA Desc */ + BOOLEAN fgTUChecksumCheckRequired; + BOOLEAN fgIPChecksumCheckRequired; + UINT_8 ucEtherTypeOffset; + +} SW_RFB_T, *P_SW_RFB_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_MSDU_INFO_T cnmMgtPktAlloc(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cnmMgtPktFree(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID cnmMemInit(IN P_ADAPTER_T prAdapter); + +PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length); + +VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory); + +VOID cnmStaRecInit(IN P_ADAPTER_T prAdapter); + +VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter); + +P_STA_RECORD_T cnmStaRecAlloc(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex); + +VOID cnmStaRecFree(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSyncToChip); + +VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip); + +P_STA_RECORD_T cnmGetStaRecByIndex(IN P_ADAPTER_T prAdapter, IN UINT_8 ucIndex); + +P_STA_RECORD_T cnmGetStaRecByAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIndex, IN UINT_8 aucPeerMACAddress[]); + +VOID cnmStaRecResetStatus(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +VOID cnmStaRecChangeState(IN P_ADAPTER_T prAdapter, IN OUT P_STA_RECORD_T prStaRec, IN UINT_8 ucNewState); + +P_STA_RECORD_T +cnmStaTheTypeGet(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID cnmMemDataTypeCheck(VOID) +{ +#if 0 + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == 0); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rLinkEntry) == OFFSET_OF(SW_RFB_T, rLinkEntry)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucBuffer) == OFFSET_OF(SW_RFB_T, pucBuffer)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucBufferSource) == OFFSET_OF(SW_RFB_T, ucBufferSource)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucMacHeader) == OFFSET_OF(SW_RFB_T, pucMacHeader)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucMacHeaderLength) == + OFFSET_OF(SW_RFB_T, ucMacHeaderLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, pucPayload) == OFFSET_OF(SW_RFB_T, pucPayload)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, u2PayloadLength) == OFFSET_OF(SW_RFB_T, u2PayloadLength)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, prStaRec) == OFFSET_OF(SW_RFB_T, prStaRec)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucNetworkTypeIndex) == + OFFSET_OF(SW_RFB_T, ucNetworkTypeIndex)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTID) == OFFSET_OF(SW_RFB_T, ucTID)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgIs802_11Frame) == OFFSET_OF(SW_RFB_T, fgIs802_11Frame)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucControlFlag) == OFFSET_OF(SW_RFB_T, ucControlFlag)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rArrivalTime) == OFFSET_OF(SW_RFB_T, rArrivalTime)); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, ucTC) == OFFSET_OF(SW_RFB_T, ucTC)); + +#if CFG_PROFILE_BUFFER_TRACING + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, eActivity[0]) == OFFSET_OF(SW_RFB_T, eActivity[0])); + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, rActivityTime[0]) == + OFFSET_OF(SW_RFB_T, rActivityTime[0])); +#endif + +#if DBG && CFG_BUFFER_FREE_CHK + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(MSDU_INFO_T, fgBufferInSource) == + OFFSET_OF(SW_RFB_T, fgBufferInSource)); +#endif + + DATA_STRUCT_INSPECTING_ASSERT(OFFSET_OF(STA_RECORD_T, rLinkEntry) == 0); + + return; +#endif +} +#endif /* _lint */ + +#endif /* _CNM_MEM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h new file mode 100644 index 0000000000000..cc5d0fa1adfca --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_scan.h @@ -0,0 +1,169 @@ +/* +** Id: @(#) +*/ + +/*! \file "cnm_scan.h" + \brief + +*/ + +/* +** Log: cnm_scan.h + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * remove unused definitions. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function prototype of cnmScanInit() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_SCAN_H +#define _CNM_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define SCN_CHANNEL_DWELL_TIME_MIN_MSEC 12 +#define SCN_CHANNEL_DWELL_TIME_EXT_MSEC 98 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_FULL 3 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_FULL 1 + +#define SCN_TOTAL_PROBEREQ_NUM_FOR_PARTIAL 2 +#define SCN_SPECIFIC_PROBEREQ_NUM_FOR_PARTIAL 1 + +#define SCN_INTERLACED_CHANNEL_GROUPS_NUM 3 /* Used by partial scan */ + +#define SCN_PARTIAL_SCAN_NUM 3 + +#define SCN_PARTIAL_SCAN_IDLE_MSEC 100 + +#define MAXIMUM_OPERATION_CHANNEL_LIST 46 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* The type of Scan Source */ +typedef enum _ENUM_SCN_REQ_SOURCE_T { + SCN_REQ_SOURCE_HEM = 0, + SCN_REQ_SOURCE_NET_FSM, + SCN_REQ_SOURCE_ROAMING, /* ROAMING Module is independent of AIS FSM */ + SCN_REQ_SOURCE_OBSS, /* 2.4G OBSS scan */ + SCN_REQ_SOURCE_NUM +} ENUM_SCN_REQ_SOURCE_T, *P_ENUM_SCN_REQ_SOURCE_T; + +typedef enum _ENUM_SCAN_PROFILE_T { + SCAN_PROFILE_FULL = 0, + SCAN_PROFILE_PARTIAL, + SCAN_PROFILE_VOIP, + SCAN_PROFILE_FULL_2G4, + SCAN_PROFILE_NUM +} ENUM_SCAN_PROFILE_T, *P_ENUM_SCAN_PROFILE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +VOID cnmScanInit(VOID); + +VOID cnmScanRunEventScanRequest(IN P_MSG_HDR_T prMsgHdr); + +BOOLEAN cnmScanRunEventScanAbort(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanProfileSelection(VOID); + +VOID cnmScanProcessStart(VOID); + +VOID cnmScanProcessStop(VOID); + +VOID cnmScanRunEventReqAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanRunEventCancelAISAbsDone(IN P_MSG_HDR_T prMsgHdr); + +VOID cnmScanPartialScanTimeout(UINT_32 u4Param); + +VOID cnmScanRunEventScnFsmComplete(IN P_MSG_HDR_T prMsgHdr); +#endif + +#endif /* _CNM_SCAN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h new file mode 100644 index 0000000000000..a2ed9cd02fedf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/cnm_timer.h @@ -0,0 +1,235 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/cnm_timer.h#1 +*/ + +/*! \file cnm_timer.h + \brief Declaration of timer obj and related timer macro for setup time out + event. + + In this file we declare the timer object and provide several macro for + Protocol functional blocks to setup their own time out event. +*/ + +/* +** Log: cnm_timer.h + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Return timer token back to COS when entering wait off state + * + * 01 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb + * + * 01 06 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix system time is 32KHz instead of 1ms + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * add the copy time function + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix LINT warnning + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +#ifndef _CNM_TIMER_H +#define _CNM_TIMER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#undef MSEC_PER_SEC +#define MSEC_PER_SEC 1000 +#undef USEC_PER_MSEC +#define USEC_PER_MSEC 1000 +#define USEC_PER_TU 1024 /* microsecond */ + +#define MSEC_PER_MIN (60 * MSEC_PER_SEC) + +#define MGMT_MAX_TIMEOUT_INTERVAL ((UINT_32)0x7fffffff) + +#define WAKE_LOCK_MAX_TIME 5 /* Unit: sec */ + +/* If WAKE_LOCK_MAX_TIME is too large, the whole system may always keep awake + * because of periodic timer of OBSS scanning + */ +#if (WAKE_LOCK_MAX_TIME >= OBSS_SCAN_MIN_INTERVAL) +#error WAKE_LOCK_MAX_TIME is too large +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef VOID(*PFN_MGMT_TIMEOUT_FUNC) (P_ADAPTER_T, ULONG); + +typedef struct _TIMER_T { + LINK_ENTRY_T rLinkEntry; + OS_SYSTIME rExpiredSysTime; + UINT_16 u2Minutes; + UINT_16 u2Reserved; + ULONG ulData; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; +} TIMER_T, *P_TIMER_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Check if time "a" is before time "b" */ +/* In 32-bit variable, 0x00000001~0x7fffffff -> positive number, + * 0x80000000~0xffffffff -> negative number + */ +#define TIME_BEFORE_64bit(a, b) (a < b) + +#define TIME_BEFORE(a, b) ((UINT_32)((UINT_32)(a) - (UINT_32)(b)) > 0x7fffffff) + +/* #define TIME_BEFORE(a,b) ((INT_32)((INT_32)(b) - (INT_32)(a)) > 0) + * may cause UNexpect result between Free build and Check build for WinCE + */ + +#define TIME_AFTER(a, b) TIME_BEFORE(b, a) + +#define SYSTIME_TO_SEC(_systime) ((_systime) / KAL_HZ) +#define SEC_TO_SYSTIME(_sec) ((_sec) * KAL_HZ) + +/* The macros to convert second & millisecond */ +#define MSEC_TO_SEC(_msec) ((_msec) / MSEC_PER_SEC) +#define SEC_TO_MSEC(_sec) ((UINT_32)(_sec) * MSEC_PER_SEC) + +/* The macros to convert millisecond & microsecond */ +#define USEC_TO_MSEC(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_USEC(_msec) ((UINT_32)(_msec) * USEC_PER_MSEC) + +/* The macros to convert TU & microsecond, TU & millisecond */ +#define TU_TO_USEC(_tu) ((_tu) * USEC_PER_TU) +#define TU_TO_MSEC(_tu) USEC_TO_MSEC(TU_TO_USEC(_tu)) + +/* The macros to convert TU & & OS system time, round up by 0.5 */ +#define TU_TO_SYSTIME(_tu) MSEC_TO_SYSTIME(TU_TO_MSEC(_tu)) +#define SYSTIME_TO_TU(_systime) \ + ((SYSTIME_TO_USEC(_systime) + ((USEC_PER_TU / 2) - 1)) / USEC_PER_TU) + +/* The macros to convert OS system time & microsecond */ +#define SYSTIME_TO_USEC(_systime) (SYSTIME_TO_MSEC(_systime) * USEC_PER_MSEC) + +/* The macro to get the current OS system time */ +#define GET_CURRENT_SYSTIME(_systime_p) {*(_systime_p) = kalGetTimeTick(); } + +/* The macro to copy the system time */ +#define COPY_SYSTIME(_destTime, _srcTime) {(_destTime) = (_srcTime); } + +/* The macro to get the system time difference between t1 and t2 (t1 - t2) */ +/* #define GET_SYSTIME_DIFFERENCE(_time1, _time2, _diffTime) \ + (_diffTime) = (_time1) - (_time2) */ + +/* The macro to check for the expiration, if TRUE means _currentTime >= _expirationTime */ +#define CHECK_FOR_EXPIRATION(_currentTime, _expirationTime) \ + (((UINT_32)(_currentTime) - (UINT_32)(_expirationTime)) <= 0x7fffffffUL) + +/* The macro to check for the timeout */ +#define CHECK_FOR_TIMEOUT(_currentTime, _timeoutStartingTime, _timeout) \ + CHECK_FOR_EXPIRATION((_currentTime), ((_timeoutStartingTime) + (_timeout))) + +/* The macro to set the expiration time with a specified timeout *//* Watch out for round up. */ +#define SET_EXPIRATION_TIME(_expirationTime, _timeout) \ + { \ + GET_CURRENT_SYSTIME(&(_expirationTime)); \ + (_expirationTime) += (OS_SYSTIME)(_timeout); \ + } + +#define timerRenewTimer(adapter, tmr, interval) \ + timerStartTimer(adapter, tmr, interval, (tmr)->function, (tmr)->data) + +#define MGMT_INIT_TIMER(_adapter_p, _timer, _callbackFunc) \ + timerInitTimer(_adapter_p, &(_timer), (ULONG)(_callbackFunc)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter); + +VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter); + +VOID +cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData); + +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer); + +VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs); + +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +static inline INT_32 timerPendingTimer(IN P_TIMER_T prTimer) +{ + ASSERT(prTimer); + + return prTimer->rLinkEntry.prNext != NULL; +} + +#endif /* _CNM_TIMER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h new file mode 100644 index 0000000000000..868de4a6c40ac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hem_mbox.h @@ -0,0 +1,446 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/hem_mbox.h#2 +*/ + +/*! \file hem_mbox.h + \brief + +*/ + +/* +** Log: hem_mbox.h +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for + * more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID + * support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 07 2011 yuche.tsai + * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response. + * cnm_timer[WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add invitation support. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 09 16 2010 cm.chang + * NULL + * Remove unused message ID + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some message ID for P2P FSM under provisioning phase. + * + * 08 11 2010 yuche.tsai + * NULL + * Add Message Event ID for P2P Module. + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 04 2010 cp.wu + * NULL + * remove unused mailbox message definitions. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * message table should not be commented out by compilation option without modifying header file + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_QOS_ACTION_FRAME + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_BA_ACTION_FRAME + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Develop partial DPD code + * + * 02 11 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added MID_RXM_MQM_QOS_ACTION_FRAME for RXM to indicate QoS Action frames to MQM + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename the parameter of mboxDummy() + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added MID_RXM_MQM_BA_ACTION_FRAME + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove Dummy MSG ID + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add JOIN REQ related MSG ID + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add AIS ABORT MSG ID + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add SCN MSG IDs + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _HEM_MBOX_H +#define _HEM_MBOX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Message IDs */ +typedef enum _ENUM_MSG_ID_T { + MID_MNY_CNM_CH_REQ, /* MANY notify CNM to obtain channel privilege */ + MID_MNY_CNM_CH_ABORT, /* MANY notify CNM to abort/release channel privilege */ + + MID_CNM_AIS_CH_GRANT, /* CNM notify AIS for indicating channel granted */ + MID_CNM_P2P_CH_GRANT, /* CNM notify P2P for indicating channel granted */ + MID_CNM_BOW_CH_GRANT, /* CNM notify BOW for indicating channel granted */ + + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_AIS_SCN_SCAN_REQ, /* AIS notify SCN for starting scan */ + MID_AIS_SCN_SCAN_REQ_V2, /* AIS notify SCN for starting scan with multiple SSID support */ + MID_AIS_SCN_SCAN_CANCEL, /* AIS notify SCN for cancelling scan */ + MID_P2P_SCN_SCAN_REQ, /* P2P notify SCN for starting scan */ + MID_P2P_SCN_SCAN_REQ_V2, /* P2P notify SCN for starting scan with multiple SSID support */ + MID_P2P_SCN_SCAN_CANCEL, /* P2P notify SCN for cancelling scan */ + MID_BOW_SCN_SCAN_REQ, /* BOW notify SCN for starting scan */ + MID_BOW_SCN_SCAN_REQ_V2, /* BOW notify SCN for starting scan with multiple SSID support */ + MID_BOW_SCN_SCAN_CANCEL, /* BOW notify SCN for cancelling scan */ + MID_RLM_SCN_SCAN_REQ, /* RLM notify SCN for starting scan (OBSS-SCAN) */ + MID_RLM_SCN_SCAN_REQ_V2, /* RLM notify SCN for starting scan (OBSS-SCAN) with multiple SSID support */ + MID_RLM_SCN_SCAN_CANCEL, /* RLM notify SCN for cancelling scan (OBSS-SCAN) */ + MID_SCN_AIS_SCAN_DONE, /* SCN notify AIS for scan completion */ + MID_SCN_P2P_SCAN_DONE, /* SCN notify P2P for scan completion */ + MID_SCN_BOW_SCAN_DONE, /* SCN notify BOW for scan completion */ + MID_SCN_RLM_SCAN_DONE, /* SCN notify RLM for scan completion (OBSS-SCAN) */ + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_OID_AIS_FSM_JOIN_REQ, /* OID/IOCTL notify AIS for join */ + MID_OID_AIS_FSM_ABORT, /* OID/IOCTL notify AIS for abort */ + MID_AIS_SAA_FSM_START, /* AIS notify SAA for Starting authentication/association fsm */ + MID_AIS_SAA_FSM_ABORT, /* AIS notify SAA for Aborting authentication/association fsm */ + MID_SAA_AIS_JOIN_COMPLETE, /* SAA notify AIS for indicating join complete */ + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_BOW_SAA_FSM_START, /* BOW notify SAA for Starting authentication/association fsm */ + MID_BOW_SAA_FSM_ABORT, /* BOW notify SAA for Aborting authentication/association fsm */ + MID_SAA_BOW_JOIN_COMPLETE, /* SAA notify BOW for indicating join complete */ +#endif + +#if CFG_ENABLE_WIFI_DIRECT + /*--------------------------------------------------*/ + /* P2P Module Mailbox Messages */ + /*--------------------------------------------------*/ + MID_P2P_SAA_FSM_START, /* P2P notify SAA for Starting authentication/association fsm */ + MID_P2P_SAA_FSM_ABORT, /* P2P notify SAA for Aborting authentication/association fsm */ + MID_SAA_P2P_JOIN_COMPLETE, /* SAA notify P2P for indicating join complete */ + + MID_MNY_P2P_FUN_SWITCH, /* Enable P2P FSM. */ + MID_MNY_P2P_DEVICE_DISCOVERY, /* Start device discovery. */ + MID_MNY_P2P_CONNECTION_REQ, /* Connection request. */ + MID_MNY_P2P_CONNECTION_ABORT, /* Abort connection request, P2P FSM return to IDLE. */ + MID_MNY_P2P_BEACON_UPDATE, + MID_MNY_P2P_STOP_AP, + MID_MNY_P2P_CHNL_REQ, + MID_MNY_P2P_CHNL_ABORT, + MID_MNY_P2P_MGMT_TX, + MID_MNY_P2P_GROUP_DISSOLVE, + MID_MNY_P2P_MGMT_FRAME_REGISTER, + MID_MNY_P2P_NET_DEV_REGISTER, + MID_MNY_P2P_START_AP, + MID_MNY_P2P_MGMT_FRAME_UPDATE, + MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, +#if CFG_SUPPORT_WFD + MID_MNY_P2P_WFD_CFG_UPDATE, +#endif +#endif + +#if CFG_SUPPORT_ADHOC + MID_SCN_AIS_FOUND_IBSS, /* SCN notify AIS that an IBSS Peer has been found and can merge into */ +#endif /* CFG_SUPPORT_ADHOC */ + + MID_SAA_AIS_FSM_ABORT, /* SAA notify AIS for indicating deauthentication/disassociation */ + + /*--------------------------------------------------*/ + /* AIS MGMT-TX Support */ + /*--------------------------------------------------*/ + MID_MNY_AIS_REMAIN_ON_CHANNEL, + MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, + MID_MNY_AIS_MGMT_TX, + + MID_TOTAL_NUM +} ENUM_MSG_ID_T, *P_ENUM_MSG_ID_T; + +/* Message header of inter-components */ +struct _MSG_HDR_T { + LINK_ENTRY_T rLinkEntry; + ENUM_MSG_ID_T eMsgId; +}; + +typedef VOID(*PFN_MSG_HNDL_FUNC) (P_ADAPTER_T, P_MSG_HDR_T); + +typedef struct _MSG_HNDL_ENTRY { + ENUM_MSG_ID_T eMsgId; + PFN_MSG_HNDL_FUNC pfMsgHndl; +} MSG_HNDL_ENTRY_T, *P_MSG_HNDL_ENTRY_T; + +typedef enum _EUNM_MSG_SEND_METHOD_T { + MSG_SEND_METHOD_BUF = 0, /* Message is put in the queue and will be + executed when mailbox is checked. */ + MSG_SEND_METHOD_UNBUF /* The handler function is called immediately + in the same context of the sender */ +} EUNM_MSG_SEND_METHOD_T, *P_EUNM_MSG_SEND_METHOD_T; + +typedef enum _ENUM_MBOX_ID_T { + MBOX_ID_0 = 0, + MBOX_ID_TOTAL_NUM +} ENUM_MBOX_ID_T, *P_ENUM_MBOX_ID_T; + +/* Define Mailbox structure */ +typedef struct _MBOX_T { + LINK_T rLinkHead; +} MBOX_T, *P_MBOX_T; + +typedef struct _MSG_SAA_FSM_START_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_START_T, *P_MSG_SAA_FSM_START_T; + +typedef struct _MSG_SAA_FSM_COMP_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + WLAN_STATUS rJoinStatus; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prSwRfb; +} MSG_SAA_FSM_COMP_T, *P_MSG_SAA_FSM_COMP_T; + +typedef struct _MSG_SAA_FSM_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + P_STA_RECORD_T prStaRec; +} MSG_SAA_FSM_ABORT_T, *P_MSG_SAA_FSM_ABORT_T; + +typedef struct _MSG_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucNetTypeIndex; +} MSG_CONNECTION_ABORT_T, *P_MSG_CONNECTION_ABORT_T; + +typedef struct _MSG_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eSco; + UINT_8 ucChannelNum; + UINT_32 u4DurationMs; + UINT_64 u8Cookie; +} MSG_REMAIN_ON_CHANNEL_T, *P_MSG_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_CANCEL_REMAIN_ON_CHANNEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_CANCEL_REMAIN_ON_CHANNEL_T, *P_MSG_CANCEL_REMAIN_ON_CHANNEL_T; + +typedef struct _MSG_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_MGMT_TX_REQUEST_T, *P_MSG_MGMT_TX_REQUEST_T; + +/* specific message data types */ +typedef MSG_SAA_FSM_START_T MSG_JOIN_REQ_T, *P_MSG_JOIN_REQ_T; +typedef MSG_SAA_FSM_COMP_T MSG_JOIN_COMP_T, *P_MSG_JOIN_COMP_T; +typedef MSG_SAA_FSM_ABORT_T MSG_JOIN_ABORT_T, *P_MSG_JOIN_ABORT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod); + +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId); + +VOID mboxInitialize(IN P_ADAPTER_T prAdapter); + +VOID mboxDestroy(IN P_ADAPTER_T prAdapter); + +VOID mboxDummy(IN P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HEM_MBOX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h new file mode 100644 index 0000000000000..88b99222133f4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/hs20.h @@ -0,0 +1,148 @@ +/* +** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/MT6620_WIFI_DRIVER_V2_1_HS_2_0/include/mgmt/hs20.h#2 +*/ + +/*! \file hs20.h + \brief This file contains the function declaration for hs20.c. +*/ + +/* +** Log: + * + */ + +#ifndef _HS20_H +#define _HS20_H + +#if CFG_SUPPORT_HOTSPOT_2_0 +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BSSID_POOL_MAX_SIZE 8 +#define HS20_SIGMA_SCAN_RESULT_TIMEOUT 30 /* sec */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_ENABLE_GTK_FRAME_FILTER +/*For GTK Frame Filter*/ +typedef struct _IPV4_NETWORK_ADDRESS_LIST { + UINT_8 ucAddrCount; + IPV4_NETWORK_ADDRESS arNetAddr[1]; +} IPV4_NETWORK_ADDRESS_LIST, *P_IPV4_NETWORK_ADDRESS_LIST; +#endif + +/* Entry of BSSID Pool - For SIGMA Test */ +typedef struct _BSSID_ENTRY_T { + UINT_8 aucBSSID[MAC_ADDR_LEN]; +} BSSID_ENTRY_T, P_HS20_BSSID_POOL_ENTRY_T; + +struct _HS20_INFO_T { + + /*Hotspot 2.0 Information */ + UINT_8 aucHESSID[MAC_ADDR_LEN]; + UINT_8 ucAccessNetworkOptions; + UINT_8 ucVenueGroup; /* VenueInfo - Group */ + UINT_8 ucVenueType; + UINT_8 ucHotspotConfig; + + /*Roaming Consortium Information */ + /* PARAM_HS20_ROAMING_CONSORTIUM_INFO rRCInfo; */ + + /*Hotspot 2.0 dummy AP Info */ + + /*Time Advertisement Information */ + /* UINT_32 u4UTCOffsetTime; */ + /* UINT_8 aucTimeZone[ELEM_MAX_LEN_TIME_ZONE]; */ + /* UINT_8 ucLenTimeZone; */ + + /* For SIGMA Test */ + /* BSSID Pool */ + BSSID_ENTRY_T arBssidPool[BSSID_POOL_MAX_SIZE]; + UINT_8 ucNumBssidPoolEntry; + BOOLEAN fgIsHS2SigmaMode; + +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*For GTK Frame Filter*/ +#if DBG +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + UINT_32 u4Size = OFFSET_OF(IPV4_NETWORK_ADDRESS_LIST, arNetAddr) + \ + (((_prAddrList)->ucAddrCount) * sizeof(IPV4_NETWORK_ADDRESS)); \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, u4Size); \ + (_prAddrList) = NULL; \ + } +#else +#define FREE_IPV4_NETWORK_ADDR_LIST(_prAddrList) \ + { \ + kalMemFree((_prAddrList), VIR_MEM_TYPE, 0); \ + (_prAddrList) = NULL; \ + } +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE); + +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID); + +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE); + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb); + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb); + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo); + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx); + +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h new file mode 100644 index 0000000000000..cb89fd8793ee4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/mib.h @@ -0,0 +1,153 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/mib.h#1 +*/ + +/*! \file mib.h + \brief This file contains the IEEE 802.11 family related MIB definition + for MediaTek 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: mib.h + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +#ifndef _MIB_H +#define _MIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Entry in SMT AuthenticationAlgorithms Table: dot11AuthenticationAlgorithmsEntry */ +typedef struct _DOT11_AUTHENTICATION_ALGORITHMS_ENTRY { + BOOLEAN dot11AuthenticationAlgorithmsEnable; /* dot11AuthenticationAlgorithmsEntry 3 */ +} DOT11_AUTHENTICATION_ALGORITHMS_ENTRY, *P_DOT11_AUTHENTICATION_ALGORITHMS_ENTRY; + +/* Entry in SMT dot11RSNAConfigPairwiseCiphersTalbe Table: dot11RSNAConfigPairwiseCiphersEntry */ +typedef struct _DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY { + UINT_32 dot11RSNAConfigPairwiseCipher; /* dot11RSNAConfigPairwiseCiphersEntry 2 */ + BOOLEAN dot11RSNAConfigPairwiseCipherEnabled; /* dot11RSNAConfigPairwiseCiphersEntry 3 */ +} DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY, *P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY; + +/* Entry in SMT dot11RSNAConfigAuthenticationSuitesTalbe Table: dot11RSNAConfigAuthenticationSuitesEntry */ +typedef struct _DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY { + UINT_32 dot11RSNAConfigAuthenticationSuite; /* dot11RSNAConfigAuthenticationSuitesEntry 2 */ + BOOLEAN dot11RSNAConfigAuthenticationSuiteEnabled; /* dot11RSNAConfigAuthenticationSuitesEntry 3 */ +} DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY, *P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY; + +/* ----- IEEE 802.11 MIB Major sections ----- */ +typedef struct _IEEE_802_11_MIB_T { + /* dot11PrivacyTable (dot11smt 5) */ + UINT_8 dot11WEPDefaultKeyID; /* dot11PrivacyEntry 2 */ + BOOLEAN dot11TranmitKeyAvailable; + UINT_32 dot11WEPICVErrorCount; /* dot11PrivacyEntry 5 */ + UINT_32 dot11WEPExcludedCount; /* dot11PrivacyEntry 6 */ + + /* dot11RSNAConfigTable (dot11smt 8) */ + UINT_32 dot11RSNAConfigGroupCipher; /* dot11RSNAConfigEntry 4 */ + + /* dot11RSNAConfigPairwiseCiphersTable (dot11smt 9) */ + DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY dot11RSNAConfigPairwiseCiphersTable[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + + /* dot11RSNAConfigAuthenticationSuitesTable (dot11smt 10) */ + DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY + dot11RSNAConfigAuthenticationSuitesTable[MAX_NUM_SUPPORTED_AKM_SUITES]; + +#if 0 /* SUPPORT_WAPI */ + BOOLEAN fgWapiKeyInstalled; + PARAM_WPI_KEY_T rWapiPairwiseKey[2]; + BOOLEAN fgPairwiseKeyUsed[2]; + UINT_8 ucWpiActivedPWKey; /* Must be 0 or 1, by wapi spec */ + PARAM_WPI_KEY_T rWapiGroupKey[2]; + BOOLEAN fgGroupKeyUsed[2]; +#endif +} IEEE_802_11_MIB_T, *P_IEEE_802_11_MIB_T; + +/* ------------------ IEEE 802.11 non HT PHY characteristics ---------------- */ +typedef const struct _NON_HT_PHY_ATTRIBUTE_T { + UINT_16 u2SupportedRateSet; + + BOOLEAN fgIsShortPreambleOptionImplemented; + + BOOLEAN fgIsShortSlotTimeOptionImplemented; + +} NON_HT_PHY_ATTRIBUTE_T, *P_NON_HT_PHY_ATTRIBUTE_T; + +typedef const struct _NON_HT_ADHOC_MODE_ATTRIBUTE_T { + + ENUM_PHY_TYPE_INDEX_T ePhyTypeIndex; + + UINT_16 u2BSSBasicRateSet; + +} NON_HT_ADHOC_MODE_ATTRIBUTE_T, *P_NON_HT_ADHOC_MODE_ATTRIBUTE_T; + +typedef NON_HT_ADHOC_MODE_ATTRIBUTE_T NON_HT_AP_MODE_ATTRIBUTE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[]; +extern NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[]; +extern NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h new file mode 100644 index 0000000000000..11145c31dbfae --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_assoc.h @@ -0,0 +1,55 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_assoc.h#1 +*/ + +/*! \file p2p_assoc.h + \brief This file contains the Wi-Fi Direct ASSOC REQ/RESP of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + +#ifndef _P2P_ASSOC_H +#define _P2P_ASSOC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h new file mode 100644 index 0000000000000..869d7bf0ee614 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_bss.h @@ -0,0 +1,56 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_bss.h#2 +*/ + +/*! \file "p2p_bss.h" + \brief In this file we define the function prototype used in p2p BSS/IBSS. + + The file contains the function declarations and defines for used in BSS/IBSS. +*/ + +#ifndef _P2P_BSS_H +#define _P2P_BSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +UINT_32 p2pGetTxProbRspIeTableSize(VOID); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h new file mode 100644 index 0000000000000..2541e1d2883e8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_fsm.h @@ -0,0 +1,2190 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_fsm.h#23 +*/ + +/*! \file p2p_fsm.h + \brief Declaration of functions and finite state machine for P2P Module. + + Declaration of functions and finite state machine for P2P Module. +*/ + +/* +** Log: p2p_fsm.h +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 14 2012 yuche.tsai +** NULL +** Fix compile error. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 18 2012 yuche.tsai + * NULL + * add one file. + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve class 3 error issue under AP mode. + * + * data frame may TX before Assoc Response TX. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix default device name issue. + * + * 11 09 2011 yuche.tsai + * [WCXRP00001093] [Need Patch][Volunteer Patch] Service Discovery 2.0 state transition issue. + * Fix SD2.0 issue which may cause KE. (Monkey test) + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version + * query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channel Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 09 01 2011 yuche.tsai + * NULL + * Fix channel stay interval. + * Sync channel stay interval & channel request interval under AP mode.. + * + * 08 30 2011 yuche.tsai + * [WCXRP00000953] [Volunteer Patch][Driver] Hot Spot Channel ASSERT issue. + * Fix hot spot FW assert issue when under concurrent case. (DBG enable only) + * + * 08 16 2011 cp.wu + * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence + * auto channel decision for 2.4GHz hot spot mode + * + * 08 16 2011 yuche.tsai + * NULL + * Fix scan policy for Active LISTEN scan. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, + * TX deauth to a disconnecting device issue. + * Support TX Deauth Issue. + * + * 07 26 2011 yuche.tsai + * [WCXRP00000875] [Volunteer Patch][WiFi Direct][Driver] MT6620 IOT issue with realtek test bed solution. + * Turn off persistent group support for V2.0 release. + * + * 07 18 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Fix compile error. + * + * 07 18 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Fix MT6620 WiFi Direct IOT Issue with BCM solution. + * + * 07 11 2011 yuche.tsai + * [WCXRP00000845] [Volunteer Patch][WiFi Direct] WiFi Direct Device Connection Robustness + * Enhance Connection Robustness. + * + * 07 08 2011 yuche.tsai + * [WCXRP00000841] [Volunteer Patch][WiFi Direct] Group Owner Setting. + * Update GO configure parameter. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Disable enhancement II for debugging. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Refine compile flag. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix connection indication twice issue. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 05 04 2011 yuche.tsai + * NULL + * Support partial persistent group function. + * + * 04 20 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove CFG_WIFI_DIRECT_MOVED. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 22 2011 yuche.tsai + * NULL + * 1.Shorten the LISTEN interval. + * 2. Fix IF address issue when we are GO + * 3. Fix LISTEN channel issue. + * + * 03 21 2011 yuche.tsai + * NULL + * Change P2P Connection Request Flow. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 07 2011 yuche.tsai + * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the ioctl setting that index not map to spec defined config method. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC IE BE format issue. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 11 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add two function prototype. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Support Disassoc & Deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. + +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. + +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 25 2011 terry.wu + * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter + * Add a new module parameter to indicate current runnig mode, P2P or AP. + * + * 01 19 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Null NOA attribute setting when no related parameters. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify some behavior of AP mode. + * + * 12 22 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Compile Error. + * + * 12 15 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Refine Connection Flow. + * + * 12 08 2010 yuche.tsai + * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. + * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client + * by checking the P2P IE in assoc req frame. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation & Provision Discovery. + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 30 2010 yuche.tsai + * NULL + * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ + * + * 11 29 2010 yuche.tsai + * NULL + * Update P2P related function for INVITATION & PROVISION DISCOVERY. + * + * 11 26 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Update P2P PS for NOA function. + * + * 11 25 2010 yuche.tsai + * NULL + * Update Code for Invitation Related Function. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] + * Set the Tx lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at WinXP. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 26 2010 yuche.tsai + * NULL + * Add connection abort message event prototype. + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 16 2010 yuche.tsai + * NULL + * Fix P2P Intended Interface Address Bug. + * Extend GO Nego Timeout Time. + * + * 08 16 2010 yuche.tsai + * NULL + * Extend Listen Interval default value & remove deprecated variable. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Add function prototype for join complete. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some function proto type for P2P FSM under provisioning phase.. + * + * 08 11 2010 yuche.tsai + * NULL + * Change P2P data structure for supporting + * 1. P2P Device discovery. + * 2. P2P Group Negotiation. + * 3. P2P JOIN + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Update P2P FSM header file. + * + * 07 23 2010 cp.wu + * + * P2P/RSN/WAPI IEs need to be declared with compact structure. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Update P2P FSM header file. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix some P2P function prototype. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename CFG flag for P2P + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify parameter of p2pStartGO + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add Wi-Fi Direct SSID and P2P GO Test Mode + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +#ifndef _P2P_FSM_H +#define _P2P_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CID52_53_54 0 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_P2P_STATE_T { + P2P_STATE_IDLE = 0, + P2P_STATE_SCAN, + P2P_STATE_AP_CHANNEL_DETECT, + P2P_STATE_REQING_CHANNEL, + P2P_STATE_CHNL_ON_HAND, /* Requesting Channel to Send Specific Frame. */ + P2P_STATE_GC_JOIN, /* Sending Specific Frame. May extending channel by other event. */ + P2P_STATE_NUM +} ENUM_P2P_STATE_T, *P_ENUM_P2P_STATE_T; + +enum _ENUM_P2P_DEV_EXT_LISTEN_T { + P2P_DEV_NOT_EXT_LISTEN, + P2P_DEV_EXT_LISTEN_ING, + P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT, + P2P_DEV_EXT_LISTEN_NUM +}; + +typedef enum _ENUM_CHANNEL_REQ_TYPE_T { + CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL, + CHANNEL_REQ_TYPE_GC_JOIN_REQ, + CHANNEL_REQ_TYPE_GO_START_BSS +} ENUM_CHANNEL_REQ_TYPE_T, *P_ENUM_CHANNEL_REQ_TYPE_T; + +typedef enum _ENUM_BUFFER_TYPE_T { + ENUM_FRAME_TYPE_EXTRA_IE_BEACON, + ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP, + ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP, + ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE, + ENUM_FRAME_TYPE_BEACON_TEMPLATE, + ENUM_FRAME_IE_NUM +} ENUM_BUFFER_TYPE_T, *P_ENUM_BUFFER_TYPE_T; + +typedef enum _ENUM_HIDDEN_SSID_TYPE_T { + ENUM_HIDDEN_SSID_NONE, + ENUM_HIDDEN_SSID_LEN, + ENUM_HIDDEN_SSID_ZERO_CONTENT, + ENUM_HIDDEN_SSID_NUM +} ENUM_HIDDEN_SSID_TYPE_T, *P_ENUM_HIDDEN_SSID_TYPE_T; + +typedef struct _P2P_SSID_STRUCT_T { + UINT_8 aucSsid[32]; + UINT_8 ucSsidLen; +} P2P_SSID_STRUCT_T, *P_P2P_SSID_STRUCT_T; + +typedef struct _P2P_STATION_INFO_T { + UINT_32 u4InactiveTime; + UINT_32 u4RxBytes; /* TODO: */ + UINT_32 u4TxBytes; /* TODO: */ + UINT_32 u4RxPackets; /* TODO: */ + UINT_32 u4TxPackets; /* TODO: */ + /* TODO: Add more for requirement. */ +} P2P_STATION_INFO_T, *P_P2P_STATION_INFO_T; + +typedef struct _AP_CRYPTO_SETTINGS_T { + UINT_32 u4WpaVersion; + UINT_32 u4CipherGroup; + INT_32 i4NumOfCiphers; + UINT_32 aucCiphersPairwise[5]; + INT_32 i4NumOfAkmSuites; + UINT_32 aucAkmSuites[2]; + BOOLEAN fgIsControlPort; + UINT_16 u2ControlPortBE; + BOOLEAN fgIsControlPortEncrypt; +} AP_CRYPTO_SETTINGS_T, *P_AP_CRYPTO_SETTINGS_T; + +/*-------------------- P2P FSM ACTION STRUCT ---------------------*/ +typedef struct _P2P_CHNL_REQ_INFO_T { + BOOLEAN fgIsChannelRequested; + UINT_8 ucSeqNumOfChReq; + UINT_64 u8Cookie; + UINT_8 ucReqChnlNum; + ENUM_BAND_T eBand; + ENUM_CHNL_EXT_T eChnlSco; + UINT_32 u4MaxInterval; + ENUM_CHANNEL_REQ_TYPE_T eChannelReqType; + + UINT_8 ucOriChnlNum; + ENUM_BAND_T eOriBand; + ENUM_CHNL_EXT_T eOriChnlSco; + UINT_32 NFC_BEAM; /*NFC Beam + Indication */ +} P2P_CHNL_REQ_INFO_T, *P_P2P_CHNL_REQ_INFO_T; + +typedef struct _P2P_SCAN_REQ_INFO_T { + ENUM_SCAN_TYPE_T eScanType; + ENUM_SCAN_CHANNEL eChannelSet; + UINT_16 u2PassiveDewellTime; + UINT_8 ucSeqNumOfScnMsg; + BOOLEAN fgIsAbort; + BOOLEAN fgIsScanRequest; + UINT_8 ucNumChannelList; + RF_CHANNEL_INFO_T arScanChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + P2P_SSID_STRUCT_T rSsidStruct; /* Currently we can only take one SSID scan request */ + BOOLEAN fgIsGOInitialDone; +} P2P_SCAN_REQ_INFO_T, *P_P2P_SCAN_REQ_INFO_T; + +typedef struct _P2P_CONNECTION_REQ_INFO_T { + + BOOLEAN fgIsConnRequest; + P2P_SSID_STRUCT_T rSsidStruct; + UINT_8 aucBssid[MAC_ADDR_LEN]; + /* For ASSOC Req. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_CONNECTION_REQ_INFO_T, *P_P2P_CONNECTION_REQ_INFO_T; + +typedef struct _P2P_MGMT_TX_REQ_INFO_T { + BOOLEAN fgIsMgmtTxRequested; + P_MSDU_INFO_T prMgmtTxMsdu; + UINT_64 u8Cookie; +} P2P_MGMT_TX_REQ_INFO_T, *P_P2P_MGMT_TX_REQ_INFO_T; + +struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T { + MSG_HDR_T rMsgHdr; + UINT_32 wait; /* interval supplicant expected to stay in listen interval */ +}; + +typedef struct _P2P_BEACON_UPDATE_INFO_T { + PUINT_8 pucBcnHdr; + UINT_32 u4BcnHdrLen; + PUINT_8 pucBcnBody; + UINT_32 u4BcnBodyLen; +} P2P_BEACON_UPDATE_INFO_T, *P_P2P_BEACON_UPDATE_INFO_T; + +typedef struct _P2P_PROBE_RSP_UPDATE_INFO_T { + P_MSDU_INFO_T prProbeRspMsduTemplate; +} P2P_PROBE_RSP_UPDATE_INFO_T, *P_P2P_PROBE_RSP_UPDATE_INFO_T; + +typedef struct _P2P_ASSOC_RSP_UPDATE_INFO_T { + PUINT_8 pucAssocRspExtIE; + UINT_16 u2AssocIELen; +} P2P_ASSOC_RSP_UPDATE_INFO_T, *P_P2P_ASSOC_RSP_UPDATE_INFO_T; + +typedef struct _P2P_JOIN_INFO_T { + UINT_32 ucSeqNumOfReqMsg; + UINT_8 ucAvailableAuthTypes; + P_STA_RECORD_T prTargetStaRec; + P2P_SSID_STRUCT_T rSsidStruct; + BOOLEAN fgIsJoinComplete; + /* For ASSOC Rsp. */ + UINT_32 u4BufLength; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; +} P2P_JOIN_INFO_T, *P_P2P_JOIN_INFO_T; + +#if CFG_SUPPORT_WFD + +#define WFD_FLAGS_DEV_INFO_VALID BIT(0) /* 1. WFD_DEV_INFO, 2. WFD_CTRL_PORT, 3. WFD_MAT_TP. */ +#define WFD_FLAGS_SINK_INFO_VALID BIT(1) /* 1. WFD_SINK_STATUS, 2. WFD_SINK_MAC. */ +#define WFD_FLAGS_ASSOC_MAC_VALID BIT(2) /* 1. WFD_ASSOC_MAC. */ +#define WFD_FLAGS_EXT_CAPABILITY_VALID BIT(3) /* 1. WFD_EXTEND_CAPABILITY. */ + +struct _WFD_CFG_SETTINGS_T { + UINT_32 u4WfdCmdType; + UINT_8 ucWfdEnable; + UINT_8 ucWfdCoupleSinkStatus; + UINT_8 ucWfdSessionAvailable; /* 0: NA 1:Set 2:Clear */ + UINT_8 ucWfdSigmaMode; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdControlPort; + UINT_16 u2WfdMaximumTp; + UINT_16 u2WfdExtendCap; + UINT_8 aucWfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 aucWfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 aucWfdVideoIp[4]; + UINT_8 aucWfdAudioIp[4]; + UINT_16 u2WfdVideoPort; + UINT_16 u2WfdAudioPort; + UINT_32 u4WfdFlag; + UINT_32 u4WfdPolicy; + UINT_32 u4WfdState; + UINT_8 aucWfdSessionInformationIE[24 * 8]; + UINT_16 u2WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 u4WfdAdvancedFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 u2WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 u2WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 u2WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReverved2[54]; + /* Group 2 64 bytes */ + UINT_8 aucReverved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReverved4[64]; + +}; + +struct _WFD_DBG_CFG_SETTINGS_T { + UINT_8 ucWfdDebugMode; + UINT_16 u2WfdSNShowPeiroid; + UINT_8 Reserved; + +}; + +#endif + +struct _P2P_FSM_INFO_T { + /* State related. */ + ENUM_P2P_STATE_T ePreviousState; + ENUM_P2P_STATE_T eCurrentState; + + /* Channel related. */ + P2P_CHNL_REQ_INFO_T rChnlReqInfo; + + /* Scan related. */ + P2P_SCAN_REQ_INFO_T rScanReqInfo; + + /* Connection related. */ + P2P_CONNECTION_REQ_INFO_T rConnReqInfo; + + /* Mgmt tx related. */ + P2P_MGMT_TX_REQ_INFO_T rMgmtTxInfo; + + /* Beacon related. */ + P2P_BEACON_UPDATE_INFO_T rBcnContentInfo; + + /* Probe Response related. */ + P2P_PROBE_RSP_UPDATE_INFO_T rProbeRspContentInfo; + + /* Assoc Rsp related. */ + P2P_ASSOC_RSP_UPDATE_INFO_T rAssocRspContentInfo; + + /* GC Join related. */ + P2P_JOIN_INFO_T rJoinInfo; + + /* FSM Timer */ +/* TIMER_T rP2pFsmTimeoutTimer; */ + + /* GC Target BSS. */ + P_BSS_DESC_T prTargetBss; + + /* GC Connection Request. */ + BOOLEAN fgIsConnectionRequested; + + BOOLEAN fgIsApMode; + + /* Channel grant interval. */ + UINT_32 u4GrantInterval; + + /* Packet filter for P2P module. */ + UINT_32 u4P2pPacketFilter; + + /* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Prepare for use vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */ + /* Msg event queue. */ + LINK_T rMsgEventQueue; + +#if CFG_SUPPORT_WFD + WFD_CFG_SETTINGS_T rWfdConfigureSettings; + WFD_DBG_CFG_SETTINGS_T rWfdDebugSetting; +#endif + + BOOLEAN fgIsWPSMode; + + enum _ENUM_P2P_DEV_EXT_LISTEN_T eListenExted; +}; + +/*---------------- Messages -------------------*/ +typedef struct _MSG_P2P_SCAN_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P_P2P_SSID_STRUCT_T prSSID; + INT_32 i4SsidNum; + UINT_32 u4NumChannel; + PUINT_8 pucIEBuf; + UINT_32 u4IELen; + BOOLEAN fgIsAbort; + RF_CHANNEL_INFO_T arChannelListInfo[1]; +} MSG_P2P_SCAN_REQUEST_T, *P_MSG_P2P_SCAN_REQUEST_T; + +typedef struct _MSG_P2P_CHNL_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; + UINT_32 u4Duration; + ENUM_CHNL_EXT_T eChnlSco; + RF_CHANNEL_INFO_T rChannelInfo; +} MSG_P2P_CHNL_REQUEST_T, *P_MSG_P2P_CHNL_REQUEST_T; + +typedef struct _MSG_P2P_CHNL_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_64 u8Cookie; +} MSG_P2P_CHNL_ABORT_T, *P_MSG_P2P_CHNL_ABORT_T; + +typedef struct _MSG_P2P_CONNECTION_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P2P_SSID_STRUCT_T rSsid; + UINT_8 aucBssid[MAC_ADDR_LEN]; + ENUM_CHNL_EXT_T eChnlSco; + RF_CHANNEL_INFO_T rChannelInfo; + UINT_32 u4IELen; + UINT_8 aucIEBuf[1]; + /* TODO: Auth Type, OPEN, SHARED, FT, EAP... */ +} MSG_P2P_CONNECTION_REQUEST_T, *P_MSG_P2P_CONNECTION_REQUEST_T; + +typedef struct _MSG_P2P_CONNECTION_ABORT_T { + MSG_HDR_T rMsgHdr; /* Must be the first member. */ + UINT_8 aucTargetID[MAC_ADDR_LEN]; + UINT_16 u2ReasonCode; + BOOLEAN fgSendDeauth; +} MSG_P2P_CONNECTION_ABORT_T, *P_MSG_P2P_CONNECTION_ABORT_T; + +typedef struct _MSG_P2P_MGMT_TX_REQUEST_T { + MSG_HDR_T rMsgHdr; + P_MSDU_INFO_T prMgmtMsduInfo; + UINT_64 u8Cookie; /* For indication. */ + BOOLEAN fgNoneCckRate; + BOOLEAN fgIsWaitRsp; +} MSG_P2P_MGMT_TX_REQUEST_T, *P_MSG_P2P_MGMT_TX_REQUEST_T; + +typedef struct _MSG_P2P_START_AP_T { + MSG_HDR_T rMsgHdr; + UINT_32 u4DtimPeriod; + UINT_32 u4BcnInterval; + UINT_8 aucSsid[32]; + UINT_16 u2SsidLen; + UINT_8 ucHiddenSsidType; + BOOLEAN fgIsPrivacy; + AP_CRYPTO_SETTINGS_T rEncryptionSettings; + INT_32 i4InactiveTimeout; +} MSG_P2P_START_AP_T, *P_MSG_P2P_START_AP_T; + +typedef struct _MSG_P2P_BEACON_UPDATE_T { + MSG_HDR_T rMsgHdr; + UINT_32 u4BcnHdrLen; + UINT_32 u4BcnBodyLen; + PUINT_8 pucBcnHdr; + PUINT_8 pucBcnBody; + UINT_8 aucBuffer[1]; /* Header & Body are put here. */ +} MSG_P2P_BEACON_UPDATE_T, *P_MSG_P2P_BEACON_UPDATE_T; + +typedef struct _MSG_P2P_MGMT_FRAME_UPDATE_T { + MSG_HDR_T rMsgHdr; + ENUM_BUFFER_TYPE_T eBufferType; + UINT_32 u4BufferLen; + UINT_8 aucBuffer[1]; +} MSG_P2P_MGMT_FRAME_UPDATE_T, *P_MSG_P2P_MGMT_FRAME_UPDATE_T; + +typedef struct _MSG_P2P_SWITCH_OP_MODE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + ENUM_OP_MODE_T eOpMode; +} MSG_P2P_SWITCH_OP_MODE_T, *P_MSG_P2P_SWITCH_OP_MODE_T; + +typedef struct _MSG_P2P_MGMT_FRAME_REGISTER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_16 u2FrameType; + BOOLEAN fgIsRegister; +} MSG_P2P_MGMT_FRAME_REGISTER_T, *P_MSG_P2P_MGMT_FRAME_REGISTER_T; + +typedef struct _MSG_P2P_NETDEV_REGISTER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsEnable; + UINT_8 ucMode; +} MSG_P2P_NETDEV_REGISTER_T, *P_MSG_P2P_NETDEV_REGISTER_T; + +#if CFG_SUPPORT_WFD +typedef struct _MSG_WFD_CONFIG_SETTINGS_CHANGED_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings; +} MSG_WFD_CONFIG_SETTINGS_CHANGED_T, *P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T; +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID p2pFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS +p2pFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); +#endif + +#if 0 +/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */ +/* ///////////////////////////////////////////////////////////////////////////////////// */ +/* ///////////////////////////////////////////////////////////////////////////////////// */ +/* ///////////////////////////////////////////////////////////////////////////////////// */ +/* ///////////////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////////////////////////////////// */ +#endif + +/* 3 --------------- WFA P2P DEFAULT PARAMETERS --------------- */ +#define P2P_WILDCARD_SSID "DIRECT-" +#define P2P_WILDCARD_SSID_LEN 7 +#define P2P_GROUP_ID_LEN 9 + +#define P2P_DRIVER_VERSION 2 /* Update when needed. */ + +#define P2P_DEFAULT_DEV_NAME "Wireless Client" +#define P2P_DEFAULT_DEV_NAME_LEN 15 +#define P2P_DEFAULT_PRIMARY_CATEGORY_ID 10 +#define P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID 5 +#define P2P_DEFAULT_CONFIG_METHOD \ + (WPS_ATTRI_CFG_METHOD_PUSH_BUTTON | WPS_ATTRI_CFG_METHOD_KEYPAD | WPS_ATTRI_CFG_METHOD_DISPLAY) +#define P2P_DEFAULT_LISTEN_CHANNEL 1 + +#define P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT 0 /* NOTE(Kevin): Shall <= 16 */ +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT 13 + +#define P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE 51 /* Contains 6 sub-band. */ + +#define P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT 8 /* NOTE(Kevin): Shall <= 16 */ + +#define P2P_MAXIMUM_CLIENT_COUNT 8 +#define P2P_MAXIMUM_NOA_COUNT 8 + +#define P2P_MAXIMUM_ATTRIBUTE_LEN 251 + +#define P2P_CTWINDOW_DEFAULT 25 /* in TU=(1024usec) */ + +#define P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE 768 + +/* P2P 3.1.2.1.3 - Find Phase */ +#define P2P_MAX_DISCOVERABLE_INTERVAL 8 /* 3 */ +#define P2P_MIN_DISCOVERABLE_INTERVAL 5 /* 1 */ + +#define P2P_LISTEN_SCAN_UNIT 100 /* MS */ + +/* FSM Time Related constrain. */ +#define P2P_SERACH_STATE_PERIOD_MS 1000 /* Deprecated. */ + +#define P2P_GO_CHANNEL_STAY_INTERVAL 1000 + +#define P2P_GO_NEGO_TIMEOUT_MS 500 +#define P2P_CONNECTION_TIMEOUT_SEC 120 + +#define P2P_INVITAION_TIMEOUT_MS 500 /* Timeout Wait Invitation Resonse. */ +#define P2P_PROVISION_DISCOVERY_TIMEOUT_MS 500 /* Timeout Wait Provision Discovery Resonse. */ + +/* 3 --------------- WFA P2P IE --------------- */ +/* P2P 4.1.1 - P2P IE format */ +#define P2P_OUI_TYPE_LEN 4 +#define P2P_IE_OUI_HDR (ELEM_HDR_LEN + P2P_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, + aucP2PAttributes[0]) */ + +/* P2P 4.1.1 - General P2P Attribute */ +#define P2P_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ +#define P2P_ATTRI_LEN_NOTICE_OF_ABSENCE (P2P_ATTRI_HDR_LEN + 2) /* 5 */ + +/* P2P 4.1.1 - P2P Attribute ID definitions */ +#define P2P_ATTRI_ID_STATUS 0 +#define P2P_ATTRI_ID_REASON_CODE 1 +#define P2P_ATTRI_ID_P2P_CAPABILITY 2 +#define P2P_ATTRI_ID_P2P_DEV_ID 3 +#define P2P_ATTRI_ID_GO_INTENT 4 +#define P2P_ATTRI_ID_CFG_TIMEOUT 5 +#define P2P_ATTRI_ID_LISTEN_CHANNEL 6 +#define P2P_ATTRI_ID_P2P_GROUP_BSSID 7 +#define P2P_ATTRI_ID_EXT_LISTEN_TIMING 8 +#define P2P_ATTRI_ID_INTENDED_P2P_IF_ADDR 9 +#define P2P_ATTRI_ID_P2P_MANAGEABILITY 10 +#define P2P_ATTRI_ID_CHANNEL_LIST 11 +#define P2P_ATTRI_ID_NOTICE_OF_ABSENCE 12 +#define P2P_ATTRI_ID_P2P_DEV_INFO 13 +#define P2P_ATTRI_ID_P2P_GROUP_INFO 14 +#define P2P_ATTRI_ID_P2P_GROUP_ID 15 +#define P2P_ATTRI_ID_P2P_INTERFACE 16 +#define P2P_ATTRI_ID_OPERATING_CHANNEL 17 +#define P2P_ATTRI_ID_INVITATION_FLAG 18 +#define P2P_ATTRI_ID_VENDOR_SPECIFIC 221 + +/* Maximum Length of P2P Attributes */ +#define P2P_ATTRI_MAX_LEN_STATUS 1 /* 0 */ +#define P2P_ATTRI_MAX_LEN_REASON_CODE 1 /* 1 */ +#define P2P_ATTRI_MAX_LEN_P2P_CAPABILITY 2 /* 2 */ +#define P2P_ATTRI_MAX_LEN_P2P_DEV_ID 6 /* 3 */ +#define P2P_ATTRI_MAX_LEN_GO_INTENT 1 /* 4 */ +#define P2P_ATTRI_MAX_LEN_CFG_TIMEOUT 2 /* 5 */ +#if CID52_53_54 +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#else +#define P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL 5 /* 6 */ +#endif +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_BSSID 6 /* 7 */ +#define P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING 4 /* 8 */ +#define P2P_ATTRI_MAX_LEN_INTENDED_P2P_IF_ADDR 6 /* 9 */ +#define P2P_ATTRI_MAX_LEN_P2P_MANAGEABILITY 1 /* 10 */ +/* #define P2P_ATTRI_MAX_LEN_CHANNEL_LIST 3 + (n* (2 + num_of_ch)) */ /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_LIST 3 /* 11 */ +#define P2P_ATTRI_LEN_CHANNEL_ENTRY 2 /* 11 */ + +/* #define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE 2 + (n* (13)) */ /* 12 */ +#define P2P_ATTRI_MAX_LEN_NOTICE_OF_ABSENCE (2 + (P2P_MAXIMUM_NOA_COUNT*(13))) /* 12 */ + +#define P2P_ATTRI_MAX_LEN_P2P_DEV_INFO (17 + (8 * (8)) + 36) /* 13 */ +/* #define P2P_ATTRI_MAX_LEN_P2P_GROUP_INFO n* (25 + (m* (8)) + 32) */ /* 14 */ +#define P2P_ATTRI_MAX_LEN_P2P_GROUP_ID 38 /* 15 */ +#define P2P_ATTRI_MAX_LEN_P2P_INTERFACE 253 /* 7 + 6* [0~41] */ /* 16 */ +#if CID52_53_54 +#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#else +#define P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL 5 /* 17 */ +#endif +#define P2P_ATTRI_MAX_LEN_INVITATION_FLAGS 1 /* 18 */ + +/* P2P 4.1.2 - P2P Status definitions */ +#define P2P_STATUS_SUCCESS 0 +#define P2P_STATUS_FAIL_INFO_IS_CURRENTLY_UNAVAILABLE 1 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PARAM 2 +#define P2P_STATUS_FAIL_LIMIT_REACHED 3 +#define P2P_STATUS_FAIL_INVALID_PARAM 4 +#define P2P_STATUS_FAIL_UNABLE_ACCOMMODATE_REQ 5 +#define P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR 6 +#define P2P_STATUS_FAIL_NO_COMMON_CHANNELS 7 +#define P2P_STATUS_FAIL_UNKNOWN_P2P_GROUP 8 +#define P2P_STATUS_FAIL_SAME_INTENT_VALUE_15 9 +#define P2P_STATUS_FAIL_INCOMPATIBLE_PROVISION_METHOD 10 +#define P2P_STATUS_FAIL_REJECTED_BY_USER 11 + +/* P2P 4.1.3 - P2P Minor Reason Code definitions */ +#define P2P_REASON_SUCCESS 0 +#define P2P_REASON_DISASSOCIATED_DUE_CROSS_CONNECTION 1 +#define P2P_REASON_DISASSOCIATED_DUE_UNMANAGEABLE 2 +#define P2P_REASON_DISASSOCIATED_DUE_NO_P2P_COEXIST_PARAM 3 +#define P2P_REASON_DISASSOCIATED_DUE_MANAGEABLE 4 + +/* P2P 4.1.4 - Device Capability Bitmap definitions */ +#define P2P_DEV_CAPABILITY_SERVICE_DISCOVERY BIT(0) +#define P2P_DEV_CAPABILITY_CLIENT_DISCOVERABILITY BIT(1) +#define P2P_DEV_CAPABILITY_CONCURRENT_OPERATION BIT(2) +#define P2P_DEV_CAPABILITY_P2P_INFRA_MANAGED BIT(3) +#define P2P_DEV_CAPABILITY_P2P_DEVICE_LIMIT BIT(4) +#define P2P_DEV_CAPABILITY_P2P_INVITATION_PROCEDURE BIT(5) + +/* P2P 4.1.4 - Group Capability Bitmap definitions */ +#define P2P_GROUP_CAPABILITY_P2P_GROUP_OWNER BIT(0) +#define P2P_GROUP_CAPABILITY_PERSISTENT_P2P_GROUP BIT(1) +#define P2P_GROUP_CAPABILITY_P2P_GROUP_LIMIT BIT(2) +#define P2P_GROUP_CAPABILITY_INTRA_BSS_DISTRIBUTION BIT(3) +#define P2P_GROUP_CAPABILITY_CROSS_CONNECTION BIT(4) +#define P2P_GROUP_CAPABILITY_PERSISTENT_RECONNECT BIT(5) +#define P2P_GROUP_CAPABILITY_GROUP_FORMATION BIT(6) + +/* P2P 4.1.6 - GO Intent field definitions */ +#define P2P_GO_INTENT_TIE_BREAKER_FIELD BIT(0) +#define P2P_GO_INTENT_VALUE_MASK BITS(1, 7) +#define P2P_GO_INTENT_VALUE_OFFSET 1 + +/* P2P 4.1.12 - Manageability Bitmap definitions */ +#define P2P_DEVICE_MANAGEMENT BIT(0) + +/* P2P 4.1.14 - CTWindow and OppPS Parameters definitions */ +#define P2P_CTW_OPPPS_PARAM_OPPPS_FIELD BIT(7) +#define P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK BITS(0, 6) + +#define ELEM_MAX_LEN_P2P_FOR_PROBE_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_ID) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_LISTEN_CHANNEL) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_OPERATING_CHANNEL)) + +#define ELEM_MAX_LEN_P2P_FOR_ASSOC_REQ \ + (P2P_OUI_TYPE_LEN + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_CAPABILITY) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING) + \ + (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_P2P_DEV_INFO)) + +/* P2P 4.1.16 - P2P Client Infor Descriptor */ +#define P2P_CLIENT_INFO_DESC_HDR_LEN 1 /* Length(1 octets) */ + +/* P2P 4.1.20 - P2P Invitation Flags Attribute*/ +#define P2P_INVITATION_FLAGS_INVITATION_TYPE BIT(0) +#define P2P_INVITATION_TYPE_INVITATION 0 +#define P2P_INVITATION_TYPE_REINVOKE 1 +/* 3 --------------- WPS Data Element Definitions --------------- */ +/* P2P 4.2.2 - General WSC Attribute */ +#define WSC_ATTRI_HDR_LEN 4 /* ID(2 octet) + Length(2 octets) */ +#define WSC_ATTRI_MAX_LEN_VERSION 1 +#define WSC_ATTRI_MAX_LEN_DEVICE_PASSWORD_ID 2 +#define WSC_ATTRI_LEN_CONFIG_METHOD 2 + +/* WPS 11 - Data Element Definitions */ +#define WPS_ATTRI_ID_VERSION 0x104A +#define WPS_ATTRI_ID_CONFIGURATION_METHODS 0x1008 +#define WPS_ATTRI_ID_DEVICE_PASSWORD 0x1012 +#define WPS_ATTRI_ID_DEVICE_NAME 0x1011 +#define WPS_ATTRI_ID_PRI_DEVICE_TYPE 0x1054 +#define WPS_ATTRI_ID_SEC_DEVICE_TYPE 0x1055 + +#define WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE 300 + +#define WPS_ATTRI_MAX_LEN_DEVICE_NAME 32 /* 0x1011 */ + +#define WPS_ATTRI_CFG_METHOD_USBA BIT(0) +#define WPS_ATTRI_CFG_METHOD_ETHERNET BIT(1) +#define WPS_ATTRI_CFG_METHOD_LABEL BIT(2) +#define WPS_ATTRI_CFG_METHOD_DISPLAY BIT(3) +#define WPS_ATTRI_CFG_METHOD_EXT_NFC BIT(4) +#define WPS_ATTRI_CFG_METHOD_INT_NFC BIT(5) +#define WPS_ATTRI_CFG_METHOD_NFC_IF BIT(6) +#define WPS_ATTRI_CFG_METHOD_PUSH_BUTTON BIT(7) +#define WPS_ATTRI_CFG_METHOD_KEYPAD BIT(8) + +#define P2P_FLAGS_PROVISION_COMPLETE 0x00000001 +#define P2P_FLAGS_PROVISION_DISCOVERY_COMPLETE 0x00000002 +#define P2P_FLAGS_PROVISION_DISCOVERY_WAIT_RESPONSE 0x00000004 +#define P2P_FLAGS_PROVISION_DISCOVERY_RESPONSE_WAIT 0x00000008 +#define P2P_FLAGS_MASK_PROVISION 0x00000017 +#define P2P_FLAGS_MASK_PROVISION_COMPLETE 0x00000015 +#define P2P_FLAGS_PROVISION_DISCOVERY_INDICATED 0x00000010 +#define P2P_FLAGS_INVITATION_TOBE_GO 0x00000100 +#define P2P_FLAGS_INVITATION_TOBE_GC 0x00000200 +#define P2P_FLAGS_INVITATION_SUCCESS 0x00000400 +#define P2P_FLAGS_INVITATION_WAITING_TARGET 0x00000800 +#define P2P_FLAGS_MASK_INVITATION 0x00000F00 +#define P2P_FLAGS_FORMATION_ON_GOING 0x00010000 +#define P2P_FLAGS_FORMATION_LOCAL_PWID_RDY 0x00020000 +#define P2P_FLAGS_FORMATION_TARGET_PWID_RDY 0x00040000 +#define P2P_FLAGS_FORMATION_COMPLETE 0x00080000 +#define P2P_FLAGS_MASK_FORMATION 0x000F0000 +#define P2P_FLAGS_DEVICE_DISCOVER_REQ 0x00100000 +#define P2P_FLAGS_DEVICE_DISCOVER_DONE 0x00200000 +#define P2P_FLAGS_DEVICE_INVITATION_WAIT 0x00400000 +#define P2P_FLAGS_DEVICE_SERVICE_DISCOVER_WAIT 0x00800000 +#define P2P_FLAGS_MASK_DEVICE_DISCOVER 0x00F00000 + +#define P2P_FLAGS_DEVICE_FORMATION_REQUEST 0x01000000 + +/* MACRO for flag operation */ +#define SET_FLAGS(_FlagsVar, _BitsToSet) \ + {(_FlagsVar) = ((_FlagsVar) | (_BitsToSet))} + +#define TEST_FLAGS(_FlagsVar, _BitsToCheck) \ + (((_FlagsVar) & (_BitsToCheck)) == (_BitsToCheck)) + +#define CLEAR_FLAGS(_FlagsVar, _BitsToClear) \ + {(_FlagsVar) &= ~(_BitsToClear)} + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_I 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_II 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_III 0 + +#define CFG_DISABLE_WIFI_DIRECT_ENHANCEMENT_IV 0 + +#define CFG_DISABLE_DELAY_PROVISION_DISCOVERY 0 + +#define CFG_CONNECTION_POLICY_2_0 0 + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005 +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +/* 3 --------------- WFA P2P IE and Attributes --------------- */ + +/* P2P 4.1.1 - P2P Information Element */ +typedef struct _IE_P2P_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucP2PAttributes[1]; /* P2P Attributes */ +} __KAL_ATTRIB_PACKED__ IE_P2P_T, *P_IE_P2P_T; + +/* P2P 4.1.1 - General P2P Attribute */ +typedef struct _P2P_ATTRIBUTE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRIBUTE_T, ATTRIBUTE_HDR_T, *P_P2P_ATTRIBUTE_T, *P_ATTRIBUTE_HDR_T; + +/* P2P 4.1.2 - P2P Status Attribute */ +typedef struct _P2P_ATTRI_STATUS_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucStatusCode; /* Status Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_STATUS_T, *P_P2P_ATTRI_STATUS_T; + +/* P2P 4.1.3 - P2P Minor Reason Code Attribute */ +typedef struct _P2P_ATTRI_REASON_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucMinorReasonCode; /* Minor Reason Code */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_REASON_T, *P_P2P_ATTRI_REASON_T; + +/* P2P 4.1.4 - P2P Capability Attribute */ +typedef struct _P2P_ATTRI_CAPABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_8 ucGroupCap; /* Group Capability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CAPABILITY_T, *P_P2P_ATTRI_CAPABILITY_T; + +/* P2P 4.1.5 - P2P Device ID Attribute */ +typedef struct _P2P_ATTRI_DEV_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_ID_T, *P_P2P_ATTRI_DEV_ID_T; + +/* P2P 4.1.6 - Group Owner Intent Attribute */ +typedef struct _P2P_ATTRI_GO_INTENT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOIntent; /* Group Owner Intent */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GO_INTENT_T, *P_P2P_ATTRI_GO_INTENT_T; + +/* P2P 4.1.7 - Configuration Timeout Attribute */ +typedef struct _P2P_ATTRI_CFG_TIMEOUT_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucGOCfgTimeout; /* GO Configuration Timeout */ + UINT_8 ucClientCfgTimeout; /* Client Configuration Timeout */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CFG_TIMEOUT_T, *P_P2P_ATTRI_CFG_TIMEOUT_T; + +/* P2P 4.1.8 - Listen Channel Attribute */ +typedef struct _P2P_ATTRI_LISTEN_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_LISTEN_CHANNEL_T, *P_P2P_ATTRI_LISTEN_CHANNEL_T; + +/* P2P 4.1.9 - P2P Group BSSID Attribute */ +typedef struct _P2P_ATTRI_GROUP_BSSID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBssid[MAC_ADDR_LEN]; /* P2P Group BSSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_BSSID_T, *P_P2P_ATTRI_GROUP_BSSID_T; + +/* P2P 4.1.10 - Extended Listen Timing Attribute */ +typedef struct _P2P_ATTRI_EXT_LISTEN_TIMING_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2AvailPeriod; /* Availability Period */ + UINT_16 u2AvailInterval; /* Availability Interval */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_EXT_LISTEN_TIMING_T, *P_P2P_ATTRI_EXT_LISTEN_TIMING_T; + +/* P2P 4.1.11 - Intended P2P Interface Address Attribute */ +typedef struct _P2P_ATTRI_INTENDED_IF_ADDR_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTENDED_IF_ADDR_T, *P_P2P_ATTRI_INTENDED_IF_ADDR_T; + +/* P2P 4.1.12 - P2P Manageability Attribute */ +typedef struct _P2P_ATTRI_MANAGEABILITY_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucManageability; /* P2P Manageability Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_MANAGEABILITY_T, *P_P2P_ATTRI_MANAGEABILITY_T; + +/* P2P 4.1.13 - Channel List Attribute */ +typedef struct _P2P_ATTRI_CHANNEL_LIST_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 aucChannelEntry[1]; /* Channel Entry List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_CHANNEL_T, *P_P2P_ATTRI_CHANNEL_T; + +typedef struct _CHANNEL_ENTRY_FIELD_T { + UINT_8 ucRegulatoryClass; /* Regulatory Class */ + UINT_8 ucNumberOfChannels; /* Number Of Channels */ + UINT_8 aucChannelList[1]; /* Channel List */ +} __KAL_ATTRIB_PACKED__ CHANNEL_ENTRY_FIELD_T, *P_CHANNEL_ENTRY_FIELD_T; + +/* P2P 4.1.14 - Notice of Absence Attribute */ +typedef struct _P2P_ATTRI_NOA_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucIndex; /* Index */ + UINT_8 ucCTWOppPSParam; /* CTWindow and OppPS Parameters */ + UINT_8 aucNoADesc[1]; /* NoA Descriptor */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_NOA_T, *P_P2P_ATTRI_NOA_T; + +typedef struct _NOA_DESCRIPTOR_T { + UINT_8 ucCountType; /* Count/Type */ + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} __KAL_ATTRIB_PACKED__ NOA_DESCRIPTOR_T, *P_NOA_DESCRIPTOR_T; + +typedef struct _P2P_ATTRI_DEV_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_DEV_INFO_T, *P_P2P_ATTRI_DEV_INFO_T; + +/* WPS 7.1 & 11 WPS TLV Data Format - Device Name */ +typedef struct _DEVICE_NAME_TLV_T { + UINT_16 u2Id; /* WPS Attribute Type */ + UINT_16 u2Length; /* Data Length */ + UINT_8 aucName[32]; /* Device Name */ /* TODO: Fixme */ +} __KAL_ATTRIB_PACKED__ DEVICE_NAME_TLV_T, *P_DEVICE_NAME_TLV_T; + +/* P2P 4.1.16 - P2P Group Info Attribute */ +typedef struct _P2P_CLIENT_INFO_DESC_T { + UINT_8 ucLength; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucIfAddr[MAC_ADDR_LEN]; /* P2P Interface Address */ + UINT_8 ucDeviceCap; /* Device Capability Bitmap */ + UINT_16 u2ConfigMethodsBE; /* Config Method */ + DEVICE_TYPE_T rPrimaryDevTypeBE; /* Primary Device Type */ + UINT_8 ucNumOfSecondaryDevType; /* Number of Secondary Device Types */ + DEVICE_TYPE_T arSecondaryDevTypeListBE[1]; /* Secondary Device Type List */ +} __KAL_ATTRIB_PACKED__ P2P_CLIENT_INFO_DESC_T, *P_P2P_CLIENT_INFO_DESC_T; + +typedef struct _P2P_ATTRI_GROUP_INFO_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + P2P_CLIENT_INFO_DESC_T arClientDesc[1]; /* P2P Client Info Descriptors */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_INFO_T, *P_P2P_ATTRI_GROUP_INFO_T; + +/* P2P 4.1.17 - P2P Group ID Attribute */ +typedef struct _P2P_ATTRI_GROUP_ID_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_GROUP_ID_T, *P_P2P_ATTRI_GROUP_ID_T; + +/* P2P 4.1.18 - P2P Interface Attribute */ +typedef struct _P2P_ATTRI_INTERFACE_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucDevAddr[MAC_ADDR_LEN]; /* P2P Device Address */ + UINT_8 ucIfAddrCount; /* P2P Interface Address Count */ + UINT_8 aucIfAddrList[MAC_ADDR_LEN]; /* P2P Interface Address List */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INTERFACE_T, *P_P2P_ATTRI_INTERFACE_T; + +/* P2P 4.1.19 - Operating Channel Attribute */ +typedef struct _P2P_ATTRI_OPERATING_CHANNEL_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucCountryString[3]; /* Country String */ + UINT_8 ucOperatingClass; /* Operating Class from 802.11 Annex J/P802.11 REVmb 3.0 */ + UINT_8 ucChannelNumber; /* Channel Number */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_OPERATING_CHANNEL_T, *P_P2P_ATTRI_OPERATING_CHANNEL_T; + +/* P2P 4.1.20 - Invitation Flags Attribute */ +typedef struct _P2P_ATTRI_INVITATION_FLAG_T { + UINT_8 ucId; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucInviteFlagsBitmap; /* Invitation Flags Bitmap */ +} __KAL_ATTRIB_PACKED__ P2P_ATTRI_INVITATION_FLAG_T, *P_P2P_ATTRI_INVITATION_FLAG_T; + +/* P2P 4.1.1 - General WSC Attribute */ +typedef struct _WSC_ATTRIBUTE_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRIBUTE_T, *P_WSC_ATTRIBUTE_T; + +/* WSC 1.0 Table 28 */ +typedef struct _WSC_ATTRI_VERSION_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_8 ucVersion; /* Version 1.0 or 1.1 */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_VERSION_T, *P_WSC_ATTRI_VERSION_T; + +typedef struct _WSC_ATTRI_DEVICE_PASSWORD_ID_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2DevPasswordId; /* Device Password ID */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_DEVICE_PASSWORD_ID_T, *P_WSC_ATTRI_DEVICE_PASSWORD_ID_T; + +typedef struct _WSC_ATTRI_CONFIGURATION_METHOD_T { + UINT_16 u2Id; /* Attribute ID */ + UINT_16 u2Length; /* Length */ + UINT_16 u2ConfigMethods; /* Configure Methods */ +} __KAL_ATTRIB_PACKED__ WSC_ATTRI_CONFIGURATION_METHOD_T, *P_WSC_ATTRI_CONFIGURATION_METHOD_T; + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + +/* 3 --------------- WFA P2P Attributes Handler prototype --------------- */ +typedef UINT_32(*PFN_APPEND_ATTRI_FUNC) (P_ADAPTER_T, BOOLEAN, PUINT_16, PUINT_8, UINT_16); + +typedef VOID(*PFN_HANDLE_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T); + +typedef VOID(*PFN_VERIFY_ATTRI_FUNC) (P_SW_RFB_T, P_P2P_ATTRIBUTE_T, PUINT_16); + +typedef UINT_32(*PFN_CALCULATE_VAR_ATTRI_LEN_FUNC) (P_ADAPTER_T, P_STA_RECORD_T); + +typedef struct _APPEND_VAR_ATTRI_ENTRY_T { + UINT_16 u2EstimatedFixedAttriLen; /* For fixed length */ + PFN_CALCULATE_VAR_ATTRI_LEN_FUNC pfnCalculateVariableAttriLen; + PFN_APPEND_ATTRI_FUNC pfnAppendAttri; +} APPEND_VAR_ATTRI_ENTRY_T, *P_APPEND_VAR_ATTRI_ENTRY_T; + +typedef enum _ENUM_CONFIG_METHOD_SEL { + ENUM_CONFIG_METHOD_SEL_AUTO, + ENUM_CONFIG_METHOD_SEL_USER, + ENUM_CONFIG_METHOD_SEL_NUM +} ENUM_CONFIG_METHOD_SEL, *P_ENUM_CONFIG_METHOD_SEL; + +typedef enum _ENUM_P2P_FORMATION_POLICY { + ENUM_P2P_FORMATION_POLICY_AUTO = 0, + ENUM_P2P_FORMATION_POLICY_PASSIVE, /* Device would wait GO NEGO REQ instead of sending it actively. */ + ENUM_P2P_FORMATION_POLICY_NUM +} ENUM_P2P_FORMATION_POLICY, P_ENUM_P2P_FORMATION_POLICY; + +typedef enum _ENUM_P2P_INVITATION_POLICY { + ENUM_P2P_INVITATION_POLICY_USER = 0, + ENUM_P2P_INVITATION_POLICY_ACCEPT_FIRST, + ENUM_P2P_INVITATION_POLICY_DENY_ALL, + ENUM_P2P_INVITATION_POLICY_NUM +} ENUM_P2P_INVITATION_POLICY, P_ENUM_P2P_INVITATION_POLICY; + +/* 3 --------------- Data Structure for P2P Operation --------------- */ +/* 3 Session for CONNECTION SETTINGS of P2P */ +struct _P2P_CONNECTION_SETTINGS_T { + UINT_8 ucDevNameLen; + UINT_8 aucDevName[WPS_ATTRI_MAX_LEN_DEVICE_NAME]; + + DEVICE_TYPE_T rPrimaryDevTypeBE; + + ENUM_P2P_FORMATION_POLICY eFormationPolicy; /* Formation Policy. */ + + /*------------WSC Related Param---------------*/ + UINT_16 u2ConfigMethodsSupport; /* Preferred configure method. + * Some device may not have keypad. + */ + ENUM_CONFIG_METHOD_SEL eConfigMethodSelType; + UINT_16 u2TargetConfigMethod; /* Configure method selected by user or auto. */ + UINT_16 u2LocalConfigMethod; /* Configure method of target. */ + BOOLEAN fgIsPasswordIDRdy; + /*------------WSC Related Param---------------*/ + + UINT_8 ucClientConfigTimeout; + UINT_8 ucGoConfigTimeout; + + UINT_8 ucSecondaryDevTypeCount; +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + DEVICE_TYPE_T arSecondaryDevTypeBE[P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT]; +#endif + +#if 0 + UINT_8 ucRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering + depends on 802.11mb Annex J. */ + +#endif +#else + UINT_8 ucRfChannelListSize; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE + UINT_8 aucChannelEntriesField[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE]; +#endif +#endif + + /* Go Intent */ + UINT_8 ucTieBreaker; + UINT_8 ucGoIntent; + + /* For Device Capability */ + BOOLEAN fgSupportServiceDiscovery; + BOOLEAN fgSupportClientDiscoverability; + BOOLEAN fgSupportConcurrentOperation; + BOOLEAN fgSupportInfraManaged; + BOOLEAN fgSupportInvitationProcedure; + + /* For Group Capability */ + BOOLEAN fgSupportPersistentP2PGroup; + BOOLEAN fgSupportIntraBSSDistribution; + BOOLEAN fgSupportCrossConnection; + BOOLEAN fgSupportPersistentReconnect; + + BOOLEAN fgP2pGroupLimit; + + BOOLEAN fgSupportOppPS; + UINT_16 u2CTWindow; + + BOOLEAN fgIsScanReqIssued; + BOOLEAN fgIsServiceDiscoverIssued; + + /*============ Target Device Connection Settings ============*/ + + /* Discover Target Device Info. */ + BOOLEAN fgIsDevId; + BOOLEAN fgIsDevType; + + /* Encryption mode of Target Device */ + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + /* SSID + * 1. AP Mode, this is the desired SSID user specified. + * 2. Client Mode, this is the target SSID to be connected to. + */ + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + + /* Operating channel requested. */ + UINT_8 ucOperatingChnl; + ENUM_BAND_T eBand; + + /* Linten channel requested. */ + UINT_8 ucListenChnl; + + /* For device discover address/type. */ + UINT_8 aucTargetDevAddr[MAC_ADDR_LEN]; /* P2P Device Address, for P2P Device Discovery & P2P Connection. */ + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_DEVICE_DESC_T prTargetP2pDesc; +#endif + + UINT_8 ucLastStatus; /* P2P FSM would append status attribute according to this field. */ + +#if !CFG_DISABLE_DELAY_PROVISION_DISCOVERY + UINT_8 ucLastDialogToken; + UINT_8 aucIndicateDevAddr[MAC_ADDR_LEN]; +#endif + +#if 0 + UINT_8 ucTargetRfChannelListCount; +#if P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT + UINT_8 aucTargetChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_COUNT]; /* Channel Numbering + depends on 802.11mb Annex J. */ +#endif +#endif + +}; + +typedef struct _NOA_TIMING_T { + BOOLEAN fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} NOA_TIMING_T, *P_NOA_TIMING_T; + +typedef enum _ENUM_P2P_IOCTL_T { + P2P_IOCTL_IDLE = 0, + P2P_IOCTL_DEV_DISCOVER, + P2P_IOCTL_INVITATION_REQ, + P2P_IOCTL_SERV_DISCOVER, + P2P_IOCTL_WAITING, + P2P_IOCTL_NUM +} ENUM_P2P_IOCTL_T; + +/*---------------- Service Discovery Related -------------------*/ +typedef enum _ENUM_SERVICE_TX_TYPE_T { + ENUM_SERVICE_TX_TYPE_BY_DA, + ENUM_SERVICE_TX_TYPE_BY_CHNL, + ENUM_SERVICE_TX_TYPE_NUM +} ENUM_SERVICE_TX_TYPE_T; + +typedef struct _SERVICE_DISCOVERY_FRAME_DATA_T { + QUE_ENTRY_T rQueueEntry; + P_MSDU_INFO_T prSDFrame; + ENUM_SERVICE_TX_TYPE_T eServiceType; + UINT_8 ucSeqNum; + union { + + UINT_8 ucChannelNum; + UINT_8 aucPeerAddr[MAC_ADDR_LEN]; + } uTypeData; + BOOLEAN fgIsTxDoneIndicate; +} SERVICE_DISCOVERY_FRAME_DATA_T, *P_SERVICE_DISCOVERY_FRAME_DATA_T; + +struct _P2P_FSM_INFO_T_DEPRECATED { + /* P2P FSM State */ + ENUM_P2P_STATE_T eCurrentState; + + /* Channel */ + BOOLEAN fgIsChannelRequested; + + ENUM_P2P_STATE_T ePreviousState; + + ENUM_P2P_STATE_T eReturnState; /* Return state after current activity finished or abort. */ + + UINT_8 aucTargetIfAddr[PARAM_MAC_ADDR_LEN]; + P_BSS_DESC_T prTargetBss; /* BSS of target P2P Device. For Connection/Service Discovery */ + + P_STA_RECORD_T prTargetStaRec; + + BOOLEAN fgIsRsponseProbe; /* Indicate if P2P FSM can response probe request frame. */ + + /* Sequence number of requested message. */ + UINT_8 ucSeqNumOfReqMsg; /* Used for SAA FSM request message. */ + + /* Channel Privilege */ + UINT_8 ucSeqNumOfChReq; /* Used for Channel Request message. */ + + UINT_8 ucSeqNumOfScnMsg; /* Used for SCAN FSM request message. */ + UINT_8 ucSeqNumOfCancelMsg; + + UINT_8 ucDialogToken; + UINT_8 ucRxDialogToken; + + /* Timer */ + TIMER_T rDeviceDiscoverTimer; /* For device discovery time of each discovery request from user. */ + TIMER_T rOperationListenTimer; /* For Find phase under operational state. */ + TIMER_T rFSMTimer; /* A timer used for Action frame timeout usage. */ + + TIMER_T rRejoinTimer; /* A timer used for Action frame timeout usage. */ + + /* Flag to indicate Provisioning */ + BOOLEAN fgIsConnectionRequested; + + /* Current IOCTL. */ + ENUM_P2P_IOCTL_T eP2pIOCTL; + + UINT_8 ucAvailableAuthTypes; /* Used for AUTH_MODE_AUTO_SWITCH */ + + /*--------SERVICE DISCOVERY--------*/ + QUE_T rQueueGASRx; /* Input Request/Response. */ + QUE_T rQueueGASTx; /* Output Response. */ + P_SERVICE_DISCOVERY_FRAME_DATA_T prSDRequest; + UINT_8 ucVersionNum; /* GAS packet sequence number for...Action Frame? */ + UINT_8 ucGlobalSeqNum; /* Sequence Number of RX SD packet. */ + /*--------Service DISCOVERY--------*/ + + /*--------DEVICE DISCOVERY---------*/ + UINT_8 aucTargetGroupID[PARAM_MAC_ADDR_LEN]; + UINT_16 u2TargetGroupSsidLen; + UINT_8 aucTargetSsid[32]; + UINT_8 aucSearchingP2pDevice[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDLToken; + /*----------------------------------*/ + + /* Indicating Peer Status. */ + UINT_32 u4Flags; + + /*Indicating current running mode. */ + BOOLEAN fgIsApMode; + + /*------------INVITATION------------*/ + ENUM_P2P_INVITATION_POLICY eInvitationRspPolicy; + /*----------------------------------*/ + +}; + +struct _P2P_SPECIFIC_BSS_INFO_T { + /* For GO(AP) Mode - Compose TIM IE */ + UINT_16 u2SmallestAID; + UINT_16 u2LargestAID; + UINT_8 ucBitmapCtrl; + /* UINT_8 aucPartialVirtualBitmap[MAX_LEN_TIM_PARTIAL_BMP]; */ + + /* For GC/GO OppPS */ + BOOLEAN fgEnableOppPS; + UINT_16 u2CTWindow; + + /* For GC/GO NOA */ + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + NOA_TIMING_T arNoATiming[P2P_MAXIMUM_NOA_COUNT]; + + BOOLEAN fgIsNoaAttrExisted; + + /* For P2P Device */ + UINT_8 ucRegClass; /* Regulatory Class for channel. */ + UINT_8 ucListenChannel; /* Linten Channel only on channels 1, 6 and 11 in the 2.4 GHz. */ + + UINT_8 ucPreferredChannel; /* Operating Channel, should be one of channel list + in p2p connection settings. */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_BAND_T eRfBand; + + /* Extended Listen Timing. */ + UINT_16 u2AvailabilityPeriod; + UINT_16 u2AvailabilityInterval; + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + UINT_16 u2IELenForBCN; + UINT_8 aucBeaconIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +/* UINT_16 u2IELenForProbeRsp; */ +/* UINT_8 aucProbeRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; */ + + UINT_16 u2IELenForAssocRsp; + UINT_8 aucAssocRspIECache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE + WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + +#else + UINT_16 u2AttributeLen; + UINT_8 aucAttributesCache[P2P_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; + + UINT_16 u2WscAttributeLen; + UINT_8 aucWscAttributesCache[WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE]; +#endif + UINT_8 aucGroupID[MAC_ADDR_LEN]; + UINT_16 u2GroupSsidLen; + UINT_8 aucGroupSsid[ELEM_MAX_LEN_SSID]; + + PARAM_CUSTOM_NOA_PARAM_STRUCT_T rNoaParam; + PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T rOppPsParam; + + UINT_16 u2WpaIeLen; + UINT_8 aucWpaIeBuffer[ELEM_HDR_LEN + ELEM_MAX_LEN_WPA]; +}; + +typedef struct _MSG_P2P_DEVICE_DISCOVER_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4DevDiscoverTime; /* 0: Infinite, 1~X: in unit of MS. */ + BOOLEAN fgIsSpecificType; +#if CFG_ENABLE_WIFI_DIRECT + P2P_DEVICE_TYPE_T rTargetDeviceType; +#endif + UINT_8 aucTargetDeviceID[MAC_ADDR_LEN]; +} MSG_P2P_DEVICE_DISCOVER_T, *P_MSG_P2P_DEVICE_DISCOVER_T; + +typedef struct _MSG_P2P_INVITATION_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; /* Target Device ID to be invited. */ +} MSG_P2P_INVITATION_REQUEST_T, *P_MSG_P2P_INVITATION_REQUEST_T; + +typedef struct _MSG_P2P_FUNCTION_SWITCH_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + BOOLEAN fgIsFuncOn; +} MSG_P2P_FUNCTION_SWITCH_T, *P_MSG_P2P_FUNCTION_SWITCH_T; + +typedef struct _MSG_P2P_SERVICE_DISCOVERY_REQUEST_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 aucDeviceID[MAC_ADDR_LEN]; + BOOLEAN fgNeedTxDoneIndicate; + UINT_8 ucSeqNum; +} MSG_P2P_SERVICE_DISCOVERY_REQUEST_T, *P_MSG_P2P_SERVICE_DISCOVERY_REQUEST_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define p2pChangeMediaState(_prAdapter, _eNewMediaState) \ +do { \ + (_prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState = (_eNewMediaState));\ + wfdChangeMediaState((_prAdapter), NETWORK_TYPE_P2P_INDEX, (_eNewMediaState)); \ +} while (0) + +#define ATTRI_ID(_fp) (((P_P2P_ATTRIBUTE_T) _fp)->ucId) +#define ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[0]) | \ + ((UINT_16) ((PUINT_8)&((P_P2P_ATTRIBUTE_T) _fp)->u2Length)[1] << 8)) + +#define ATTRI_SIZE(_fp) (P2P_ATTRI_HDR_LEN + ATTRI_LEN(_fp)) + +#define P2P_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += ATTRI_SIZE(_pucAttriBuf))) + +#define P2P_IE(_fp) ((P_IE_P2P_T) _fp) + +#define WSC_ATTRI_ID(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Id)[1])) + +#define WSC_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WSC_ATTRIBUTE_T) _fp)->u2Length)[1])) + +#define WSC_ATTRI_SIZE(_fp) (WSC_ATTRI_HDR_LEN + WSC_ATTRI_LEN(_fp)) + +#define WSC_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WSC_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WSC_ATTRI_SIZE(_pucAttriBuf))) + +#define WSC_IE(_fp) ((P_IE_P2P_T) _fp) + +#define WFD_ATTRI_ID(_fp) (((P_WFD_ATTRIBUTE_T) _fp)->ucElemID) + +#define WFD_ATTRI_LEN(_fp) \ + (((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[0] << 8) | \ + ((UINT_16) ((PUINT_8)&((P_WFD_ATTRIBUTE_T) _fp)->u2Length)[1])) + +#define WFD_ATTRI_SIZE(_fp) (WFD_ATTRI_HDR_LEN + WFD_ATTRI_LEN(_fp)) + +#define WFD_ATTRI_FOR_EACH(_pucAttriBuf, _u2AttriBufLen, _u2Offset) \ + for ((_u2Offset) = 0; ((_u2Offset) < (_u2AttriBufLen)); \ + (_u2Offset) += WFD_ATTRI_SIZE(_pucAttriBuf), ((_pucAttriBuf) += WFD_ATTRI_SIZE(_pucAttriBuf))) + +#if DBG +#define ASSERT_BREAK(_exp) \ + { \ + if (!(_exp)) { \ + ASSERT(FALSE); \ + break; \ + } \ + } + +#else +#define ASSERT_BREAK(_exp) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*======P2P State======*/ +VOID +p2pStateInit_LISTEN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prSP2pBssInfo, IN UINT_8 ucListenChannel); + +VOID p2pStateAbort_LISTEN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); + +VOID p2pStateAbort_SEARCH_SCAN(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtenstion); + +VOID p2pStateAbort_GO_OPERATION(IN P_ADAPTER_T prAdapter); + +VOID p2pStateAbort_GC_OPERATION(IN P_ADAPTER_T prAdapter); + +VOID +p2pStateInit_CONFIGURATION(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecBssInfo); + +VOID p2pStateAbort_CONFIGURATION(IN P_ADAPTER_T prAdapter); + +VOID p2pStateInit_JOIN(IN P_ADAPTER_T prAdapter); + +VOID p2pStateAbort_JOIN(IN P_ADAPTER_T prAdapter); + +/*====== P2P Functions ======*/ + +VOID p2pFuncInitGO(IN P_ADAPTER_T prAdapter); + +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +VOID +p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW); + +VOID p2pFuncRunEventProvisioningComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +WLAN_STATUS p2pFuncSetGroupID(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucGroupID, IN PUINT_8 pucSsid, IN UINT_8 ucSsidLen); + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityReqFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); + +WLAN_STATUS +p2pFuncSendDeviceDiscoverabilityRspFrame(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDestAddr[], IN UINT_8 ucDialogToken); + +UINT_8 p2pFuncGetVersionNumOfSD(IN P_ADAPTER_T prAdapter); + +/*====== P2P FSM ======*/ +VOID p2pFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDeviceDiscoveryRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventDeviceDiscoveryAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventRxGroupNegotiationReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationResponseTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventGroupNegotiationConfirmTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventProvisionDiscoveryResponseTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +WLAN_STATUS +p2pFsmRunEventInvitationRequestTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +p2pFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if 1 +#endif + +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/* //////////////////////////////////////////////////////////////////////// */ +/*======Mail Box Event Message=====*/ + +VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventConnectionTrigger(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventP2PFunctionSwitch(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventConnectionPause(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +p2pIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState, IN UINT_8 aucTargetAddr[]); + +VOID p2pUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); + +/*======Mail Box Event Message=====*/ + +VOID p2pFsmInit(IN P_ADAPTER_T prAdapter); + +VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID p2pFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStartGO(IN P_ADAPTER_T prAdapter); + +VOID p2pAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID p2pFsmRunEventIOReqTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventSearchPeriodTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param); + +VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG u4Param); + +VOID p2pFsmRunEventRejoinTimeout(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Parm); + +/*=============== P2P Function Related ================*/ + +/*=============== P2P Function Related ================*/ + +#if CFG_TEST_WIFI_DIRECT_GO +VOID p2pTest(IN P_ADAPTER_T prAdapter); +#endif /* CFG_TEST_WIFI_DIRECT_GO */ + +VOID p2pGenerateP2P_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID p2pGenerateP2P_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID p2pGenerateP2P_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID +p2pGenerateP2P_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pCalculateP2P_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pCalculateP2P_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pGenerateWSC_IEForProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID +p2pGenerateWSC_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_16 p2pCalculateWSC_IELenForProbeReq(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +UINT_32 +p2pCalculateWSC_IELenForProbeResp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriStatus(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriCapability(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriGoIntent(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriCfgTimeout(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriGroupBssid(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForBeacon(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForProbeReq(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceIDForDeviceDiscoveryReq(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriListenChannel(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriIntendP2pIfAddr(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriChannelList(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenChannelList(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriNoA(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriDeviceInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenDeviceInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriGroupInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 p2pCalculateAttriLenGroupInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +p2pAppendAttriP2pGroupID(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriOperatingChannel(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriInvitationFlag(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +VOID +p2pGenerateWscIE(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); + +UINT_32 +p2pAppendAttriWSCConfigMethod(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCVersion(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCGONegReqDevPasswordId(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pAppendAttriWSCGONegRspDevPasswordId(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +WLAN_STATUS +p2pGetWscAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +WLAN_STATUS +p2pGetAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS p2pSendProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +BOOLEAN p2pFsmRunEventRxProbeRequestFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc); + +WLAN_STATUS p2pRxPublicActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS p2pRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxGroupNegotiationRspFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID p2pFsmRunEventRxGroupNegotiationCfmFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#if 0 /* frog */ +BOOLEAN scanMatchFilterOfP2P(IN P_SW_RFB_T prSWRfb, IN PP_BSS_DESC_T pprBssDesc); +#endif /* frog */ + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam); + +VOID p2pFuncCompleteIOCTL(IN P_ADAPTER_T prAdapter, IN WLAN_STATUS rWlanStatus); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#ifndef _lint +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID p2pDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(IE_P2P_T) == (2 + 4 + 1)); /* all UINT_8 */ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRIBUTE_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_STATUS_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_REASON_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CAPABILITY_T) == (3 + 2)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_ID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GO_INTENT_T) == (3 + 1)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CFG_TIMEOUT_T) == (3 + 2)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_LISTEN_CHANNEL_T) == (3 + 5)); +#endif + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_BSSID_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_EXT_LISTEN_TIMING_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTENDED_IF_ADDR_T) == (3 + 6)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_MANAGEABILITY_T) == (3 + 1)); + + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_CHANNEL_T) == (3 + 4)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(CHANNEL_ENTRY_FIELD_T) == 3); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_NOA_T) == (3 + 3)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(NOA_DESCRIPTOR_T) == 13); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_TYPE_T) == 8); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_DEV_INFO_T) == (3 + 6 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(DEVICE_NAME_TLV_T) == (4 + 32)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_CLIENT_INFO_DESC_T) == (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_INFO_T) == (3 + (1 + 6 + 6 + 1 + 2 + 8 + 1 + 8))); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_GROUP_ID_T) == (3 + 38)); + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_INTERFACE_T) == (3 + 13)); +#if CID52_53_54 + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#else + DATA_STRUCT_INSPECTING_ASSERT(sizeof(P2P_ATTRI_OPERATING_CHANNEL_T) == (3 + 5)); +#endif + +} +#endif /* _lint */ + +#endif /* _P2P_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h new file mode 100644 index 0000000000000..1ac1770debcab --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_func.h @@ -0,0 +1,155 @@ +#ifndef _P2P_FUNC_H +#define _P2P_FUNC_H + +#define P2P_EXT_LISTEN_TIME_MS 600 +#define P2P_OFF_CHNL_TX_DEFAULT_TIME_MS 1000 + +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID +p2pFuncStartGO(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucSsidBuf, + IN UINT_8 ucSsidLen, + IN UINT_8 ucChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN BOOLEAN fgIsPureAP); + +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN P_RF_CHANNEL_INFO_T prRfChannelInfo); + +BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo); + +VOID +p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb); + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie); + +WLAN_STATUS +p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, + IN PUINT_8 pucNewBcnHdr, IN UINT_32 u4NewHdrLen, IN PUINT_8 pucNewBcnBody, IN UINT_32 u4NewBodyLen); + +BOOLEAN +p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings); + +BOOLEAN p2pFuncParseCheckForP2PInfoElem(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType); + +BOOLEAN p2pFuncValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pFuncParseBeaconContent(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen); + +P_BSS_DESC_T +p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo); + +VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID +p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter); + +VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter); + +VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo); + +BOOLEAN +p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen); + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu); + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +#endif +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); + +VOID +p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize); + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +VOID +p2pFuncDissolve(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +P_IE_HDR_T +p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore); + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID); + +WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, + IN ENUM_PARAM_MEDIA_STATE_T eConnectionState); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h new file mode 100644 index 0000000000000..efb75855695f9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_ie.h @@ -0,0 +1,156 @@ +#ifndef _P2P_IE_H +#define _P2P_IE_H + +#if CFG_SUPPORT_WFD + +#define ELEM_MAX_LEN_WFD 62 /* TODO: Move to appropriate place */ + +/*---------------- WFD Data Element Definitions ----------------*/ +/* WFD 4.1.1 - WFD IE format */ +#define WFD_OUI_TYPE_LEN 4 +#define WFD_IE_OUI_HDR (ELEM_HDR_LEN + WFD_OUI_TYPE_LEN) /* == OFFSET_OF(IE_P2P_T, + aucP2PAttributes[0]) */ + +/* WFD 4.1.1 - General WFD Attribute */ +#define WFD_ATTRI_HDR_LEN 3 /* ID(1 octet) + Length(2 octets) */ + +/* WFD Attribute Code */ +#define WFD_ATTRI_ID_DEV_INFO 0 +#define WFD_ATTRI_ID_ASSOC_BSSID 1 +#define WFD_ATTRI_ID_COUPLED_SINK_INFO 6 +#define WFD_ATTRI_ID_EXT_CAPABILITY 7 +#define WFD_ATTRI_ID_SESSION_INFO 9 +#define WFD_ATTRI_ID_ALTER_MAC_ADDRESS 10 + +/* Maximum Length of WFD Attributes */ +#define WFD_ATTRI_MAX_LEN_DEV_INFO 6 /* 0 */ +#define WFD_ATTRI_MAX_LEN_ASSOC_BSSID 6 /* 1 */ +#define WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO 7 /* 6 */ +#define WFD_ATTRI_MAX_LEN_EXT_CAPABILITY 2 /* 7 */ +#define WFD_ATTRI_MAX_LEN_SESSION_INFO 0 /* 9 */ /* 24 * #Clients */ +#define WFD_ATTRI_MAX_LEN_ALTER_MAC_ADDRESS 6 /* 10 */ + +/* WFD 1.10 5.1.1 */ +typedef struct _IE_WFD_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 aucWFDAttributes[1]; /* WFD Subelement */ +} __KAL_ATTRIB_PACKED__ IE_WFD_T, *P_IE_WFD_T; + +typedef struct _WFD_ATTRIBUTE_T { + UINT_8 ucElemID; /* Subelement ID */ + UINT_16 u2Length; /* Length */ + UINT_8 aucBody[1]; /* Body field */ +} __KAL_ATTRIB_PACKED__ WFD_ATTRIBUTE_T, *P_WFD_ATTRIBUTE_T; + +typedef struct _WFD_DEVICE_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdDevInfo; + UINT_16 u2SessionMgmtCtrlPort; + UINT_16 u2WfdDevMaxSpeed; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_IE_T, *P_WFD_DEVICE_INFORMATION_IE_T; + +typedef struct _WFD_ASSOCIATED_BSSID_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_ASSOCIATED_BSSID_IE_T, *P_WFD_ASSOCIATED_BSSID_IE_T; + +typedef struct _WFD_COUPLE_SINK_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_COUPLE_SINK_INFORMATION_IE_T, *P_WFD_COUPLE_SINK_INFORMATION_IE_T; + +typedef struct _WFD_EXTENDED_CAPABILITY_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + UINT_16 u2WfdExtCapabilityBp; +} __KAL_ATTRIB_PACKED__ WFD_EXTENDED_CAPABILITY_IE_T, *P_WFD_EXTENDED_CAPABILITY_IE_T; + +typedef struct _WFD_SESSION_INFORMATION_IE_T { + UINT_8 ucElemID; + UINT_16 u2Length; + PUINT_8 pucWfdDevInfoDesc[1]; +} __KAL_ATTRIB_PACKED__ WFD_SESSION_INFORMATION_IE_T, *P_WFD_SESSION_INFORMATION_IE_T; + +typedef struct _WFD_DEVICE_INFORMATION_DESCRIPTOR_T { + UINT_8 ucLength; + UINT_8 aucDevAddr[MAC_ADDR_LEN]; + UINT_8 aucAssocBssid[MAC_ADDR_LEN]; + UINT_16 u2WfdDevInfo; + UINT_16 u2WfdDevMaxSpeed; + UINT_8 ucCoupleSinkStatusBp; + UINT_8 aucCoupleSinkMac[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WFD_DEVICE_INFORMATION_DESCRIPTOR_T, *P_WFD_DEVICE_INFORMATION_DESCRIPTOR_T; + +#endif + +UINT_32 +p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#if CFG_SUPPORT_WFD + +UINT_32 +wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_32 +wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize); + +UINT_32 +wfdFuncCalculateWfdIELenForProbeResp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForProbeResp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 +wfdFuncCalculateWfdIELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +VOID wfdFuncGenerateWfdIEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec); + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h new file mode 100644 index 0000000000000..32bc14c109591 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm.h @@ -0,0 +1,74 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm.h#1 +*/ + +/*! \file "rlm.h" + \brief +*/ + +#ifndef _P2P_RLM_H +#define _P2P_RLM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); + +VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter); + +VOID +rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize); + +UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum); + +BOOLEAN +rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel); + +ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h new file mode 100644 index 0000000000000..5b6e756f48dd4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_rlm_obss.h @@ -0,0 +1,64 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_rlm_obss.h#1 +*/ + +/*! \file "rlm_obss.h" + \brief +*/ + +#ifndef _P2P_RLM_OBSS_H +#define _P2P_RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h new file mode 100644 index 0000000000000..8db6aa5c31e0c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_scan.h @@ -0,0 +1,81 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/mgmt/p2p_scan.h#1 +*/ + +/*! \file "scan.h" + \brief + +*/ + +#ifndef _P2P_SCAN_H +#define _P2P_SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc); + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound); + +P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum); + +BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID +scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); + +VOID scanRemoveAllP2pBssDesc(P_ADAPTER_T prAdapter); + +VOID scanRemoveP2pBssDesc(P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +P_BSS_DESC_T +scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h new file mode 100644 index 0000000000000..8f0c4c1564a85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/p2p_state.h @@ -0,0 +1,43 @@ +#ifndef _P2P_STATE_H +#define _P2P_STATE_H + +BOOLEAN +p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState); + +VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +VOID +p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState); + +VOID +p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc); + +VOID +p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h new file mode 100644 index 0000000000000..c80430ae4eb54 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/privacy.h @@ -0,0 +1,230 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/privacy.h#1 +*/ + +/*! \file privacy.h + \brief This file contains the function declaration for privacy.c. +*/ + +/* +** Log: privacy.h + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 25 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * For support the WHQL test, do the remove key code refine. + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the cmd return type + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for auth mode and encryption status setting from build connection command + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for wapi + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the tx done callback handle function + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function declaration for mac header privacy bit setting + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the structure for parsing the EAPoL frame + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the class error function parameter + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security function declaration + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the ap selection structure + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +#ifndef _PRIVACY_H +#define _PRIVACY_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_KEY_NUM 4 +#define WEP_40_LEN 5 +#define WEP_104_LEN 13 +#define LEGACY_KEY_MAX_LEN 16 +#define CCMP_KEY_LEN 16 +#define TKIP_KEY_LEN 32 +#define MAX_KEY_LEN 32 +#define MIC_RX_KEY_OFFSET 16 +#define MIC_TX_KEY_OFFSET 24 +#define MIC_KEY_LEN 8 + +#define WEP_KEY_ID_FIELD BITS(0, 29) +#define KEY_ID_FIELD BITS(0, 7) + +#define IS_TRANSMIT_KEY BIT(31) +#define IS_UNICAST_KEY BIT(30) +#define IS_AUTHENTICATOR BIT(28) + +#define CIPHER_SUITE_NONE 0 +#define CIPHER_SUITE_WEP40 1 +#define CIPHER_SUITE_TKIP 2 +#define CIPHER_SUITE_TKIP_WO_MIC 3 +#define CIPHER_SUITE_CCMP 4 +#define CIPHER_SUITE_WEP104 5 +#define CIPHER_SUITE_BIP 6 +#define CIPHER_SUITE_WEP128 7 +#define CIPHER_SUITE_WPI 8 + +#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ +#define WPA_KEY_INFO_MIC BIT(8) +#define WPA_KEY_INFO_SECURE BIT(9) + +#define MASK_2ND_EAPOL (WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _IEEE_802_1X_HDR { + UINT_8 ucVersion; + UINT_8 ucType; + UINT_16 u2Length; + /* followed by length octets of data */ +} IEEE_802_1X_HDR, *P_IEEE_802_1X_HDR; + +typedef struct _EAPOL_KEY { + UINT_8 ucType; + /* Note: key_info, key_length, and key_data_length are unaligned */ + UINT_8 aucKeyInfo[2]; /* big endian */ + UINT_8 aucKeyLength[2]; /* big endian */ + UINT_8 aucReplayCounter[8]; + UINT_8 aucKeyNonce[16]; + UINT_8 aucKeyIv[16]; + UINT_8 aucKeyRsc[8]; + UINT_8 aucKeyId[8]; /* Reserved in IEEE 802.11i/RSN */ + UINT_8 aucKeyMic[16]; + UINT_8 aucKeyDataLength[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +} EAPOL_KEY, *P_EAPOL_KEY; + +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; + +#if 0 +/* WPA2 PMKID cache structure */ +typedef struct _PMKID_ENTRY_T { + PARAM_BSSID_INFO_T rBssidInfo; + BOOLEAN fgPmkidExist; +} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID secInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIdx); + +VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPort); + +BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec); + +BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); + +VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags); + +BOOLEAN +secProcessEAPOL(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen); + +VOID +secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T pMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus); + +BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec); + +VOID secClearPmkid(IN P_ADAPTER_T prAdapter); + +BOOLEAN secRsnKeyHandshakeEnabled(IN P_ADAPTER_T prAdapter); + +BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRIVACY_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h new file mode 100644 index 0000000000000..123dbebdacaf2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rate.h @@ -0,0 +1,93 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rate.h#1 +*/ + +/*! \file rate.h + \brief This file contains the rate utility function of + IEEE 802.11 family for MediaTek 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: rate.h + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * +*/ + +#ifndef _RATE_H +#define _RATE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in rate.c */ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate); + +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen); + +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex); + +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RATE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h new file mode 100644 index 0000000000000..1af3841ecec25 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm.h @@ -0,0 +1,396 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm.h#2 +*/ + +/*! \file "rlm.h" + \brief +*/ + +/* +** Log: rlm.h + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 13 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Use SCO of BSS_INFO to replace user-defined setting variables + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 18 2010 cm.chang + * [WCXRP00000114] [MT6620 Wi-Fi] [Driver] Fix compiling warning in Linux about RLM network index checking + * Enum member cannot be used as compiling option decision in Linux + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX HT GF compiling option + * + * 06 02 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Roll back to remove CFG_SUPPORT_BCM_TEST. + * + * 06 01 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Update BCM Test and RW configuration. + * + * 05 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some compiling options to control 11n functions + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 17 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * MT6620 does not support L-SIG TXOP + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Move default value of HT capability to rlm.h + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * + * Modify the prototype of rlmRecAssocRspHtInfo() + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add several function prototypes for HT operation + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +#ifndef _RLM_H +#define _RLM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ELEM_EXT_CAP_DEFAULT_VAL \ + (ELEM_EXT_CAP_20_40_COEXIST_SUPPORT /*| ELEM_EXT_CAP_PSMP_CAP*/) + +#if CFG_SUPPORT_RX_STBC +#define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_1_SS +#else +#define FIELD_HT_CAP_INFO_RX_STBC HT_CAP_INFO_RX_STBC_NO_SUPPORTED +#endif + +#if CFG_SUPPORT_RX_SGI +#define FIELD_HT_CAP_INFO_SGI_20M HT_CAP_INFO_SHORT_GI_20M +#define FIELD_HT_CAP_INFO_SGI_40M HT_CAP_INFO_SHORT_GI_40M +#else +#define FIELD_HT_CAP_INFO_SGI_20M 0 +#define FIELD_HT_CAP_INFO_SGI_40M 0 +#endif + +#if CFG_SUPPORT_RX_HT_GF +#define FIELD_HT_CAP_INFO_HT_GF HT_CAP_INFO_HT_GF +#else +#define FIELD_HT_CAP_INFO_HT_GF 0 +#endif + +#define HT_CAP_INFO_DEFAULT_VAL \ + (HT_CAP_INFO_SUP_CHNL_WIDTH | FIELD_HT_CAP_INFO_HT_GF | \ + FIELD_HT_CAP_INFO_SGI_20M | FIELD_HT_CAP_INFO_SGI_40M | \ + FIELD_HT_CAP_INFO_RX_STBC | HT_CAP_INFO_DSSS_CCK_IN_40M) + +#define AMPDU_PARAM_DEFAULT_VAL \ + (AMPDU_PARAM_MAX_AMPDU_LEN_64K | AMPDU_PARAM_MSS_NO_RESTRICIT) + +#define SUP_MCS_TX_DEFAULT_VAL \ + SUP_MCS_TX_SET_DEFINED /* TX defined and TX/RX equal (TBD) */ + +#if CFG_SUPPORT_MFB +#define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_BOTH +#else +#define FIELD_HT_EXT_CAP_MFB HT_EXT_CAP_MCS_FEEDBACK_NO_FB +#endif + +#if CFG_SUPPORT_RX_RDG +#define FIELD_HT_EXT_CAP_RDR HT_EXT_CAP_RD_RESPONDER +#else +#define FIELD_HT_EXT_CAP_RDR 0 +#endif + +#if CFG_SUPPORT_MFB || CFG_SUPPORT_RX_RDG +#define FIELD_HT_EXT_CAP_HTC HT_EXT_CAP_HTC_SUPPORT +#else +#define FIELD_HT_EXT_CAP_HTC 0 +#endif + +#define HT_EXT_CAP_DEFAULT_VAL \ + (HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE | \ + FIELD_HT_EXT_CAP_MFB | FIELD_HT_EXT_CAP_HTC | \ + FIELD_HT_EXT_CAP_RDR) + +#define TX_BEAMFORMING_CAP_DEFAULT_VAL 0 +#define ASEL_CAP_DEFAULT_VAL 0 + +/* Define bandwidth from user setting */ +#define CONFIG_BW_20_40M 0 +#define CONFIG_BW_20M 1 /* 20MHz only */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* It is used for RLM module to judge if specific network is valid + * Note: Ad-hoc mode of AIS is not included now. (TBD) + */ +#define RLM_NET_PARAM_VALID(_prBssInfo) \ + (IS_BSS_ACTIVE(_prBssInfo) && \ + ((_prBssInfo)->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_ACCESS_POINT || \ + (_prBssInfo)->eCurrentOPMode == OP_MODE_IBSS || \ + RLM_NET_IS_BOW(_prBssInfo)) \ + ) + +#define RLM_NET_IS_11N(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11N) +#define RLM_NET_IS_11GN(_prBssInfo) \ + ((_prBssInfo)->ucPhyTypeSet & PHY_TYPE_SET_802_11GN) + +/* This macro is used to sweep all 3 networks */ +#define RLM_NET_FOR_EACH(_ucNetIdx) \ + for ((_ucNetIdx) = 0; \ + (_ucNetIdx) < NETWORK_TYPE_INDEX_NUM; \ + (_ucNetIdx)++) + +/* This macro is used to sweep all networks excluding BOW */ +#if CFG_ENABLE_BT_OVER_WIFI + /* Note: value of enum NETWORK_TYPE_BOW_INDEX is validated in + * rlmStuctureCheck(). + */ +#define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) \ + for ((_ucNetIdx) = 0; \ + (_ucNetIdx) < NETWORK_TYPE_BOW_INDEX; \ + (_ucNetIdx)++) + +#define RLM_NET_IS_BOW(_prBssInfo) \ + ((_prBssInfo)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + +#else +#define RLM_NET_FOR_EACH_NO_BOW(_ucNetIdx) RLM_NET_FOR_EACH(_ucNetIdx) +#define RLM_NET_IS_BOW(_prBssInfo) (FALSE) + +#endif /* end of CFG_ENABLE_BT_OVER_WIFI */ + +/* The bandwidth modes are not used anymore. They represent if AP + * can use 20/40 bandwidth, not all modes. (20110411) + */ +#define RLM_AP_IS_BW_40_ALLOWED(_prAdapter, _prBssInfo) \ + (((_prBssInfo)->eBand == BAND_2G4 && \ + (_prAdapter)->rWifiVar.rConnSettings.uc2G4BandwidthMode \ + == CONFIG_BW_20_40M) || \ + ((_prBssInfo)->eBand == BAND_5G && \ + (_prAdapter)->rWifiVar.rConnSettings.uc5GBandwidthMode \ + == CONFIG_BW_20_40M)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID rlmFsmEventInit(P_ADAPTER_T prAdapter); + +VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter); + +VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateHtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmRspGenerateErpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo); + +VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +UINT32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, + UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf); + +UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme); + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE); +#endif + +VOID +rlmTxRateEnhanceConfig( + P_ADAPTER_T prAdapter + ); + +VOID +rlmCmd( + P_GLUE_INFO_T prGlueInfo, + UINT_8 *prInBuf, + UINT_32 u4InBufLen + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#ifndef _lint +static inline VOID rlmDataTypeCheck(VOID) +{ +#if CFG_ENABLE_BT_OVER_WIFI + DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_AIS_INDEX < NETWORK_TYPE_BOW_INDEX); + +#if CFG_ENABLE_WIFI_DIRECT + DATA_STRUCT_INSPECTING_ASSERT(NETWORK_TYPE_P2P_INDEX < NETWORK_TYPE_BOW_INDEX); +#endif +#endif + +} +#endif /* _lint */ + +#endif /* _RLM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h new file mode 100644 index 0000000000000..65e907041a28b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_domain.h @@ -0,0 +1,557 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_domain.h#1 +*/ + +/*! \file "rlm_domain.h" + \brief +*/ + +/* +** Log: rlm_domain.h + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Provide legal channel function based on domain + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 01 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide query function about full channel list. + * + * Dec 1 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Declare public rDomainInfo + * +** +*/ + +#ifndef _RLM_DOMAIN_H +#define _RLM_DOMAIN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SUBBAND_NUM 6 +#define MAX_SUBBAND_NUM_5G 8 + +#define COUNTRY_CODE_NULL ((UINT_16)0x0) + +/* ISO/IEC 3166-1 two-character country codes */ + +#define COUNTRY_CODE_AD (((UINT_16) 'A' << 8) | (UINT_16) 'D') /* Andorra */ +#define COUNTRY_CODE_AE (((UINT_16) 'A' << 8) | (UINT_16) 'E') /* UAE */ +#define COUNTRY_CODE_AF (((UINT_16) 'A' << 8) | (UINT_16) 'F') /* Afghanistan */ +#define COUNTRY_CODE_AG (((UINT_16) 'A' << 8) | (UINT_16) 'G') /* Antigua & Barbuda */ +#define COUNTRY_CODE_AI (((UINT_16) 'A' << 8) | (UINT_16) 'I') /* Anguilla */ +#define COUNTRY_CODE_AL (((UINT_16) 'A' << 8) | (UINT_16) 'L') /* Albania */ +#define COUNTRY_CODE_AM (((UINT_16) 'A' << 8) | (UINT_16) 'M') /* Armenia */ +#define COUNTRY_CODE_AN (((UINT_16) 'A' << 8) | (UINT_16) 'N') /* Netherlands Antilles */ +#define COUNTRY_CODE_AO (((UINT_16) 'A' << 8) | (UINT_16) 'O') /* Angola */ +#define COUNTRY_CODE_AR (((UINT_16) 'A' << 8) | (UINT_16) 'R') /* Argentina */ +#define COUNTRY_CODE_AS (((UINT_16) 'A' << 8) | (UINT_16) 'S') /* American Samoa (USA) */ +#define COUNTRY_CODE_AT (((UINT_16) 'A' << 8) | (UINT_16) 'T') /* Austria */ +#define COUNTRY_CODE_AU (((UINT_16) 'A' << 8) | (UINT_16) 'U') /* Australia */ +#define COUNTRY_CODE_AW (((UINT_16) 'A' << 8) | (UINT_16) 'W') /* Aruba */ +#define COUNTRY_CODE_AZ (((UINT_16) 'A' << 8) | (UINT_16) 'Z') /* Azerbaijan */ +#define COUNTRY_CODE_BA (((UINT_16) 'B' << 8) | (UINT_16) 'A') /* Bosnia and Herzegovina */ +#define COUNTRY_CODE_BB (((UINT_16) 'B' << 8) | (UINT_16) 'B') /* Barbados */ +#define COUNTRY_CODE_BD (((UINT_16) 'B' << 8) | (UINT_16) 'D') /* Bangladesh */ +#define COUNTRY_CODE_BE (((UINT_16) 'B' << 8) | (UINT_16) 'E') /* Belgium */ +#define COUNTRY_CODE_BF (((UINT_16) 'B' << 8) | (UINT_16) 'F') /* Burkina Faso */ +#define COUNTRY_CODE_BG (((UINT_16) 'B' << 8) | (UINT_16) 'G') /* Bulgaria */ +#define COUNTRY_CODE_BH (((UINT_16) 'B' << 8) | (UINT_16) 'H') /* Bahrain */ +#define COUNTRY_CODE_BI (((UINT_16) 'B' << 8) | (UINT_16) 'I') /* Burundi */ +#define COUNTRY_CODE_BJ (((UINT_16) 'B' << 8) | (UINT_16) 'J') /* Benin */ +#define COUNTRY_CODE_BM (((UINT_16) 'B' << 8) | (UINT_16) 'M') /* Bermuda */ +#define COUNTRY_CODE_BN (((UINT_16) 'B' << 8) | (UINT_16) 'N') /* Brunei */ +#define COUNTRY_CODE_BO (((UINT_16) 'B' << 8) | (UINT_16) 'O') /* Bolivia */ +#define COUNTRY_CODE_BR (((UINT_16) 'B' << 8) | (UINT_16) 'R') /* Brazil */ +#define COUNTRY_CODE_BS (((UINT_16) 'B' << 8) | (UINT_16) 'S') /* Bahamas */ +#define COUNTRY_CODE_BT (((UINT_16) 'B' << 8) | (UINT_16) 'T') /* Bhutan */ +#define COUNTRY_CODE_BW (((UINT_16) 'B' << 8) | (UINT_16) 'W') /* Botswana */ +#define COUNTRY_CODE_BY (((UINT_16) 'B' << 8) | (UINT_16) 'Y') /* Belarus */ +#define COUNTRY_CODE_BZ (((UINT_16) 'B' << 8) | (UINT_16) 'Z') /* Belize */ +#define COUNTRY_CODE_CA (((UINT_16) 'C' << 8) | (UINT_16) 'A') /* Canada */ +#define COUNTRY_CODE_CD (((UINT_16) 'C' << 8) | (UINT_16) 'D') /* Congo. Democratic Republic of the */ +#define COUNTRY_CODE_CF (((UINT_16) 'C' << 8) | (UINT_16) 'F') /* Central African Republic */ +#define COUNTRY_CODE_CG (((UINT_16) 'C' << 8) | (UINT_16) 'G') /* Congo. Republic of the */ +#define COUNTRY_CODE_CH (((UINT_16) 'C' << 8) | (UINT_16) 'H') /* Switzerland */ +#define COUNTRY_CODE_CI (((UINT_16) 'C' << 8) | (UINT_16) 'I') /* Cote d'lvoire */ +#define COUNTRY_CODE_CK (((UINT_16) 'C' << 8) | (UINT_16) 'K') /* Cook Island */ +#define COUNTRY_CODE_CL (((UINT_16) 'C' << 8) | (UINT_16) 'L') /* Chile */ +#define COUNTRY_CODE_CM (((UINT_16) 'C' << 8) | (UINT_16) 'M') /* Cameroon */ +#define COUNTRY_CODE_CN (((UINT_16) 'C' << 8) | (UINT_16) 'N') /* China */ +#define COUNTRY_CODE_CO (((UINT_16) 'C' << 8) | (UINT_16) 'O') /* Columbia */ +#define COUNTRY_CODE_CR (((UINT_16) 'C' << 8) | (UINT_16) 'R') /* Costa Rica */ +#define COUNTRY_CODE_CU (((UINT_16) 'C' << 8) | (UINT_16) 'U') /* Cuba */ +#define COUNTRY_CODE_CV (((UINT_16) 'C' << 8) | (UINT_16) 'V') /* Cape Verde */ +#define COUNTRY_CODE_CX (((UINT_16) 'C' << 8) | (UINT_16) 'X') /* "Christmas Island(Australia) */ +#define COUNTRY_CODE_CY (((UINT_16) 'C' << 8) | (UINT_16) 'Y') /* Cyprus */ +#define COUNTRY_CODE_CZ (((UINT_16) 'C' << 8) | (UINT_16) 'Z') /* Czech */ +#define COUNTRY_CODE_DE (((UINT_16) 'D' << 8) | (UINT_16) 'E') /* Germany */ +#define COUNTRY_CODE_DJ (((UINT_16) 'D' << 8) | (UINT_16) 'J') /* Djibouti */ +#define COUNTRY_CODE_DK (((UINT_16) 'D' << 8) | (UINT_16) 'K') /* Denmark */ +#define COUNTRY_CODE_DM (((UINT_16) 'D' << 8) | (UINT_16) 'M') /* Dominica */ +#define COUNTRY_CODE_DO (((UINT_16) 'D' << 8) | (UINT_16) 'O') /* Dominican Republic */ +#define COUNTRY_CODE_DZ (((UINT_16) 'D' << 8) | (UINT_16) 'Z') /* Algeria */ +#define COUNTRY_CODE_EC (((UINT_16) 'E' << 8) | (UINT_16) 'C') /* Ecuador */ +#define COUNTRY_CODE_EE (((UINT_16) 'E' << 8) | (UINT_16) 'E') /* Estonia */ +#define COUNTRY_CODE_EG (((UINT_16) 'E' << 8) | (UINT_16) 'G') /* Egypt */ +#define COUNTRY_CODE_EH (((UINT_16) 'E' << 8) | (UINT_16) 'H') /* Western Sahara (Morocco) */ +#define COUNTRY_CODE_ER (((UINT_16) 'E' << 8) | (UINT_16) 'R') /* Eritrea */ +#define COUNTRY_CODE_ES (((UINT_16) 'E' << 8) | (UINT_16) 'S') /* Spain */ +#define COUNTRY_CODE_ET (((UINT_16) 'E' << 8) | (UINT_16) 'T') /* Ethiopia */ +#define COUNTRY_CODE_EU (((UINT_16) 'E' << 8) | (UINT_16) 'U') /* Europe */ +#define COUNTRY_CODE_FI (((UINT_16) 'F' << 8) | (UINT_16) 'I') /* Finland */ +#define COUNTRY_CODE_FJ (((UINT_16) 'F' << 8) | (UINT_16) 'J') /* Fiji */ +#define COUNTRY_CODE_FK (((UINT_16) 'F' << 8) | (UINT_16) 'K') /* Falkland Island */ +#define COUNTRY_CODE_FM (((UINT_16) 'F' << 8) | (UINT_16) 'M') /* Micronesia */ +#define COUNTRY_CODE_FO (((UINT_16) 'F' << 8) | (UINT_16) 'O') /* Faroe Island */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* France */ +#define COUNTRY_CODE_FR (((UINT_16) 'F' << 8) | (UINT_16) 'R') /* Wallis and Futuna (France) */ +#define COUNTRY_CODE_GA (((UINT_16) 'G' << 8) | (UINT_16) 'A') /* Gabon */ +#define COUNTRY_CODE_GB (((UINT_16) 'G' << 8) | (UINT_16) 'B') /* United Kingdom */ +#define COUNTRY_CODE_GD (((UINT_16) 'G' << 8) | (UINT_16) 'D') /* Grenada */ +#define COUNTRY_CODE_GE (((UINT_16) 'G' << 8) | (UINT_16) 'E') /* Georgia */ +#define COUNTRY_CODE_GF (((UINT_16) 'G' << 8) | (UINT_16) 'F') /* French Guiana */ +#define COUNTRY_CODE_GG (((UINT_16) 'G' << 8) | (UINT_16) 'G') /* Guernsey */ +#define COUNTRY_CODE_GH (((UINT_16) 'G' << 8) | (UINT_16) 'H') /* Ghana */ +#define COUNTRY_CODE_GI (((UINT_16) 'G' << 8) | (UINT_16) 'I') /* Gibraltar */ +#define COUNTRY_CODE_GM (((UINT_16) 'G' << 8) | (UINT_16) 'M') /* Gambia */ +#define COUNTRY_CODE_GN (((UINT_16) 'G' << 8) | (UINT_16) 'N') /* Guinea */ +#define COUNTRY_CODE_GP (((UINT_16) 'G' << 8) | (UINT_16) 'P') /* Guadeloupe */ +#define COUNTRY_CODE_GQ (((UINT_16) 'G' << 8) | (UINT_16) 'Q') /* Equatorial Guinea */ +#define COUNTRY_CODE_GR (((UINT_16) 'G' << 8) | (UINT_16) 'R') /* Greece */ +#define COUNTRY_CODE_GT (((UINT_16) 'G' << 8) | (UINT_16) 'T') /* Guatemala */ +#define COUNTRY_CODE_GU (((UINT_16) 'G' << 8) | (UINT_16) 'U') /* Guam */ +#define COUNTRY_CODE_GW (((UINT_16) 'G' << 8) | (UINT_16) 'W') /* Guinea-Bissau */ +#define COUNTRY_CODE_GY (((UINT_16) 'G' << 8) | (UINT_16) 'Y') /* Guyana */ +#define COUNTRY_CODE_HK (((UINT_16) 'H' << 8) | (UINT_16) 'K') /* Hong Kong */ +#define COUNTRY_CODE_HN (((UINT_16) 'H' << 8) | (UINT_16) 'N') /* Honduras */ +#define COUNTRY_CODE_HR (((UINT_16) 'H' << 8) | (UINT_16) 'R') /* Croatia */ +#define COUNTRY_CODE_HT (((UINT_16) 'H' << 8) | (UINT_16) 'T') /* Haiti */ +#define COUNTRY_CODE_HU (((UINT_16) 'H' << 8) | (UINT_16) 'U') /* Hungary */ +#define COUNTRY_CODE_ID (((UINT_16) 'I' << 8) | (UINT_16) 'D') /* Indonesia */ +#define COUNTRY_CODE_IE (((UINT_16) 'I' << 8) | (UINT_16) 'E') /* Ireland */ +#define COUNTRY_CODE_IL (((UINT_16) 'I' << 8) | (UINT_16) 'L') /* Israel */ +#define COUNTRY_CODE_IM (((UINT_16) 'I' << 8) | (UINT_16) 'M') /* Isle of Man */ +#define COUNTRY_CODE_IN (((UINT_16) 'I' << 8) | (UINT_16) 'N') /* India */ +#define COUNTRY_CODE_IQ (((UINT_16) 'I' << 8) | (UINT_16) 'Q') /* Iraq */ +#define COUNTRY_CODE_IR (((UINT_16) 'I' << 8) | (UINT_16) 'R') /* Iran */ +#define COUNTRY_CODE_IS (((UINT_16) 'I' << 8) | (UINT_16) 'S') /* Iceland */ +#define COUNTRY_CODE_IT (((UINT_16) 'I' << 8) | (UINT_16) 'T') /* Italy */ +#define COUNTRY_CODE_JE (((UINT_16) 'J' << 8) | (UINT_16) 'E') /* Jersey */ +#define COUNTRY_CODE_JM (((UINT_16) 'J' << 8) | (UINT_16) 'M') /* Jameica */ +#define COUNTRY_CODE_JO (((UINT_16) 'J' << 8) | (UINT_16) 'O') /* Jordan */ +#define COUNTRY_CODE_JP (((UINT_16) 'J' << 8) | (UINT_16) 'P') /* Japan */ +#define COUNTRY_CODE_KE (((UINT_16) 'K' << 8) | (UINT_16) 'E') /* Kenya */ +#define COUNTRY_CODE_KG (((UINT_16) 'K' << 8) | (UINT_16) 'G') /* Kyrgyzstan */ +#define COUNTRY_CODE_KH (((UINT_16) 'K' << 8) | (UINT_16) 'H') /* Cambodia */ +#define COUNTRY_CODE_KI (((UINT_16) 'K' << 8) | (UINT_16) 'I') /* Kiribati */ +#define COUNTRY_CODE_KM (((UINT_16) 'K' << 8) | (UINT_16) 'M') /* Comoros */ +#define COUNTRY_CODE_KN (((UINT_16) 'K' << 8) | (UINT_16) 'N') /* Saint Kitts and Nevis */ +#define COUNTRY_CODE_KP (((UINT_16) 'K' << 8) | (UINT_16) 'P') /* North Korea */ +#define COUNTRY_CODE_KR (((UINT_16) 'K' << 8) | (UINT_16) 'R') /* South Korea */ +#define COUNTRY_CODE_KW (((UINT_16) 'K' << 8) | (UINT_16) 'W') /* Kuwait */ +#define COUNTRY_CODE_KY (((UINT_16) 'K' << 8) | (UINT_16) 'Y') /* Cayman Islands */ +#define COUNTRY_CODE_KZ (((UINT_16) 'K' << 8) | (UINT_16) 'Z') /* Kazakhstan */ +#define COUNTRY_CODE_LA (((UINT_16) 'L' << 8) | (UINT_16) 'A') /* Laos */ +#define COUNTRY_CODE_LB (((UINT_16) 'L' << 8) | (UINT_16) 'B') /* Lebanon */ +#define COUNTRY_CODE_LC (((UINT_16) 'L' << 8) | (UINT_16) 'C') /* Saint Lucia */ +#define COUNTRY_CODE_LI (((UINT_16) 'L' << 8) | (UINT_16) 'I') /* Liechtenstein */ +#define COUNTRY_CODE_LK (((UINT_16) 'L' << 8) | (UINT_16) 'K') /* Sri Lanka */ +#define COUNTRY_CODE_LR (((UINT_16) 'L' << 8) | (UINT_16) 'R') /* Liberia */ +#define COUNTRY_CODE_LS (((UINT_16) 'L' << 8) | (UINT_16) 'S') /* Lesotho */ +#define COUNTRY_CODE_LT (((UINT_16) 'L' << 8) | (UINT_16) 'T') /* Lithuania */ +#define COUNTRY_CODE_LU (((UINT_16) 'L' << 8) | (UINT_16) 'U') /* Luxemburg */ +#define COUNTRY_CODE_LV (((UINT_16) 'L' << 8) | (UINT_16) 'V') /* Latvia */ +#define COUNTRY_CODE_LY (((UINT_16) 'L' << 8) | (UINT_16) 'Y') /* Libya */ +#define COUNTRY_CODE_MA (((UINT_16) 'M' << 8) | (UINT_16) 'A') /* Morocco */ +#define COUNTRY_CODE_MC (((UINT_16) 'M' << 8) | (UINT_16) 'C') /* Monaco */ +#define COUNTRY_CODE_MD (((UINT_16) 'M' << 8) | (UINT_16) 'D') /* Moldova */ +#define COUNTRY_CODE_ME (((UINT_16) 'M' << 8) | (UINT_16) 'E') /* Montenegro */ +#define COUNTRY_CODE_MF (((UINT_16) 'M' << 8) | (UINT_16) 'F') /* Saint Martin / Sint Marteen + (Added on window's list) */ +#define COUNTRY_CODE_MG (((UINT_16) 'M' << 8) | (UINT_16) 'G') /* Madagascar */ +#define COUNTRY_CODE_MH (((UINT_16) 'M' << 8) | (UINT_16) 'H') /* Marshall Islands */ +#define COUNTRY_CODE_MK (((UINT_16) 'M' << 8) | (UINT_16) 'K') /* Macedonia */ +#define COUNTRY_CODE_ML (((UINT_16) 'M' << 8) | (UINT_16) 'L') /* Mali */ +#define COUNTRY_CODE_MM (((UINT_16) 'M' << 8) | (UINT_16) 'M') /* Myanmar */ +#define COUNTRY_CODE_MN (((UINT_16) 'M' << 8) | (UINT_16) 'N') /* Mongolia */ +#define COUNTRY_CODE_MO (((UINT_16) 'M' << 8) | (UINT_16) 'O') /* Macao */ +#define COUNTRY_CODE_MP (((UINT_16) 'M' << 8) | (UINT_16) 'P') /* Northern Mariana Islands (Rota Island. + Saipan and Tinian Island) */ +#define COUNTRY_CODE_MQ (((UINT_16) 'M' << 8) | (UINT_16) 'Q') /* Martinique (France) */ +#define COUNTRY_CODE_MR (((UINT_16) 'M' << 8) | (UINT_16) 'R') /* Mauritania */ +#define COUNTRY_CODE_MS (((UINT_16) 'M' << 8) | (UINT_16) 'S') /* Montserrat (UK) */ +#define COUNTRY_CODE_MT (((UINT_16) 'M' << 8) | (UINT_16) 'T') /* Malta */ +#define COUNTRY_CODE_MU (((UINT_16) 'M' << 8) | (UINT_16) 'U') /* Mauritius */ +#define COUNTRY_CODE_MV (((UINT_16) 'M' << 8) | (UINT_16) 'V') /* Maldives */ +#define COUNTRY_CODE_MW (((UINT_16) 'M' << 8) | (UINT_16) 'W') /* Malawi */ +#define COUNTRY_CODE_MX (((UINT_16) 'M' << 8) | (UINT_16) 'X') /* Mexico */ +#define COUNTRY_CODE_MY (((UINT_16) 'M' << 8) | (UINT_16) 'Y') /* Malaysia */ +#define COUNTRY_CODE_MZ (((UINT_16) 'M' << 8) | (UINT_16) 'Z') /* Mozambique */ +#define COUNTRY_CODE_NA (((UINT_16) 'N' << 8) | (UINT_16) 'A') /* Namibia */ +#define COUNTRY_CODE_NC (((UINT_16) 'N' << 8) | (UINT_16) 'C') /* New Caledonia */ +#define COUNTRY_CODE_NE (((UINT_16) 'N' << 8) | (UINT_16) 'E') /* Niger */ +#define COUNTRY_CODE_NF (((UINT_16) 'N' << 8) | (UINT_16) 'F') /* Norfolk Island */ +#define COUNTRY_CODE_NG (((UINT_16) 'N' << 8) | (UINT_16) 'G') /* Nigeria */ +#define COUNTRY_CODE_NI (((UINT_16) 'N' << 8) | (UINT_16) 'I') /* Nicaragua */ +#define COUNTRY_CODE_NL (((UINT_16) 'N' << 8) | (UINT_16) 'L') /* Netherlands */ +#define COUNTRY_CODE_NO (((UINT_16) 'N' << 8) | (UINT_16) 'O') /* Norway */ +#define COUNTRY_CODE_NP (((UINT_16) 'N' << 8) | (UINT_16) 'P') /* Nepal */ +#define COUNTRY_CODE_NR (((UINT_16) 'N' << 8) | (UINT_16) 'R') /* Nauru */ +#define COUNTRY_CODE_NU (((UINT_16) 'N' << 8) | (UINT_16) 'U') /* Niue */ +#define COUNTRY_CODE_NZ (((UINT_16) 'N' << 8) | (UINT_16) 'Z') /* New Zealand */ +#define COUNTRY_CODE_OM (((UINT_16) 'O' << 8) | (UINT_16) 'M') /* Oman */ +#define COUNTRY_CODE_PA (((UINT_16) 'P' << 8) | (UINT_16) 'A') /* Panama */ +#define COUNTRY_CODE_PE (((UINT_16) 'P' << 8) | (UINT_16) 'E') /* Peru */ +#define COUNTRY_CODE_PF (((UINT_16) 'P' << 8) | (UINT_16) 'F') /* "French Polynesia */ +#define COUNTRY_CODE_PG (((UINT_16) 'P' << 8) | (UINT_16) 'G') /* Papua New Guinea */ +#define COUNTRY_CODE_PH (((UINT_16) 'P' << 8) | (UINT_16) 'H') /* Philippines */ +#define COUNTRY_CODE_PK (((UINT_16) 'P' << 8) | (UINT_16) 'K') /* Pakistan */ +#define COUNTRY_CODE_PL (((UINT_16) 'P' << 8) | (UINT_16) 'L') /* Poland */ +#define COUNTRY_CODE_PM (((UINT_16) 'P' << 8) | (UINT_16) 'M') /* Saint Pierre and Miquelon */ +#define COUNTRY_CODE_PN (((UINT_16) 'P' << 8) | (UINT_16) 'N') /* Pitcairn Islands */ +#define COUNTRY_CODE_PR (((UINT_16) 'P' << 8) | (UINT_16) 'R') /* Puerto Rico (USA) */ +#define COUNTRY_CODE_PS (((UINT_16) 'P' << 8) | (UINT_16) 'S') /* Palestinian Authority */ +#define COUNTRY_CODE_PT (((UINT_16) 'P' << 8) | (UINT_16) 'T') /* Portugal */ +#define COUNTRY_CODE_PW (((UINT_16) 'P' << 8) | (UINT_16) 'W') /* Palau */ +#define COUNTRY_CODE_PY (((UINT_16) 'P' << 8) | (UINT_16) 'Y') /* Paraguay */ +#define COUNTRY_CODE_QA (((UINT_16) 'Q' << 8) | (UINT_16) 'A') /* Qatar */ +#define COUNTRY_CODE_RE (((UINT_16) 'R' << 8) | (UINT_16) 'E') /* Reunion (France) */ +#define COUNTRY_CODE_RKS (((UINT_16) 'R' << 8) | (UINT_16) 'K') /* Kosvo (Added on window's list) */ +#define COUNTRY_CODE_RO (((UINT_16) 'R' << 8) | (UINT_16) 'O') /* Romania */ +#define COUNTRY_CODE_RS (((UINT_16) 'R' << 8) | (UINT_16) 'S') /* Serbia */ +#define COUNTRY_CODE_RU (((UINT_16) 'R' << 8) | (UINT_16) 'U') /* Russia */ +#define COUNTRY_CODE_RW (((UINT_16) 'R' << 8) | (UINT_16) 'W') /* Rwanda */ +#define COUNTRY_CODE_SA (((UINT_16) 'S' << 8) | (UINT_16) 'A') /* Saudi Arabia */ +#define COUNTRY_CODE_SB (((UINT_16) 'S' << 8) | (UINT_16) 'B') /* Solomon Islands */ +#define COUNTRY_CODE_SC (((UINT_16) 'S' << 8) | (UINT_16) 'C') /* Seychelles */ +#define COUNTRY_CODE_SD (((UINT_16) 'S' << 8) | (UINT_16) 'D') /* Sudan */ +#define COUNTRY_CODE_SE (((UINT_16) 'S' << 8) | (UINT_16) 'E') /* Sweden */ +#define COUNTRY_CODE_SG (((UINT_16) 'S' << 8) | (UINT_16) 'G') /* Singapole */ +#define COUNTRY_CODE_SI (((UINT_16) 'S' << 8) | (UINT_16) 'I') /* Slovenia */ +#define COUNTRY_CODE_SK (((UINT_16) 'S' << 8) | (UINT_16) 'K') /* Slovakia */ +#define COUNTRY_CODE_SL (((UINT_16) 'S' << 8) | (UINT_16) 'L') /* Sierra Leone */ +#define COUNTRY_CODE_SM (((UINT_16) 'S' << 8) | (UINT_16) 'M') /* San Marino */ +#define COUNTRY_CODE_SN (((UINT_16) 'S' << 8) | (UINT_16) 'N') /* Senegal */ +#define COUNTRY_CODE_SO (((UINT_16) 'S' << 8) | (UINT_16) 'O') /* Somalia */ +#define COUNTRY_CODE_SR (((UINT_16) 'S' << 8) | (UINT_16) 'R') /* Suriname */ +#define COUNTRY_CODE_SS (((UINT_16) 'S' << 8) | (UINT_16) 'S') /* South_Sudan */ +#define COUNTRY_CODE_ST (((UINT_16) 'S' << 8) | (UINT_16) 'T') /* Sao Tome and Principe */ +#define COUNTRY_CODE_SV (((UINT_16) 'S' << 8) | (UINT_16) 'V') /* El Salvador */ +#define COUNTRY_CODE_SY (((UINT_16) 'S' << 8) | (UINT_16) 'Y') /* Syria */ +#define COUNTRY_CODE_SZ (((UINT_16) 'S' << 8) | (UINT_16) 'Z') /* Swaziland */ +#define COUNTRY_CODE_TC (((UINT_16) 'T' << 8) | (UINT_16) 'C') /* Turks and Caicos Islands (UK) */ +#define COUNTRY_CODE_TD (((UINT_16) 'T' << 8) | (UINT_16) 'D') /* Chad */ +#define COUNTRY_CODE_TF (((UINT_16) 'T' << 8) | (UINT_16) 'F') /* French Southern and Antarctic Lands */ +#define COUNTRY_CODE_TG (((UINT_16) 'T' << 8) | (UINT_16) 'G') /* Togo */ +#define COUNTRY_CODE_TH (((UINT_16) 'T' << 8) | (UINT_16) 'H') /* Thailand */ +#define COUNTRY_CODE_TJ (((UINT_16) 'T' << 8) | (UINT_16) 'J') /* Tajikistan */ +#define COUNTRY_CODE_TL (((UINT_16) 'T' << 8) | (UINT_16) 'L') /* East Timor */ +#define COUNTRY_CODE_TM (((UINT_16) 'T' << 8) | (UINT_16) 'M') /* Turkmenistan */ +#define COUNTRY_CODE_TN (((UINT_16) 'T' << 8) | (UINT_16) 'N') /* Tunisia */ +#define COUNTRY_CODE_TO (((UINT_16) 'T' << 8) | (UINT_16) 'O') /* Tonga */ +#define COUNTRY_CODE_TR (((UINT_16) 'T' << 8) | (UINT_16) 'R') /* Turkey */ +#define COUNTRY_CODE_TT (((UINT_16) 'T' << 8) | (UINT_16) 'T') /* Trinidad and Tobago */ +#define COUNTRY_CODE_TV (((UINT_16) 'T' << 8) | (UINT_16) 'V') /* Tuvalu */ +#define COUNTRY_CODE_TW (((UINT_16) 'T' << 8) | (UINT_16) 'W') /* Taiwan */ +#define COUNTRY_CODE_TZ (((UINT_16) 'T' << 8) | (UINT_16) 'Z') /* Tanzania */ +#define COUNTRY_CODE_UA (((UINT_16) 'U' << 8) | (UINT_16) 'A') /* Ukraine */ +#define COUNTRY_CODE_UG (((UINT_16) 'U' << 8) | (UINT_16) 'G') /* Ugnada */ +#define COUNTRY_CODE_US (((UINT_16) 'U' << 8) | (UINT_16) 'S') /* US */ +#define COUNTRY_CODE_UY (((UINT_16) 'U' << 8) | (UINT_16) 'Y') /* Uruguay */ +#define COUNTRY_CODE_UZ (((UINT_16) 'U' << 8) | (UINT_16) 'Z') /* Uzbekistan */ +#define COUNTRY_CODE_VA (((UINT_16) 'V' << 8) | (UINT_16) 'A') /* Vatican (Holy See) */ +#define COUNTRY_CODE_VC (((UINT_16) 'V' << 8) | (UINT_16) 'C') /* Saint Vincent and the Grenadines */ +#define COUNTRY_CODE_VE (((UINT_16) 'V' << 8) | (UINT_16) 'E') /* Venezuela */ +#define COUNTRY_CODE_VG (((UINT_16) 'V' << 8) | (UINT_16) 'G') /* British Virgin Islands */ +#define COUNTRY_CODE_VI (((UINT_16) 'V' << 8) | (UINT_16) 'I') /* US Virgin Islands */ +#define COUNTRY_CODE_VN (((UINT_16) 'V' << 8) | (UINT_16) 'N') /* Vietnam */ +#define COUNTRY_CODE_VU (((UINT_16) 'V' << 8) | (UINT_16) 'U') /* Vanuatu */ +#define COUNTRY_CODE_WS (((UINT_16) 'W' << 8) | (UINT_16) 'S') /* Samoa */ +#define COUNTRY_CODE_YE (((UINT_16) 'Y' << 8) | (UINT_16) 'E') /* Yemen */ +#define COUNTRY_CODE_YT (((UINT_16) 'Y' << 8) | (UINT_16) 'T') /* Mayotte (France) */ +#define COUNTRY_CODE_ZA (((UINT_16) 'Z' << 8) | (UINT_16) 'A') /* South Africa */ +#define COUNTRY_CODE_ZM (((UINT_16) 'Z' << 8) | (UINT_16) 'M') /* Zambia */ +#define COUNTRY_CODE_ZW (((UINT_16) 'Z' << 8) | (UINT_16) 'W') /* Zimbabwe */ + +#define COUNTRY_CODE_DF (((UINT_16) 'D' << 8) | (UINT_16) 'F') /* Default country domain */ +#define COUNTRY_CODE_UDF (((UINT_16) 'U' << 8) | (UINT_16) 'D') /* User defined supported channel list + and passive scan channel list */ + +#define COUNTRY_CODE_FF (((UINT_16) 'F' << 8) | (UINT_16) 'F') /* enable open for all channel for Certification */ +#define COUNTRY_CODE_FE (((UINT_16) 'F' << 8) | (UINT_16) 'E') /* disable open for all channel for Certification */ + +/* dot11RegDomainsSupportValue */ +#define MIB_REG_DOMAIN_FCC 0x10 /* FCC (US) */ +#define MIB_REG_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define MIB_REG_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define MIB_REG_DOMAIN_SPAIN 0x31 /* Spain */ +#define MIB_REG_DOMAIN_FRANCE 0x32 /* France */ +#define MIB_REG_DOMAIN_JAPAN 0x40 /* MPHPT (Japan) */ +#define MIB_REG_DOMAIN_OTHER 0x00 /* other */ + +/*2.4G*/ +#define BAND_2G4_LOWER_BOUND 1 +#define BAND_2G4_UPPER_BOUND 14 +/*5G SubBand FCC spec*/ +#define UNII1_LOWER_BOUND 36 +#define UNII1_UPPER_BOUND 48 +#define UNII2A_LOWER_BOUND 52 +#define UNII2A_UPPER_BOUND 64 +#define UNII2C_LOWER_BOUND 100 +#define UNII2C_UPPER_BOUND 144 +#define UNII3_LOWER_BOUND 149 +#define UNII3_UPPER_BOUND 173 + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +#define POWER_LIMIT_TABLE_NULL 0xFFFF +#define MAX_TX_POWER 63 +#define MIN_TX_POWER -64 +#define MAX_CMD_SUPPORT_CHANNEL_NUM 64 + +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef enum _ENUM_POWER_LIMIT_T { + PWR_LIMIT_CCK, + PWR_LIMIT_20M, + PWR_LIMIT_40M, + PWR_LIMIT_80M, + PWR_LIMIT_160M, + PWR_LIMIT_NUM +} ENUM_POWER_LIMIT_T, *P_ENUM_POWER_LIMIT_T; + +#endif + +typedef enum _ENUM_POWER_LIMIT_SUBBAND_T { + POWER_LIMIT_2G4, + POWER_LIMIT_UNII1, + POWER_LIMIT_UNII2A, + POWER_LIMIT_UNII2C, + POWER_LIMIT_UNII3, + POWER_LIMIT_SUBAND_NUM +} ENUM_POWER_LIMIT_SUBBAND_T, *P_ENUM_POWER_LIMIT_SUBBAND_T; + +/* Define channel offset in unit of 5MHz bandwidth */ +typedef enum _ENUM_CHNL_SPAN_T { + CHNL_SPAN_5 = 1, + CHNL_SPAN_10 = 2, + CHNL_SPAN_20 = 4, + CHNL_SPAN_40 = 8 +} ENUM_CHNL_SPAN_T, *P_ENUM_CHNL_SPAN_T; + +/* Define BSS operating bandwidth */ +typedef enum _ENUM_CHNL_BW_T { + CHNL_BW_20, + CHNL_BW_20_40, + CHNL_BW_10, + CHNL_BW_5 +} ENUM_CHNL_BW_T, *P_ENUM_CHNL_BW_T; + +/* In all bands, the first channel will be SCA and the second channel is SCB, + * then iteratively. + * Note the final channel will not be SCA. + */ +typedef struct _DOMAIN_SUBBAND_INFO { + /* Note1: regulation class depends on operation bandwidth and RF band. + * For example: 2.4GHz, 1~13, 20MHz ==> regulation class = 81 + * 2.4GHz, 1~13, SCA ==> regulation class = 83 + * 2.4GHz, 1~13, SCB ==> regulation class = 84 + * Note2: TX power limit is not specified here because path loss is unknown + */ + UINT_8 ucRegClass; /* Regulation class for 20MHz */ + UINT_8 ucBand; /* Type: ENUM_BAND_T */ + UINT_8 ucChannelSpan; /* Type: ENUM_CHNL_SPAN_T */ + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 fgDfs; /* Type: BOOLEAN */ +} DOMAIN_SUBBAND_INFO, *P_DOMAIN_SUBBAND_INFO; + +/* Use it as all available channel list for STA */ +typedef struct _DOMAIN_INFO_ENTRY { + PUINT_16 pu2CountryGroup; + UINT_32 u4CountryNum; + + /* If different attributes, put them into different rSubBands. + * For example, DFS shall be used or not. + */ + DOMAIN_SUBBAND_INFO rSubBand[MAX_SUBBAND_NUM]; +} DOMAIN_INFO_ENTRY, *P_DOMAIN_INFO_ENTRY; + + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +typedef struct _CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CHANNEL_POWER_LIMIT, *P_CHANNEL_POWER_LIMIT; + +typedef struct _COUNTRY_CHANNEL_POWER_LIMIT { + UINT_8 aucCountryCode[2]; + UINT_8 ucCountryFlag; + UINT_8 ucChannelNum; + UINT_8 aucReserved[4]; + CHANNEL_POWER_LIMIT rChannelPowerLimit[80]; +} COUNTRY_CHANNEL_POWER_LIMIT, *P_COUNTRY_CHANNEL_POWER_LIMIT; + +#define CHANNEL_PWR_LIMIT(_channel, _pwrLimit_cck, _pwrLimit_bw20, \ + _pwrLimit_bw40, _pwrLimit_bw80, _pwrLimit_bw160, _ucFlag) \ + { \ + .ucCentralCh = (_channel), \ + .cPwrLimitCCK = (_pwrLimit_cck), \ + .cPwrLimit20 = (_pwrLimit_bw20), \ + .cPwrLimit40 = (_pwrLimit_bw40), \ + .cPwrLimit80 = (_pwrLimit_bw80), \ + .cPwrLimit160 = (_pwrLimit_bw160), \ + .ucFlag = (_ucFlag), \ + .aucReserved = {0} \ +} + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_DEFAULT { + UINT_8 aucCountryCode[2]; + /* 0: ch 1 ~14 , 1: ch 36 ~48, 2: ch 52 ~64, 3: ch 100 ~144, 4: ch 149 ~165 */ + INT_8 aucPwrLimitSubBand[POWER_LIMIT_SUBAND_NUM]; + /* bit0: cPwrLimit2G4, bit1: cPwrLimitUnii1; bit2: cPwrLimitUnii2A; + * bit3: cPwrLimitUnii2C; bit4: cPwrLimitUnii3; mW: 0, mW\MHz : 1 */ + UINT_8 ucPwrUnit; +} COUNTRY_POWER_LIMIT_TABLE_DEFAULT, *P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT; + +typedef struct _COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION { + UINT_8 aucCountryCode[2]; + UINT_8 ucCentralCh; + INT_8 aucPwrLimit[PWR_LIMIT_NUM]; +} COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION, *P_COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION; + +typedef struct _SUBBAND_CHANNEL_T { + UINT_8 ucStartCh; + UINT_8 ucEndCh; + UINT_8 ucInterval; + UINT_8 ucReserved; +} SUBBAND_CHANNEL_T, *P_SUBBAND_CHANNEL_T; + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define CAL_CH_OFFSET_80M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 6) >> 2) + +#define CAL_CH_OFFSET_160M(_PRIMARY_CH, _CENTRAL_CH) \ + (((_PRIMARY_CH - _CENTRAL_CH) + 14) >> 2) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter); + +VOID +rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList); + +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid); + +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel); + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf); + +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh); + +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +BOOLEAN rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, + UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2); + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum); + +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter); + +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode); + +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_DOMAIN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h new file mode 100644 index 0000000000000..7f29dba4ce069 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_obss.h @@ -0,0 +1,150 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_obss.h#1 +*/ + +/*! \file "rlm_obss.h" + \brief +*/ + +/* +** Log: rlm_obss.h + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop + * ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +#ifndef _RLM_OBSS_H +#define _RLM_OBSS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +#define CHNL_LEVEL0 0 +#define CHNL_LEVEL1 1 +#define CHNL_LEVEL2 2 + +#define AFFECTED_CHNL_OFFSET 5 + +#define OBSS_SCAN_MIN_INTERVAL 10 /* In unit of sec */ + +#define PUBLIC_ACTION_MAX_LEN 200 /* In unit of byte */ + +/* P2P GO only */ +/* Define default OBSS Scan parameters (from MIB in spec.) */ +#define dot11OBSSScanPassiveDwell 20 +#define dot11OBSSScanActiveDwell 10 +#define dot11OBSSScanPassiveTotalPerChannel 200 +#define dot11OBSSScanActiveTotalPerChannel 20 +#define dot11BSSWidthTriggerScanInterval 300 /* Unit: sec */ +#define dot11BSSWidthChannelTransitionDelayFactor 5 +#define dot11OBSSScanActivityThreshold 25 + +#define OBSS_20_40M_TIMEOUT (dot11BSSWidthTriggerScanInterval + 10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Control MAC PCO function */ +typedef enum _ENUM_SYS_PCO_PHASE_T { + SYS_PCO_PHASE_DISABLED = 0, + SYS_PCO_PHASE_20M, + SYS_PCO_PHASE_40M +} ENUM_SYS_PCO_PHASE_T, *P_ENUM_SYS_PCO_PHASE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID rlmObssInit(P_ADAPTER_T prAdapter); + +VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr); + +VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_OBSS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h new file mode 100644 index 0000000000000..8665e48569bad --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_protection.h @@ -0,0 +1,122 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_protection.h#1 +*/ + +/*! \file "rlm_protection.h" + \brief +*/ + +/* +** Log: rlm_protection.h + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +#ifndef _RLM_PROTECTION_H +#define _RLM_PROTECTION_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SYS_PROTECT_MODE_T { + SYS_PROTECT_MODE_NONE = 0, /* Mode 0 */ + SYS_PROTECT_MODE_ERP, /* Mode 1 */ + SYS_PROTECT_MODE_NON_HT, /* Mode 2 */ + SYS_PROTECT_MODE_20M, /* Mode 3 */ + + SYS_PROTECT_MODE_NUM +} ENUM_SYS_PROTECT_MODE_T, *P_ENUM_SYS_PROTECT_MODE_T; + +/* This definition follows HT Protection field of HT Operation IE */ +typedef enum _ENUM_HT_PROTECT_MODE_T { + HT_PROTECT_MODE_NONE = 0, + HT_PROTECT_MODE_NON_MEMBER, + HT_PROTECT_MODE_20M, + HT_PROTECT_MODE_NON_HT, + + HT_PROTECT_MODE_NUM +} ENUM_HT_PROTECT_MODE_T, *P_ENUM_HT_PROTECT_MODE_T; + +typedef enum _ENUM_GF_MODE_T { + GF_MODE_NORMAL = 0, + GF_MODE_PROTECT, + GF_MODE_DISALLOWED, + + GF_MODE_NUM +} ENUM_GF_MODE_T, *P_ENUM_GF_MODE_T; + +typedef enum _ENUM_RIFS_MODE_T { + RIFS_MODE_NORMAL = 0, + RIFS_MODE_DISALLOWED, + + RIFS_MODE_NUM +} ENUM_RIFS_MODE_T, *P_ENUM_RIFS_MODE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_PROTECTION_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h new file mode 100644 index 0000000000000..d01c6e01e83f5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rlm_txpwr_init.h @@ -0,0 +1,1213 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rlm_txpwr_init.h#1 +*/ + +/*! \file "rlm_txpwr_init.h" + \brief +*/ + +/* +** Log: rlm_txpwr_init.h +*/ + + +#ifndef _RLM_TXPWR_INIT_H +#define _RLM_TXPWR_INIT_H + + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*Support Tx Power Range : 63~ -64 (unit : 0.5dBm)*/ + +#define PWR_LIMIT_2G4_IN_MW_MHZ BIT(0) +#define PWR_LIMIT_UNII1_IN_MW_MHZ BIT(1) +#define PWR_LIMIT_UNII2A_IN_MW_MHZ BIT(2) +#define PWR_LIMIT_UNII2C_IN_MW_MHZ BIT(3) +#define PWR_LIMIT_UNII3_IN_MW_MHZ BIT(4) + +#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT +#define CE_FCC_TXPWR_LIMIT_CCK 30 /* 15 dBm */ +#define CE_FCC_TXPWR_LIMIT_OFDM 20 /* 10 dBm */ +#define CE_FCC_TXPWR_LIMIT_HT40 18 /* 9 dBm */ +#endif + + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +COUNTRY_POWER_LIMIT_TABLE_DEFAULT g_rRlmPowerLimitDefault[] = { + + {{'A', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'B', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'F'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'D'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'C', 'I'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'D', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'Q'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'E', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'F', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'A'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'N'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'G', 'W'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'R', 'K'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'K', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'L', 'Y'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'M', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'N', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'T'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'C'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'L'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'B'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'R'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'S', 'Z'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'J'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'G'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'O'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'M'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'T', 'V'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'V', 'U'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'Y', 'E'} + , {40, 63, 63, 63, 63} + , 0} + , + {{'A', 'S'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'A', 'I'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'B', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'A'} + , {60, 46, 48, 48, 60} + , 0} + , + {{'K', 'Y'} + , {60, 34, 48, 60, 60} + , 0} + , + {{'G', 'U'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'F', 'M'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'R'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'U', 'S'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'V', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'A', 'U'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'A', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'B', 'W'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'K', 'H'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'C', 'X'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'C', 'O'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'C', 'R'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'E', 'C'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'G', 'D'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'G', 'T'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'H', 'K'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'K', 'I'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'L', 'B'} + , {40, 46, 46, 46, 46} + , 0} + , + {{'L', 'R'} + , {60, 46, 60, 63, 63} + , 0} + , + {{'M', 'N'} + , {46, 32, 46, 46, 58} + , 0} + , + {{'A', 'N'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'N', 'Z'} + , {63, 46, 60, 48, 63} + , 0} + , + {{'N', 'I'} + , {60, 34, 48, 48, 60} + , 0} + , + {{'P', 'W'} + , {60, 60, 60, 60, 60} + , 0} + , + {{'P', 'Y'} + , {60, 46, 46, 48, 60} + , 0} + , + {{'P', 'E'} + , {54, 46, 48, 42, 48} + , 0} + , + {{'P', 'H'} + , {40, 46, 46, 48, 48} + , 0} + , + {{'W', 'S'} + , {40, 40, 40, 40, 60} + , 0} + , + {{'S', 'G'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'L', 'K'} + , {46, 46, 46, 46, 46} + , 0} + , + {{'T', 'H'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'T', 'T'} + , {60, 46, 46, 60, 60} + , 0} + , + {{'U', 'Y'} + , {63, 46, 46, 46, 46} + , 0} + , + {{'V', 'N'} + , {46, 46, 46, 60, 60} + , 0} + , + {{'A', 'W'} + , {60, 46, 60, 60, 63} + , 0} + , + {{'L', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'A'} + , {40, 46, 46, 60, 60} + , 0} + , + {{'A', 'E'} + , {40, 46, 46, 60, 46} + , 0} + , + {{'U', 'G'} + , {40, 46, 46, 48, 60} + , 0} + , + {{'M', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'B', 'G'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Y'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'Z'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'T'} + , {40, 40, 40, 40, 63} + , 0} + , + {{'F', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'F', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'D', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'H'} + , {40, 34, 48, 60, 63} + , 0} + , + {{'G', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'P'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'H', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'I', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'K', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'V'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'L', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'Q'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'R'} + , {40, 46, 46, 46, 63} + , 0} + , + {{'M', 'U'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Y', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'D'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'N', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'O', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'L'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'P', 'T'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'R', 'O'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'M', 'F'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'M'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'N'} + , {40, 40, 40, 60, 63} + , 0} + , + {{'R', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'K'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'I'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'Z', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'E', 'S'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'S', 'E'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'C', 'H'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'R'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'T', 'C'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'G', 'B'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'V', 'A'} + , {40, 46, 46, 60, 63} + , 0} + , + {{'A', 'M'} + , {40, 40, 40, 63, 63} + , 0} + , + {{'I', 'L'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'K', 'W'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'M', 'A'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'E'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'T', 'N'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'E', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'N', 'P'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'A', 'F'} + , {40, 46, 63, 63, 63} + , 0} + , + {{'A', 'G'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'S'} + , {63, 46, 60, 63, 63} + , 0} + , + {{'B', 'H'} + , {40, 46, 46, 63, 63} + , 0} + , + {{'B', 'B'} + , {40, 46, 48, 63, 54} + , 0} + , + {{'B', 'N'} + , {46, 46, 46, 63, 60} + , 0} + , + {{'C', 'L'} + , {40, 44, 44, 63, 44} + , 0} + , + {{'C', 'N'} + , {40, 46, 46, 63, 54} + , 0} + , + {{'E', 'G'} + , {40, 46, 46, 63, 46} + , 0} + , + {{'S', 'V'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'I', 'N'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'M', 'Y'} + , {54, 60, 60, 63, 60} + , 0} + , + {{'M', 'V'} + , {40, 46, 46, 63, 40} + , 0} + , + {{'P', 'A'} + , {60, 34, 48, 63, 60} + , 0} + , + {{'V', 'E'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'Z', 'M'} + , {60, 46, 46, 63, 60} + , 0} + , + {{'J', 'O'} + , {40, 46, 63, 63, 46} + , 0} + , + {{'P', 'G'} + , {40, 46, 63, 63, 60} + , 0} + , + {{'B', 'F'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'G', 'Y'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'H', 'T'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'H', 'N'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'J', 'M'} + , {54, 63, 63, 63, 57} + , 0} + , + {{'M', 'O'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'M', 'W'} + , {60, 63, 63, 63, 60} + , 0} + , + {{'P', 'K'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'Q', 'A'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'R', 'W'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'K', 'N'} + , {40, 63, 63, 63, 60} + , 0} + , + {{'T', 'Z'} + , {40, 63, 63, 63, 40} + , 0} + , + {{'I', 'D'} + , {46, 63, 63, 63, 60} + , 0} + , + {{'N', 'G'} + , {40, 63, 46, 63, 60} + , 0} + , + {{'B', 'D'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'B', 'R'} + , {52, 46, 46, 60, 60} + , 0} + , + {{'D', 'M'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'D', 'O'} + , {63, 46, 46, 60, 63} + , 0} + , + {{'F', 'K'} + , {40, 46, 46, 60, 28} + , 0} + , + {{'K', 'Z'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'M', 'X'} + , {60, 34, 48, 60, 63} + , 0} + , + {{'M', 'Z'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'N', 'A'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'R', 'U'} + , {40, 34, 48, 60, 60} + , 0} + , + {{'L', 'C'} + , {40, 34, 48, 48, 60} + , 0} + , + {{'V', 'C'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'U', 'A'} + , {40, 46, 46, 46, 48} + , 0} + , + {{'U', 'Z'} + , {40, 48, 48, 48, 60} + , 0} + , + {{'Z', 'W'} + , {40, 34, 46, 48, 60} + , 0} + , + {{'M', 'P'} + , {60, 34, 46, 48, 60} + , 0} + , + {{'T', 'W'} + , {60, 63, 34, 48, 60} + , 0} + , + {{'C', 'K'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'C', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'T', 'L'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'F', 'O'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'I'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'G', 'G'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'R'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'I', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'E'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'K', 'P'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'M', 'H'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'U'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'N', 'F'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'N'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'P', 'M'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'S'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'D'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'S', 'Y'} + , {63, 63, 63, 63, 63} + , 0} + , + {{'J', 'P'} + , {46, 46, 46, 60, 63} + , 0} + , + {{'K', 'R'} + , {46, 34, 46, 46, 46} + , PWR_LIMIT_UNII1_IN_MW_MHZ} + , + +/*Default*/ + {{0, 0} + , {63, 63, 63, 63, 63} + , 0} +}; + +COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION g_rRlmPowerLimitConfiguration[] = { + + {{'A', 'I'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'A', 'Z'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'B', 'W'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'G', 'D'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'B'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'L', 'R'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'W', 'S'} + , 165, {40, 40, 40, 40, 40} + } + , + {{'V', 'N'} + , 144, {48, 48, 48, 48, 48} + } + , + {{'U', 'S'} + , 1, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 3, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 9, {60, 60, 26, 60, 60} + } + , + {{'U', 'S'} + , 11, {38, 30, 60, 60, 60} + } + , + {{'U', 'S'} + , 36, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 38, {34, 34, 34, 34, 34} + } + , + {{'U', 'S'} + , 42, {34, 34, 34, 31, 34} + } + , + {{'U', 'S'} + , 58, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 62, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 64, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 100, {37, 37, 48, 48, 48} + } + , + {{'U', 'S'} + , 102, {48, 48, 34, 48, 48} + } + , + {{'U', 'S'} + , 106, {48, 48, 48, 31, 48} + } + , + {{'U', 'S'} + , 155, {60, 60, 60, 31, 60} + } + , + {{'U', 'S'} + , 159, {60, 60, 34, 60, 60} + } + , + {{'U', 'S'} + , 165, {37, 37, 60, 60, 60} + } + , + +/*Default*/ + {{0, 0} + , 165, {63, 63, 63, 63, 63} + } +}; + +#if 0 +COUNTRY_CHANNEL_POWER_LIMIT g_rRlmCountryPowerLimitTable[] = { + { + {'A', 'O'} + , 0, 0, {0, 0, 0, 0} + , + { + CHANNEL_PWR_LIMIT(1, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(2, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(3, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(4, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(5, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(6, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(7, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(8, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(9, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(10, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(11, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(12, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(13, 40, 40, 40, 40, 40, 0), + CHANNEL_PWR_LIMIT(14, 40, 40, 40, 40, 40, 0), + + CHANNEL_PWR_LIMIT(36, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(38, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(40, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(42, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(44, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(46, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(48, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(52, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(54, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(56, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(58, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(60, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(62, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(64, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(100, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(102, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(104, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(106, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(108, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(110, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(112, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(114, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(116, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(118, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(120, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(122, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(124, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(126, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(128, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(130, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(132, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(134, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(136, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(138, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(140, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(142, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(144, 63, 63, 63, 63, 63, 0), + + CHANNEL_PWR_LIMIT(149, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(151, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(153, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(155, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(157, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(159, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(161, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(163, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(165, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(167, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(169, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(171, 63, 63, 63, 63, 63, 0), + CHANNEL_PWR_LIMIT(173, 63, 63, 63, 63, 63, 0) + } + } + , + { + /*Used to check the end of country entry */ + {0, 0} + , 0, 0, {0, 0, 0, 0} + , + { + /*Used to check the end of channel power limit */ + CHANNEL_PWR_LIMIT(ENDCH, 0, 0, 0, 0, 0, 0) + } + } /*end of CountryTable */ +}; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /* _RLM_TXPWR_INIT_H */ + + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h new file mode 100644 index 0000000000000..0df4ec3e08282 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/roaming_fsm.h @@ -0,0 +1,171 @@ +/* +** Id: +*/ + +/*! \file "roaming_fsm.h" + \brief This file defines the FSM for Roaming MODULE. + + This file defines the FSM for Roaming MODULE. +*/ + +/* +** Log: roaming_fsm.h + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * +*/ + +#ifndef _ROAMING_FSM_H +#define _ROAMING_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Roaming Discovery interval, SCAN result need to be updated */ +#define ROAMING_DISCOVERY_TIMEOUT_SEC 5 /* Seconds. */ + +/* #define ROAMING_NO_SWING_RCPI_STEP 5 //rcpi */ +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_ROAMING_FAIL_REASON_T { + ROAMING_FAIL_REASON_CONNLIMIT = 0, + ROAMING_FAIL_REASON_NOCANDIDATE, + ROAMING_FAIL_REASON_NUM +} ENUM_ROAMING_FAIL_REASON_T; + +/* events of roaming between driver and firmware */ +typedef enum _ENUM_ROAMING_EVENT_T { + ROAMING_EVENT_START = 0, + ROAMING_EVENT_DISCOVERY, + ROAMING_EVENT_ROAM, + ROAMING_EVENT_FAIL, + ROAMING_EVENT_ABORT, + ROAMING_EVENT_NUM +} ENUM_ROAMING_EVENT_T; + +#define ROAMING_EVENT_REASON_TX_ERR BIT(0) +#define ROAMING_EVENT_REASON_RCPI BIT(1) + +typedef struct _ROAMING_PARAM_T { + UINT_16 u2Event; + UINT_16 u2Data; + UINT_16 u2Reason; +} ROAMING_PARAM_T, *P_ROAMING_PARAM_T; + + /**/ typedef enum _ENUM_ROAMING_STATE_T { + ROAMING_STATE_IDLE = 0, + ROAMING_STATE_DECISION, + ROAMING_STATE_DISCOVERY, + ROAMING_STATE_ROAM, + ROAMING_STATE_NUM +} ENUM_ROAMING_STATE_T; + +typedef struct _ROAMING_INFO_T { + BOOLEAN fgIsEnableRoaming; + + ENUM_ROAMING_STATE_T eCurrentState; + + OS_SYSTIME rRoamingDiscoveryUpdateTime; + +#define ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX 2 + UINT_32 RoamingEntryTimeoutSkipCount; + +} ROAMING_INFO_T, *P_ROAMING_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if CFG_SUPPORT_ROAMING +#define IS_ROAMING_ACTIVE(prAdapter) \ + (prAdapter->rWifiVar.rRoamingInfo.eCurrentState == ROAMING_STATE_ROAM) +#else +#define IS_ROAMING_ACTIVE(prAdapter) FALSE +#endif /* CFG_SUPPORT_ROAMING */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID roamingFsmInit(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState); + +VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter); + +VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Reason); + +VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ROAMING_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h new file mode 100644 index 0000000000000..20ab14251f65d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/rsn.h @@ -0,0 +1,271 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/rsn.h#1 +*/ + +/*! \file rsn.h + \brief The wpa/rsn related define, macro and structure are described here. +*/ + +/* +** Log: rsn.h + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h + * and let the sw structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 wh.su + * NULL + * remove non-used code. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify + * the security related callback function prototype. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function prototype for generate wap/rsn ie + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function input parameter + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some event function declaration + * + * Nov 26 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * move the internal data structure for pmkid to rsn.h + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the port control and class error function + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the pmkid candidate + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +#ifndef _RSN_H +#define _RSN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* ----- Definitions for Cipher Suite Selectors ----- */ +#define RSN_CIPHER_SUITE_USE_GROUP_KEY 0x00AC0F00 +#define RSN_CIPHER_SUITE_WEP40 0x01AC0F00 +#define RSN_CIPHER_SUITE_TKIP 0x02AC0F00 +#define RSN_CIPHER_SUITE_CCMP 0x04AC0F00 +#define RSN_CIPHER_SUITE_WEP104 0x05AC0F00 +#if CFG_SUPPORT_802_11W +#define RSN_CIPHER_SUITE_AES_128_CMAC 0x06AC0F00 +#endif + +#define WPA_CIPHER_SUITE_NONE 0x00F25000 +#define WPA_CIPHER_SUITE_WEP40 0x01F25000 +#define WPA_CIPHER_SUITE_TKIP 0x02F25000 +#define WPA_CIPHER_SUITE_CCMP 0x04F25000 +#define WPA_CIPHER_SUITE_WEP104 0x05F25000 + +/* ----- Definitions for Authentication and Key Management Suite Selectors ----- */ +#define RSN_AKM_SUITE_NONE 0x00AC0F00 +#define RSN_AKM_SUITE_802_1X 0x01AC0F00 +#define RSN_AKM_SUITE_PSK 0x02AC0F00 +#if CFG_SUPPORT_802_11W +#define RSN_AKM_SUITE_802_1X_SHA256 0x05AC0F00 +#define RSN_AKM_SUITE_PSK_SHA256 0x06AC0F00 +#endif + +#define WPA_AKM_SUITE_NONE 0x00F25000 +#define WPA_AKM_SUITE_802_1X 0x01F25000 +#define WPA_AKM_SUITE_PSK 0x02F25000 + +#define ELEM_ID_RSN_LEN_FIXED 20 /* The RSN IE len for associate request */ + +#define ELEM_ID_WPA_LEN_FIXED 22 /* The RSN IE len for associate request */ + +#define MASK_RSNIE_CAP_PREAUTH BIT(0) + +#define GET_SELECTOR_TYPE(x) ((UINT_8)(((x) >> 24) & 0x000000FF)) +#define SET_SELECTOR_TYPE(x, y) {x = (((x) & 0x00FFFFFF) | (((UINT_32)(y) << 24) & 0xFF000000))} + +#define AUTH_CIPHER_CCMP 0x00000008 + +/* Cihpher suite flags */ +#define CIPHER_FLAG_NONE 0x00000000 +#define CIPHER_FLAG_WEP40 0x00000001 /* BIT 1 */ +#define CIPHER_FLAG_TKIP 0x00000002 /* BIT 2 */ +#define CIPHER_FLAG_CCMP 0x00000008 /* BIT 4 */ +#define CIPHER_FLAG_WEP104 0x00000010 /* BIT 5 */ +#define CIPHER_FLAG_WEP128 0x00000020 /* BIT 6 */ + +#define WAIT_TIME_IND_PMKID_CANDICATE_SEC 6 /* seconds */ +#define TKIP_COUNTERMEASURE_SEC 60 /* seconds */ + +#if CFG_SUPPORT_802_11W +#define RSN_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define RSN_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define RSN_AUTH_MFP_REQUIRED 2 /* MFP required */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* Flags for PMKID Candidate list structure */ +#define EVENT_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 + +#define CONTROL_FLAG_UC_MGMT_NO_ENC BIT(5) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RSN_IE(fp) ((P_RSN_INFO_ELEM_T) fp) +#define WPA_IE(fp) ((P_WPA_INFO_ELEM_T) fp) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +BOOLEAN rsnParseRsnIE(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prRsnInfo); + +BOOLEAN rsnParseWpaIE(IN P_ADAPTER_T prAdapter, IN P_WPA_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prWpaInfo); + +BOOLEAN rsnSearchSupportedCipher(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Cipher, OUT PUINT_32 pu4Index); + +BOOLEAN rsnSearchAKMSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4AkmSuite, OUT PUINT_32 pu4Index); + +BOOLEAN rsnPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +VOID rsnGenerateWpaNoneIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +VOID rsnGenerateRSNIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +BOOLEAN +rsnParseCheckForWFAInfoElem(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType, OUT PUINT_16 pu2SubTypeVersion); + +BOOLEAN rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo); + +#if CFG_SUPPORT_AAA +void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, PUINT_16 pu2StatusCode); +#endif + +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType); + +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex); + +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter); + +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter); + +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); +#if CFG_SUPPORT_WPS2 +VOID rsnGenerateWSCIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +#endif + +#if CFG_SUPPORT_802_11W +UINT_32 rsnCheckBipKeyInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +UINT_8 rsnCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter); + +void rsnStartSaQueryTimer(IN P_ADAPTER_T prAdapter); + +void rsnStartSaQuery(IN P_ADAPTER_T prAdapter); + +void rsnStopSaQuery(IN P_ADAPTER_T prAdapter); + +void rsnSaQueryRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +void rsnSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +BOOLEAN rsnCheckRxMgmt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN UINT_8 ucSubtype); +#endif +BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _RSN_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h new file mode 100644 index 0000000000000..c08b2244be6c4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/scan.h @@ -0,0 +1,988 @@ +/* +** Id: @(#) +*/ + +/*! \file "scan.h" + \brief + +*/ + +/* +** Log: scan.h + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration + * with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting + * preferred band configuration corresponding to network type. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than one SSID + * in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID + * support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings + * to work around some tricky AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module + * with structure miss-align pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix compile error. + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 12 2010 yuche.tsai + * NULL + * Add a functio prototype to find p2p descriptor of a bss descriptor directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Add function prototype for return channel. + * modify data structure for scan specific device ID or TYPE. (Move from P2P Connection Settings to Scan Param) + * + * 08 05 2010 yuche.tsai + * NULL + * Check-in P2P Device Discovery Feature. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Add a option for channel time extension in scan abort command. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Scan status "FIND" is used for P2P FSM find state. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request + * will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related field in SCAN_PARAM_T. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * + * Add new HW CH macro support + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify scanBuildProbeReqFrameCommonIEs() to support P2P SCAN + * + * 02 23 2010 wh.su + * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver + * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Simplify the process of Beacon during SCAN and remove redundant variable in PRE_BSS_DESC_T + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding variable for wapi ap + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove non-used secuirty variavle + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Refine data structure of BSS_DESC_T and PRE_BSS_DESC_T + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add eNetType to rScanParam and revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add ucAvailablePhyTypeSet to BSS_DESC_T + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aucSrcAddress to SCAN_PARAM_T for P2P's Device Address + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security related variable + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security ie filed for scan parsing + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scanSearchBssDescByPolicy() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function declarations of scan_fsm.c + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scan.h to source control +** +*/ + +#ifndef _SCAN_H +#define _SCAN_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_vendor.h" + +/* TDLS test purpose */ +extern BOOLEAN flgTdlsTestExtCapElm; +extern UINT8 aucTdlsTestExtCapElm[]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! Maximum buffer size of SCAN list */ +#define SCN_MAX_BUFFER_SIZE (CFG_MAX_NUM_BSS_LIST * ALIGN_4(sizeof(BSS_DESC_T))) + +#define SCN_RM_POLICY_EXCLUDE_CONNECTED BIT(0) /* Remove SCAN result except the connected one. */ +#define SCN_RM_POLICY_TIMEOUT BIT(1) /* Remove the timeout one */ +#define SCN_RM_POLICY_OLDEST_HIDDEN BIT(2) /* Remove the oldest one with hidden ssid */ +#define SCN_RM_POLICY_SMART_WEAKEST BIT(3) /* If there are more than half BSS which has the + * same ssid as connection setting, remove the + * weakest one from them + * Else remove the weakest one. + */ +#define SCN_RM_POLICY_ENTIRE BIT(4) /* Remove entire SCAN result */ + +#define SCN_BSS_DESC_SAME_SSID_THRESHOLD 3 /* This is used by POLICY SMART WEAKEST, + * If exceed this value, remove weakest BSS_DESC_T + * with same SSID first in large network. + */ + +/* the scan time in WFD mode + 2.4G/5G is about 9s so we need to enlarge the value */ +#define SCN_BSS_DESC_REMOVE_TIMEOUT_SEC 15 /* Second. */ + /* This is used by POLICY TIMEOUT, + * If exceed this value, remove timeout BSS_DESC_T. + */ + +#define SCN_PROBE_DELAY_MSEC 0 + +#define SCN_ADHOC_BSS_DESC_TIMEOUT_SEC 5 /* Second. */ + +#define SCN_NLO_NETWORK_CHANNEL_NUM (4) + +/*----------------------------------------------------------------------------*/ +/* MSG_SCN_SCAN_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_REQ_SSID_WILDCARD BIT(0) +#define SCAN_REQ_SSID_P2P_WILDCARD BIT(1) +#define SCAN_REQ_SSID_SPECIFIED BIT(2) + +/*----------------------------------------------------------------------------*/ +/* Support Multiple SSID SCAN */ +/*----------------------------------------------------------------------------*/ +#define SCN_SSID_MAX_NUM CFG_SCAN_SSID_MAX_NUM +#define SCN_SSID_MATCH_MAX_NUM CFG_SCAN_SSID_MATCH_MAX_NUM + +#define SWC_NUM_BSSID_THRESHOLD_DEFAULT 8 +#define SWC_RSSI_WINDSIZE_DEFAULT 8 +#define LOST_AP_WINDOW 16 +#define MAX_CHANNEL_NUM_PER_BUCKETS 8 + +#define SCN_BSS_JOIN_FAIL_THRESOLD 4 +#define SCN_BSS_JOIN_FAIL_CNT_RESET_SEC 15 +#define SCN_BSS_JOIN_FAIL_RESET_STEP 2 + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/* SCAN_BATCH_REQ */ +/*----------------------------------------------------------------------------*/ +#define SCAN_BATCH_REQ_START BIT(0) +#define SCAN_BATCH_REQ_STOP BIT(1) +#define SCAN_BATCH_REQ_RESULT BIT(2) +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SCAN_TYPE_T { + SCAN_TYPE_PASSIVE_SCAN = 0, + SCAN_TYPE_ACTIVE_SCAN, + SCAN_TYPE_NUM +} ENUM_SCAN_TYPE_T, *P_ENUM_SCAN_TYPE_T; + +typedef enum _ENUM_SCAN_STATE_T { + SCAN_STATE_IDLE = 0, + SCAN_STATE_SCANNING, + SCAN_STATE_NUM +} ENUM_SCAN_STATE_T; + +typedef enum _ENUM_SCAN_CHANNEL_T { + SCAN_CHANNEL_FULL = 0, + SCAN_CHANNEL_2G4, + SCAN_CHANNEL_5G, + SCAN_CHANNEL_P2P_SOCIAL, + SCAN_CHANNEL_SPECIFIED, + SCAN_CHANNEL_NUM +} ENUM_SCAN_CHANNEL, *P_ENUM_SCAN_CHANNEL; + +typedef struct _MSG_SCN_FSM_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_32 u4Dummy; +} MSG_SCN_FSM_T, *P_MSG_SCN_FSM_T; + +typedef enum _ENUM_PSCAN_STATE_T { + PSCN_IDLE = 1, + PSCN_SCANNING, + PSCN_RESET, + PSCAN_STATE_T_NUM +} ENUM_PSCAN_STATE_T; + +/*----------------------------------------------------------------------------*/ +/* BSS Descriptors */ +/*----------------------------------------------------------------------------*/ +struct _BSS_DESC_T { + LINK_ENTRY_T rLinkEntry; + + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ + + BOOLEAN fgIsConnecting; /* If we are going to connect to this BSS + * (JOIN or ROAMING to another BSS), don't + * remove this record from BSS List. + */ + BOOLEAN fgIsConnected; /* If we have connected to this BSS (NORMAL_TR), + * don't removed this record from BSS list. + */ + + BOOLEAN fgIsHiddenSSID; /* When this flag is TRUE, means the SSID + * of this BSS is not known yet. + */ + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + + OS_SYSTIME rUpdateTime; + + ENUM_BSS_TYPE_T eBSSType; + + UINT_16 u2CapInfo; + + UINT_16 u2BeaconInterval; + UINT_16 u2ATIMWindow; + + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + BOOLEAN fgIsERPPresent; + BOOLEAN fgIsHTPresent; + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this BSS */ + + UINT_8 ucChannelNum; + + ENUM_CHNL_EXT_T eSco; /* Record bandwidth for association process + Some AP will send association resp by 40MHz BW */ + ENUM_BAND_T eBand; + + UINT_8 ucDTIMPeriod; + + BOOLEAN fgIsLargerTSF; /* This BSS's TimeStamp is larger than us(TCL == 1 in RX_STATUS_T) */ + + UINT_8 ucRCPI; + + UINT_8 ucWmmFlag; /* A flag to indicate this BSS's WMM capability */ + + /*! \brief The srbiter Search State will matched the scan result, + and saved the selected cipher and akm, and report the score, + for arbiter join state, join module will carry this target BSS + to rsn generate ie function, for gen wpa/rsn ie */ + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + + UINT_16 u2RsnCap; + + RSN_INFO_T rRSNInfo; + RSN_INFO_T rWPAInfo; +#if 1 /* CFG_SUPPORT_WAPI */ + WAPI_INFO_T rIEWAPI; + BOOLEAN fgIEWAPI; +#endif + BOOLEAN fgIERSN; + BOOLEAN fgIEWPA; + + /*! \brief RSN parameters selected for connection */ + /*! \brief The Select score for final AP selection, + 0, no sec, 1,2,3 group cipher is WEP, TKIP, CCMP */ + UINT_8 ucEncLevel; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PPresent; + BOOLEAN fgIsP2PReport; /* TRUE: report to upper layer */ + P_P2P_DEVICE_DESC_T prP2pDesc; + + UINT_8 aucIntendIfAddr[MAC_ADDR_LEN]; /* For IBSS, the SrcAddr is different from BSSID */ +/* UINT_8 ucDevCapabilityBitmap; */ /* Device Capability Attribute. (P2P_DEV_CAPABILITY_XXXX) */ +/* UINT_8 ucGroupCapabilityBitmap; */ /* Group Capability Attribute. (P2P_GROUP_CAPABILITY_XXXX) */ + + LINK_T rP2pDeviceList; + +/* P_LINK_T prP2pDeviceList; */ + + /* For + * 1. P2P Capability. + * 2. P2P Device ID. ( in aucSrcAddr[] ) + * 3. NOA (TODO:) + * 4. Extend Listen Timing. (Probe Rsp) (TODO:) + * 5. P2P Device Info. (Probe Rsp) + * 6. P2P Group Info. (Probe Rsp) + */ +#endif + + BOOLEAN fgIsIEOverflow; /* The received IE length exceed the maximum IE buffer size */ + UINT_16 u2RawLength; /* The byte count of aucRawBuf[] */ + UINT_16 u2IELength; /* The byte count of aucIEBuf[] */ + + ULARGE_INTEGER u8TimeStamp; /* Place u8TimeStamp before aucIEBuf[1] to force DW align */ + UINT_8 aucRawBuf[CFG_RAW_BUFFER_SIZE]; + UINT_8 aucIEBuf[CFG_IE_BUFFER_SIZE]; + UINT_8 ucJoinFailureCount; + OS_SYSTIME rJoinFailTime; +}; + +typedef struct _SCAN_PARAM_T { /* Used by SCAN FSM */ + /* Active or Passive */ + ENUM_SCAN_TYPE_T eScanType; + + /* Network Type */ + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + + /* Specified SSID Type */ + UINT_8 ucSSIDType; + UINT_8 ucSSIDNum; + + /* Length of Specified SSID */ + UINT_8 ucSpecifiedSSIDLen[SCN_SSID_MAX_NUM]; + + /* Specified SSID */ + UINT_8 aucSpecifiedSSID[SCN_SSID_MAX_NUM][ELEM_MAX_LEN_SSID]; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgFindSpecificDev; /* P2P: Discovery Protocol */ + UINT_8 aucDiscoverDevAddr[MAC_ADDR_LEN]; + BOOLEAN fgIsDevType; + P2P_DEVICE_TYPE_T rDiscoverDevType; + + UINT_16 u2PassiveListenInterval; + /* TODO: Find Specific Device Type. */ +#endif /* CFG_SUPPORT_P2P */ + + BOOLEAN fgIsObssScan; + BOOLEAN fgIsScanV2; + + /* Run time flags */ + UINT_16 u2ProbeDelayTime; + + /* channel information */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + + /* Feedback information */ + UINT_8 ucSeqNum; + + /* Information Element */ + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; + +} SCAN_PARAM_T, *P_SCAN_PARAM_T; + +typedef struct _NLO_PARAM_T { /* Used by SCAN FSM */ + SCAN_PARAM_T rScanParam; + + /* NLO */ + BOOLEAN fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + + /* Match SSID */ + UINT_8 ucMatchSSIDNum; + UINT_8 ucMatchSSIDLen[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucMatchSSID[SCN_SSID_MATCH_MAX_NUM][ELEM_MAX_LEN_SSID]; + + UINT_8 aucCipherAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_16 au2AuthAlgo[SCN_SSID_MATCH_MAX_NUM]; + UINT_8 aucChannelHint[SCN_SSID_MATCH_MAX_NUM][SCN_NLO_NETWORK_CHANNEL_NUM]; + P_BSS_DESC_T aprPendingBssDescToInd[SCN_SSID_MATCH_MAX_NUM]; +} NLO_PARAM_T, *P_NLO_PARAM_T; + +#if 1 + +typedef struct _GSCN_CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannel; /* frequency */ + UINT_8 ucPassive; /* 0 => active, 1 => passive scan; ignored for DFS */ + UINT_8 aucReserved[1]; + + UINT_32 u4DwellTimeMs; /* dwell time hint */ + /* Add channel class */ +} GSCN_CHANNEL_INFO_T, *P_GSCN_CHANNEL_INFO_T; + +typedef struct _GSCAN_CHANNEL_BUCKET_T { + + UINT_16 u2BucketIndex; /* bucket index, 0 based */ + UINT_8 ucBucketFreqMultiple; /* desired period, in millisecond; + * if this is too low, the firmware should choose to generate + * results as fast as it can instead of failing the command */ + /* report_events semantics - + * 0 => report only when scan history is % full + * 1 => same as 0 + report a scan completion event after scanning this bucket + * 2 => same as 1 + forward scan results (beacons/probe responses + IEs) in real time to HAL + * 3 => same as 2 + forward scan results (beacons/probe responses + IEs) in real time to + supplicant as well (optional) . */ + UINT_8 ucReportFlag; + UINT_8 ucNumChannels; + UINT_8 aucReserved[3]; + WIFI_BAND eBand; /* when UNSPECIFIED, use channel list */ + GSCN_CHANNEL_INFO_T arChannelList[GSCAN_MAX_CHANNELS]; /* channels to scan; these may include DFS channels */ +} GSCAN_CHANNEL_BUCKET_T, *P_GSCAN_CHANNEL_BUCKET_T; + +typedef struct _CMD_GSCN_REQ_T { + UINT_8 ucFlags; + UINT_8 ucNumScnToCache; + UINT_8 aucReserved[2]; + UINT_32 u4BufferThreshold; + UINT_32 u4BasePeriod; /* base timer period in ms */ + UINT_32 u4NumBuckets; + UINT_32 u4MaxApPerScan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + + GSCAN_CHANNEL_BUCKET_T arChannelBucket[GSCAN_MAX_BUCKETS]; +} CMD_GSCN_REQ_T, *P_CMD_GSCN_REQ_T; + +#endif + +typedef struct _CMD_GSCN_SCN_COFIG_T { + UINT_8 ucNumApPerScn; /* GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN */ + UINT_32 u4NumScnToCache; /* GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE */ + UINT_32 u4BufferThreshold; /* GSCAN_ATTRIBUTE_REPORT_THRESHOLD */ +} CMD_GSCN_SCN_COFIG_T, *P_CMD_GSCN_SCN_COFIG_T; + +typedef struct _CMD_GET_GSCAN_RESULT { + UINT_8 ucVersion; + UINT_8 aucReserved[2]; + UINT_8 ucFlush; + UINT_32 u4Num; +} CMD_GET_GSCAN_RESULT_T, *P_CMD_GET_GSCAN_RESULT_T; + +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* an integer number of highest-strength AP for which we'd like + approximate distance reported */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _PSCN_PARAM_T { + UINT_8 ucVersion; + CMD_NLO_REQ rCurrentCmdNloReq; + CMD_BATCH_REQ_T rCurrentCmdBatchReq; + CMD_GSCN_REQ_T rCurrentCmdGscnReq; + BOOLEAN fgNLOScnEnable; + BOOLEAN fgBatchScnEnable; + BOOLEAN fgGScnEnable; + UINT_32 u4BasePeriod; /* GSCAN_ATTRIBUTE_BASE_PERIOD */ +} PSCN_PARAM_T, *P_PSCN_PARAM_T; + +typedef struct _SCAN_INFO_T { + ENUM_SCAN_STATE_T eCurrentState; /* Store the STATE variable of SCAN FSM */ + + OS_SYSTIME rLastScanCompletedTime; + + SCAN_PARAM_T rScanParam; + NLO_PARAM_T rNloParam; + + UINT_32 u4NumOfBssDesc; + + UINT_8 aucScanBuffer[SCN_MAX_BUFFER_SIZE]; + + LINK_T rBSSDescList; + + LINK_T rFreeBSSDescList; + + LINK_T rPendingMsgList; + + /* Sparse Channel Detection */ + BOOLEAN fgIsSparseChannelValid; + RF_CHANNEL_INFO_T rSparseChannel; + + /* NLO scanning state tracking */ + BOOLEAN fgNloScanning; + BOOLEAN fgPscnOnnning; + BOOLEAN fgGScnConfigSet; + BOOLEAN fgGScnParamSet; + P_PSCN_PARAM_T prPscnParam; + ENUM_PSCAN_STATE_T eCurrentPSCNState; + +} SCAN_INFO_T, *P_SCAN_INFO_T; + +/* Incoming Mailbox Messages */ +typedef struct _MSG_SCN_SCAN_REQ_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_TYPE_T eScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucSSID[PARAM_MAX_LEN_SSID]; +#if CFG_ENABLE_WIFI_DIRECT + UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ +#endif + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} MSG_SCN_SCAN_REQ, *P_MSG_SCN_SCAN_REQ; + +typedef struct _MSG_SCN_SCAN_REQ_V2_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_TYPE_T eScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDNum; + P_PARAM_SSID_T prSsid; + UINT_16 u2ProbeDelay; + UINT_16 u2ChannelDwellTime; /* In TU. 1024us. */ + ENUM_SCAN_CHANNEL eScanChannel; + UINT_8 ucChannelListNum; + RF_CHANNEL_INFO_T arChnlInfoList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} MSG_SCN_SCAN_REQ_V2, *P_MSG_SCN_SCAN_REQ_V2; + +typedef struct _MSG_SCN_SCAN_CANCEL_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsChannelExt; +#endif +} MSG_SCN_SCAN_CANCEL, *P_MSG_SCN_SCAN_CANCEL; + +/* Outgoing Mailbox Messages */ +typedef enum _ENUM_SCAN_STATUS_T { + SCAN_STATUS_DONE = 0, + SCAN_STATUS_CANCELLED, + SCAN_STATUS_FAIL, + SCAN_STATUS_BUSY, + SCAN_STATUS_NUM +} ENUM_SCAN_STATUS, *P_ENUM_SCAN_STATUS; + +typedef struct _MSG_SCN_SCAN_DONE_T { + MSG_HDR_T rMsgHdr; /* Must be the first member */ + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + ENUM_SCAN_STATUS eScanStatus; +} MSG_SCN_SCAN_DONE, *P_MSG_SCN_SCAN_DONE; + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum { + AGPS_PHY_A, + AGPS_PHY_B, + AGPS_PHY_G, +} AP_PHY_TYPE; + +typedef struct _AGPS_AP_INFO_T { + UINT_8 aucBSSID[6]; + INT_16 i2ApRssi; /* -127..128 */ + UINT_16 u2Channel; /* 0..256 */ + AP_PHY_TYPE ePhyType; +} AGPS_AP_INFO_T, *P_AGPS_AP_INFO_T; + +typedef struct _AGPS_AP_LIST_T { + UINT_8 ucNum; + AGPS_AP_INFO_T arApInfo[32]; +} AGPS_AP_LIST_T, *P_AGPS_AP_LIST_T; +#endif + +typedef struct _CMD_SET_PSCAN_PARAM { + UINT_8 ucVersion; + CMD_NLO_REQ rCmdNloReq; + CMD_BATCH_REQ_T rCmdBatchReq; + CMD_GSCN_REQ_T rCmdGscnReq; + BOOLEAN fgNLOScnEnable; + BOOLEAN fgBatchScnEnable; + BOOLEAN fgGScnEnable; + UINT_32 u4BasePeriod; +} CMD_SET_PSCAN_PARAM, *P_CMD_SET_PSCAN_PARAM; + +typedef struct _CMD_SET_PSCAN_ADD_HOTLIST_BSSID { + UINT_8 aucMacAddr[6]; + UINT_8 ucFlags; + UINT_8 aucReserved[5]; +} CMD_SET_PSCAN_ADD_HOTLIST_BSSID, *P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID; + +typedef struct _CMD_SET_PSCAN_ADD_SWC_BSSID { + INT_32 i4RssiLowThreshold; + INT_32 i4RssiHighThreshold; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[6]; +} CMD_SET_PSCAN_ADD_SWC_BSSID, *P_CMD_SET_PSCAN_ADD_SWC_BSSID; + +typedef struct _CMD_SET_PSCAN_MAC_ADDR { + UINT_8 ucVersion; + UINT_8 ucFlags; + UINT_8 aucMacAddr[6]; + UINT_8 aucReserved[8]; +} CMD_SET_PSCAN_MAC_ADDR, *P_CMD_SET_PSCAN_MAC_ADDR; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in scan.c */ +/*----------------------------------------------------------------------------*/ +VOID scnInit(IN P_ADAPTER_T prAdapter); + +VOID scnUninit(IN P_ADAPTER_T prAdapter); + +/* BSS-DESC Search */ +P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]); + +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +#if CFG_SUPPORT_HOTSPOT_2_0 +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); +#endif + +/* BSS-DESC Search - Alternative */ +P_BSS_DESC_T +scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]); + +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid); + +/* BSS-DESC Allocation */ +P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter); + +/* BSS-DESC Removal */ +VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy); + +VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +VOID +scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/* BSS-DESC State Change */ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]); + +#if 0 +/* BSS-DESC Insertion */ +P_BSS_DESC_T scanAddToInternalScanResult(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb, IN P_BSS_DESC_T prBssDesc); +#endif + +/* BSS-DESC Insertion - ALTERNATIVE */ +P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb); + +VOID +scanBuildProbeReqFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, + IN PUINT_8 pucDesiredSsid, IN UINT_32 u4DesiredSsidLen, IN UINT_16 u2SupportedRateSet); + +WLAN_STATUS scanSendProbeReqFrames(IN P_ADAPTER_T prAdapter, IN P_SCAN_PARAM_T prScanParam); + +VOID scanUpdateBssDescForSearch(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc); + +P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb); + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc); + +/*----------------------------------------------------------------------------*/ +/* Routines in scan_fsm.c */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState); + +/*----------------------------------------------------------------------------*/ +/* Command Routines */ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReq(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter); + +VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* RX Event Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone); + +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Handling */ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg); + +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg); + +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Generation */ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus); + +/*----------------------------------------------------------------------------*/ +/* Query for sparse channel */ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, + IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval); + +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter); + +BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPscanAct); + +BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +BOOLEAN scnFsmGSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); + +#if 0 + +BOOLEAN scnFsmGSCNSetRssiSignificatn(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam); +#endif + +BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId); + +BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr); + +#if 1 /* CFG_SUPPORT_GSCN_NONSYNC_BROADCOM */ +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam); + +#else +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_REQ_T prCmdGscnParam); + +#endif + +BOOLEAN +scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prCmdNloReq, + IN P_CMD_BATCH_REQ_T prCmdBatchReq, + IN P_CMD_GSCN_REQ_T prCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN); + +BOOLEAN scnFsmSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig); + +BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, IN P_CMD_GET_GSCAN_RESULT_T prGetGscnScnResultCmd); + +VOID +scnPSCNFsm(IN P_ADAPTER_T prAdapter, + ENUM_PSCAN_STATE_T eNextPSCNState, + IN P_CMD_NLO_REQ prCmdNloReq, + IN P_CMD_BATCH_REQ_T prCmdBatchReq, + IN P_CMD_GSCN_REQ_T prCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN, IN BOOLEAN fgEnableGSCN); + +#endif /* _SCAN_H */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter); +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h new file mode 100644 index 0000000000000..c6c468e06c4a5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/sec_fsm.h @@ -0,0 +1,233 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/sec_fsm.h#1 +*/ + +/*! \file sec_fsm.h + \brief Declaration of functions and finite state machine for SECURITY Module. + + Function declaration for privacy.c and SEC_STATE for SECURITY FSM. +*/ + +/* +** Log: sec_fsm.h + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 03 04 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Code refine, and remove non-used code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, and modify the security + * related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * fixed the deauth Tx done callback parameter + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the reference function declaration + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * delete non-used code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function prototype + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function declaration + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the security variable + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** \main\maintrunk.MT5921\14 2009-04-06 15:35:47 GMT mtk01088 +** add the variable to set the disable AP selection for privacy check, for wps open networking. +** \main\maintrunk.MT5921\13 2008-11-19 11:46:01 GMT mtk01088 +** rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\12 2008-08-28 20:37:11 GMT mtk01088 +** remove non-used code +** +** \main\maintrunk.MT5921\11 2008-03-18 09:51:52 GMT mtk01088 +** Add function declaration for timer to indicate pmkid candidate +** \main\maintrunk.MT5921\10 2008-02-29 15:12:08 GMT mtk01088 +** add variable for sw port control +** \main\maintrunk.MT5921\9 2008-02-29 12:37:30 GMT mtk01088 +** rename the security related function declaration +** \main\maintrunk.MT5921\8 2007-12-27 13:59:08 GMT mtk01088 +** adjust the wlan table and sec fsm init timing +** \main\maintrunk.MT5921\7 2007-11-20 10:39:49 GMT mtk01088 +** add function timer for wait EAPoL Error timeout +** \main\maintrunk.MT5921\6 2007-11-06 20:39:08 GMT mtk01088 +** rename the counter measure timer +** \main\maintrunk.MT5921\5 2007-11-06 20:14:31 GMT mtk01088 +** add a abort function +** Revision 1.5 2007/07/16 02:33:42 MTK01088 +** change the ENUM declaration structure prefix from r to e +** +** Revision 1.4 2007/07/09 06:23:10 MTK01088 +** update +** +** Revision 1.3 2007/07/04 10:09:04 MTK01088 +** adjust the state for security fsm +** change function name +** +** Revision 1.2 2007/07/03 08:13:22 MTK01088 +** change the sec fsm state +** add the event for sec fsm +** +** Revision 1.1 2007/06/27 06:20:35 MTK01088 +** add the sec fsm header file +** +** +*/ +#ifndef _SEC_FSM_H +#define _SEC_FSM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* TKIP CounterMeasure interval for Rejoin to Network. */ +#define COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC 60 + +/* Timeout to wait the EAPoL Error Report frame Send out. */ +#define EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef UINT_32 SEC_STATUS, *P_SEC_STATUS; + +#if 0 +/* WPA2 PMKID candicate structure */ +typedef struct _PMKID_CANDICATE_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; /* MAC address */ + UINT_32 u4PreAuthFlags; +} PMKID_CANDICATE_T, *P_PMKID_CANDICATE_T; +#endif + +typedef SEC_STATUS(*PFN_SEC_FSM_STATE_HANDLER) (VOID); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SEC_STATE_TRANSITION_FLAG fgIsTransition +#define SEC_NEXT_STATE_VAR eNextState + +#define SEC_STATE_TRANSITION(prAdapter, prSta, eFromState, eToState) \ + { secFsmTrans_ ## eFromState ## _to_ ## eToState(prAdapter, prSta); \ + SEC_NEXT_STATE_VAR = SEC_STATE_ ## eToState; \ + SEC_STATE_TRANSITION_FLAG = (BOOLEAN)TRUE; \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle the sec check */ +/*--------------------------------------------------------------*/ +/***** Routines in sec_fsm.c *****/ +VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID +secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); + +VOID +secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta); + +VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, IN ULONG ulParm); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _SEC_FSM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h new file mode 100644 index 0000000000000..1c0f9a76e1192 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/stats.h @@ -0,0 +1,368 @@ +/* +** Id: stats.h#1 +*/ + +/*! \file stats.h + \brief This file includes statistics support. +*/ + +/* +** Log: stats.h + * + * 07 17 2014 samp.lin + * NULL + * Initial version. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +extern UINT_64 u8DrvOwnStart, u8DrvOwnEnd; +extern UINT32 u4DrvOwnMax; +extern BOOLEAN fgIsUnderSuspend; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Command to TDLS core module */ +typedef enum _STATS_CMD_CORE_ID { + STATS_CORE_CMD_ENV_REQUEST = 0x00 +} STATS_CMD_CORE_ID; + +typedef enum _STATS_EVENT_HOST_ID { + STATS_HOST_EVENT_ENV_REPORT = 0x00, + STATS_HOST_EVENT_RX_DROP +} STATS_EVENT_HOST_ID; + +#define CFG_ARP BIT(0) +#define CFG_DNS BIT(1) +#define CFG_TCP BIT(2) +#define CFG_UDP BIT(3) +#define CFG_EAPOL BIT(4) +#define CFG_DHCP BIT(5) +#define CFG_ICMP BIT(6) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _STATS_CMD_CORE_T { + + UINT32 u4Command; /* STATS_CMD_CORE_ID */ + + UINT8 ucStaRecIdx; + UINT8 ucReserved[3]; + + UINT32 u4Reserved[4]; + +#define STATS_CMD_CORE_RESERVED_SIZE 50 + union { + UINT8 Reserved[STATS_CMD_CORE_RESERVED_SIZE]; + } Content; + +} STATS_CMD_CORE_T; + +typedef struct _STATS_INFO_ENV_T { + + BOOLEAN fgIsUsed; /* TRUE: used */ + + /* ------------------- TX ------------------- */ + BOOLEAN fgTxIsRtsUsed; /* TRUE: we use RTS/CTS currently */ + BOOLEAN fgTxIsRtsEverUsed; /* TRUE: we ever use RTS/CTS */ + BOOLEAN fgTxIsCtsSelfUsed; /* TRUE: we use CTS-self */ + +#define STATS_INFO_TX_PARAM_HW_BW40_OFFSET 0 +#define STATS_INFO_TX_PARAM_HW_SHORT_GI20_OFFSET 1 +#define STATS_INFO_TX_PARAM_HW_SHORT_GI40_OFFSET 2 +#define STATS_INFO_TX_PARAM_USE_BW40_OFFSET 3 +#define STATS_INFO_TX_PARAM_USE_SHORT_GI_OFFSET 4 +#define STATS_INFO_TX_PARAM_NO_ACK_OFFSET 5 + UINT_8 ucTxParam; + + UINT_8 ucStaRecIdx; + UINT_8 ucReserved1[2]; + + UINT32 u4TxDataCntAll; /* total tx count from host */ + UINT32 u4TxDataCntOK; /* total tx ok count to air */ + UINT32 u4TxDataCntErr; /* total tx err count to air */ + + /* WLAN_STATUS_BUFFER_RETAINED ~ WLAN_STATUS_PACKET_LIFETIME_ERROR */ + UINT32 u4TxDataCntErrType[6]; /* total tx err count for different type to air */ + + UINT_8 ucTxRate1NonHTMax; + UINT_8 ucTxRate1HTMax; + UINT32 u4TxRateCntNonHT[16]; /* tx done rate */ + UINT32 u4TxRateCntHT[16]; /* tx done rate */ + + UINT_8 ucTxAggBitmap; /* TX BA sessions TID0 ~ TID7 */ + UINT_8 ucTxPeerAggMaxSize; + + /* ------------------- RX ------------------- */ + BOOLEAN fgRxIsRtsUsed; /* TRUE: peer uses RTS/CTS currently */ + BOOLEAN fgRxIsRtsEverUsed; /* TRUE: peer ever uses RTS/CTS */ + + UINT_8 ucRcvRcpi; + UINT_8 ucHwChanNum; + BOOLEAN fgRxIsShortGI; + UINT_8 ucReserved2[1]; + + UINT32 u4RxDataCntAll; /* total rx count from peer */ + UINT32 u4RxDataCntErr; /* total rx err count */ + UINT32 u4RxRateCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ + + UINT_8 ucRxAggBitmap; /* RX BA sessions TID0 ~ TID7 */ + UINT_8 ucRxAggMaxSize; + +#define STATS_INFO_PHY_MODE_CCK 0 +#define STATS_INFO_PHY_MODE_OFDM 1 +#define STATS_INFO_PHY_MODE_HT 2 +#define STATS_INFO_PHY_MODE_VHT 3 + UINT_8 ucBssSupPhyMode; /* CCK, OFDM, HT, or VHT BSS */ + + UINT_8 ucVersion; /* the version of statistics info environment */ + + /* ------------------- Delay ------------------- */ +#define STATS_AIR_DELAY_INT 500 /* 500 byte */ + + /* delay in firmware from host to MAC */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxH2M[3], u4StayIntMinH2M[3], u4StayIntAvgH2M[3]; + + /* delay in firmware from MAC to TX done */ + /* unit: 32us, for 500B, 1000B, max */ + UINT32 u4AirDelayMax[3], u4AirDelayMin[3], u4AirDelayAvg[3]; + + /* delay in firmware from host to TX done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMax[3], u4StayIntMin[3], u4StayIntAvg[3]; + UINT32 u4StayIntMaxSysTime[3]; + + /* delay in firmware from driver to TX done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxD2T[3], u4StayIntMinD2T[3], u4StayIntAvgD2T[3]; + + /* delay count in firmware from host to TX done */ + /* u4StayIntByConst: divide 4 fix partitions to count each delay in firmware */ +#define STATS_STAY_INT_CONST 1 /* 1ms */ +#define STATS_STAY_INT_CONST_2 5 +#define STATS_STAY_INT_CONST_3 10 +#define STATS_STAY_INT_CONST_4 15 +#define STATS_STAY_INT_CONST_NUM 4 + UINT32 u4StayIntByConst[STATS_STAY_INT_CONST_NUM]; + + /* + u4StayIntMaxPast: past maximum delay in firmware + u4StayIntCnt[]: divide 4 partitions to count each delay in firmware + */ +#define STATS_STAY_INT_NUM 4 + UINT32 u4StayIntMaxPast; + UINT32 u4StayIntCnt[STATS_STAY_INT_NUM + 1]; + + /* delay count in firmware from driver to HIF */ + /* u4StayIntD2HByConst: divide 4 fix partitions to count each delay in firmware */ +#define STATS_STAY_INT_D2H_CONST 10 /* 10ms */ +#define STATS_STAY_INT_D2H_CONST_2 20 +#define STATS_STAY_INT_D2H_CONST_3 30 +#define STATS_STAY_INT_D2H_CONST_4 40 +#define STATS_STAY_INT_D2H_CONST_NUM 4 + UINT32 u4StayIntD2HByConst[STATS_STAY_INT_D2H_CONST_NUM]; + + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxRx[3], u4StayIntMinRx[3], u4StayIntAvgRx[3]; + + /* ------------------- Others ------------------- */ + UINT32 u4NumOfChanChange; /* total channel change count */ + UINT32 u4NumOfRetryCnt; /* total TX retry count */ + UINT32 u4RxFifoFullCnt; /* counter of the number of the packets which + pass RFCR but are dropped due to FIFO full. */ + UINT32 u4PsIntMax; /* maximum time from ps to active */ + UINT_8 ucNumOfPsChange; /* peer power save change count */ + UINT_8 ucReserved3[3]; + + UINT32 u4ReportSysTime; /* firmware system time */ + UINT32 u4RxDataCntOk; /* total rx count to hif */ + + /* V4 */ + UINT32 u4RxRateRetryCnt[3][16]; /* [0]:CCK, [1]:OFDM, [2]:MIXED (skip green mode) */ + UINT32 au4ChanIdleCnt[10]; /* past Channel idle count in unit of slot */ + + /* V5 */ + UINT32 u4BtContUseTime; /* the air time that BT continuous occypy */ + + /* V6 */ + UINT32 u4LastTxOkTime; /* last time we tx ok to the station */ + + /* V7 */ + UINT_8 ucBtWfCoexGrantCnt[8]; /* [0]:WF Rx Grant Cnt[1]: WF Tx Grant Cnt[2]: WF Grant with Priority1 */ + /* [4]:BT Rx Grant Cnt[5]: BT Tx Grant Cnt[6]: BT Grant with Priority1 */ + + /* V8 */ + UINT_32 u4RxMacFreeDescCnt[6]; + UINT_32 u4RxHifFreeDescCnt[6]; + + /* V9 */ +#define STATS_MAX_RX_DROP_TYPE 20 + UINT32 u4NumOfRxDrop[STATS_MAX_RX_DROP_TYPE]; + + /* V10 */ + UINT_32 u4NumOfTxDone; /* number of all packets (data/man/ctrl) tx done */ + UINT_32 u4NumOfTxDoneFixRate; /* number of done rate = 0 */ + UINT_32 u4NumOfTxDoneErrRate; /* number of error done rate */ + UINT_32 u4NumOfNullTxDone; /* number of null tx done */ + UINT_32 u4NumOfQoSNullTxDone; /* number of QoS-null tx done */ + + /* V11 */ + /* delay in firmware from HIF RX to HIF RX Done */ + /* unit: us, for 500B, 1000B, max */ + UINT32 u4StayIntMaxHR2HRD[3], u4StayIntMinHR2HRD[3], u4StayIntAvgHR2HRD[3]; + + /* V12 */ + UINT32 u4AirDelayTotal; /* agg all the air delay */ + + /* V13 */ + UINT32 u4CurrChnlInfo; /* add current channel information */ + + UINT_8 ucReserved_rate[4]; /* the field must be the last one */ +} STATS_INFO_ENV_T; + +/******************************************************************************* +* M A C R O D E C L A R A T I O N S +******************************************************************************** +*/ +#if (CFG_SUPPORT_STATISTICS == 1) + +#define STATS_ENV_REPORT_DETECT statsEnvReportDetect + +#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderFallAheadCnt++; \ +} + +#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderFallBehindCnt++; \ +} + +#define STATS_RX_REORDER_HOLE_INC(__StaRec__) \ +{ \ + (__StaRec__)->u4RxReorderHoleCnt++; \ +} + +#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) \ +{ \ + if ((__IsTimeout__) == TRUE) \ + (__StaRec__)->u4RxReorderHoleTimeoutCnt++; \ +} + +#define STATS_RX_ARRIVE_TIME_RECORD(__SwRfb__) \ +{ \ + (__SwRfb__)->rRxTime = StatsEnvTimeGet(); \ +} + +#define STATS_RX_PASS2OS_INC StatsEnvRxDone + +#define STATS_RX_PKT_INFO_DISPLAY StatsRxPktInfoDisplay + +#define STATS_TX_TIME_ARRIVE(__Skb__) \ +do { \ + UINT_64 __SysTime; \ + __SysTime = StatsEnvTimeGet(); /* us */ \ + GLUE_SET_PKT_XTIME(__Skb__, __SysTime); \ +} while (FALSE) + +#define STATS_TX_TIME_TO_HIF StatsEnvTxTime2Hif + +#define STATS_TX_PKT_CALLBACK StatsTxPktCallBack +#define STATS_TX_PKT_DONE_INFO_DISPLAY StatsTxPktDoneInfoDisplay + +#define STATS_DRIVER_OWN_RESET() \ +{ \ + u4DrvOwnMax = 0; \ +} +#define STATS_DRIVER_OWN_START_RECORD() \ +{ \ + u8DrvOwnStart = StatsEnvTimeGet(); \ +} +#define STATS_DRIVER_OWN_END_RECORD() \ +{ \ + u8DrvOwnEnd = StatsEnvTimeGet(); \ +} +#define STATS_DRIVER_OWN_STOP() \ +do { \ + UINT32 __Diff; \ + __Diff = (UINT32)(u8DrvOwnEnd - u8DrvOwnStart); \ + if (__Diff > u4DrvOwnMax) \ + u4DrvOwnMax = __Diff; \ +} while (FALSE) + +#else + +#define STATS_ENV_REPORT_DETECT(__Adapter__, __StaRecIndex__) + +#define STATS_RX_REORDER_FALL_AHEAD_INC(__StaRec__) +#define STATS_RX_REORDER_FALL_BEHIND_INC(__StaRec__) +#define STATS_RX_REORDER_HOLE_INC(__StaRec__) +#define STATS_RX_REORDER_HOLE_TIMEOUT_INC(__StaRec__, __IsTimeout__) +#define STATS_RX_PASS2OS_INC(__StaRec__, __SwRfb__) +#define STATS_RX_PKT_INFO_DISPLAY(__Pkt__) + +#define STATS_TX_TIME_ARRIVE(__Skb__) +#define STATS_TX_TIME_TO_HIF(__MsduInfo__, __HwTxHeader__) +#define STATS_TX_PKT_CALLBACK(__Pkt__, __fgIsNeedAck__) +#define STATS_TX_PKT_DONE_INFO_DISPLAY(__Adapter__, __Event__) + +#define STATS_DRIVER_OWN_RESET() +#define STATS_DRIVER_OWN_START_RECORD() +#define STATS_DRIVER_OWN_END_RECORD() +#define STATS_DRIVER_OWN_STOP() +#endif /* CFG_SUPPORT_STATISTICS */ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex); + +VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb); + +UINT_64 StatsEnvTimeGet(VOID); + +VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader); + +VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +VOID StatsRxPktInfoDisplay(UINT_8 *pPkt); + +VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo); + +VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf); + +VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet); + +UINT_16 StatsGetCfgTxDone(VOID); + +/* End of stats.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h new file mode 100644 index 0000000000000..50c4b558c2cd5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/swcr.h @@ -0,0 +1,187 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/swcr.h#1 +*/ + +/*! \file "swcr.h" + \brief +*/ + +/* + * + */ + +#ifndef _SWCR_H +#define _SWCR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "nic_cmd_event.h" + +#if 0 +extern SWCR_MAP_ENTRY_T g_arRlmArSwCrMap[]; +#endif +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define SWCR_VAR(x) ((VOID *)&x) +#define SWCR_FUNC(x) ((VOID *)x) + +#define SWCR_T_FUNC BIT(7) + +#define SWCR_L_32 3 +#define SWCR_L_16 2 +#define SWCR_L_8 1 + +#define SWCR_READ 0 +#define SWCR_WRITE 1 + +#define SWCR_MAP_NUM(x) (sizeof(x)/sizeof(x[0])) + +#define SWCR_CR_NUM 7 + +#define SWCR_GET_RW_INDEX(action, rw, index) \ +do { \ + index = action & 0x7F; \ + rw = action >> 7; \ +} while (0) + +extern UINT_32 g_au4SwCr[]; /*: 0: command other: data */ + +typedef VOID(*PFN_SWCR_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); +typedef VOID(*PFN_CMD_RW_T) (P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); + +typedef struct _SWCR_MAP_ENTRY_T { + UINT_16 u2Type; + PVOID u4Addr; +} SWCR_MAP_ENTRY_T, *P_SWCR_MAP_ENTRY_T; + +typedef struct _SWCR_MOD_MAP_ENTRY_T { + UINT_8 ucMapNum; + P_SWCR_MAP_ENTRY_T prSwCrMap; +} SWCR_MOD_MAP_ENTRY_T, *P_SWCR_MOD_MAP_ENTRY_T; + +typedef enum _ENUM_SWCR_DBG_TYPE_T { + SWCR_DBG_TYPE_ALL = 0, + SWCR_DBG_TYPE_TXRX, + SWCR_DBG_TYPE_RX_RATES, + SWCR_DBG_TYPE_PS, + SWCR_DBG_TYPE_NUM +} ENUM_SWCR_DBG_TYPE_T; + +typedef enum _ENUM_SWCR_DBG_ALL_T { + SWCR_DBG_ALL_TX_CNT = 0, + SWCR_DBG_ALL_TX_BCN_CNT, + SWCR_DBG_ALL_TX_FAILED_CNT, + SWCR_DBG_ALL_TX_RETRY_CNT, + SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT, + SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT, + SWCR_DBG_ALL_TX_MGNT_DROP_CNT, + SWCR_DBG_ALL_TX_ERROR_CNT, + + SWCR_DBG_ALL_RX_CNT, + SWCR_DBG_ALL_RX_DROP_CNT, + SWCR_DBG_ALL_RX_DUP_DROP_CNT, + SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT, + SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT, + + SWCR_DBG_ALL_RX_FCSERR_CNT, + SWCR_DBG_ALL_RX_FIFOFULL_CNT, + SWCR_DBG_ALL_RX_PFDROP_CNT, + + SWCR_DBG_ALL_PWR_PS_POLL_CNT, + SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT, + SWCR_DBG_ALL_PWR_BCN_IND_CNT, + SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT, + SWCR_DBG_ALL_PWR_PM_STATE0, + SWCR_DBG_ALL_PWR_PM_STATE1, + SWCR_DBG_ALL_PWR_CUR_PS_PROF0, + SWCR_DBG_ALL_PWR_CUR_PS_PROF1, + + SWCR_DBG_ALL_AR_STA0_RATE, + SWCR_DBG_ALL_AR_STA0_BWGI, + SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI, + + SWCR_DBG_ALL_ROAMING_ENABLE, + SWCR_DBG_ALL_ROAMING_ROAM_CNT, + SWCR_DBG_ALL_ROAMING_INT_CNT, + + SWCR_DBG_ALL_BB_RX_MDRDY_CNT, + SWCR_DBG_ALL_BB_RX_FCSERR_CNT, + SWCR_DBG_ALL_BB_CCK_PD_CNT, + SWCR_DBG_ALL_BB_OFDM_PD_CNT, + SWCR_DBG_ALL_BB_CCK_SFDERR_CNT, + SWCR_DBG_ALL_BB_CCK_SIGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT, + SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT, + + SWCR_DBG_ALL_NUM +} ENUM_SWCR_DBG_ALL_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +void testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1); +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Support Debug */ +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl); +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam); +VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data); + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType); +VOID swCrDebugInit(P_ADAPTER_T prAdapter); +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout); +VOID swCrDebugUninit(P_ADAPTER_T prAdapter); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h new file mode 100644 index 0000000000000..3b6991131d058 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/tdls.h @@ -0,0 +1,262 @@ +/* +** Id: include/tdls.h#1 +*/ + +/*! \file "tdls.h" + \brief This file contains the internal used in TDLS modules + for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: tdls.h + * + * 11 18 2013 vend_samp.lin + * NULL + * Initial version. + * + ** + */ + +#ifndef _TDLS_H +#define _TDLS_H + +#if (CFG_SUPPORT_TDLS == 1) + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define TDLS_CFG_CMD_TEST 1 +#define TDLS_CFG_HT_SUP 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); +extern BOOLEAN flgTdlsTestExtCapElm; +extern UINT8 aucTdlsTestExtCapElm[]; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +typedef struct _TDLS_LINK_HIS_OTHERS_T { + BOOLEAN fgIsHt; /* TRUE: HT device */ + +} TDLS_LINK_HIS_OTHERS_T; + +/* command */ +typedef enum _TDLS_CMD_ID { + TDLS_CMD_TEST_TX_FRAME = 0x00, + TDLS_CMD_TEST_RCV_FRAME = 0x01, + TDLS_CMD_TEST_PEER_ADD = 0x02, + TDLS_CMD_TEST_PEER_UPDATE = 0x03, + TDLS_CMD_TEST_DATA_FRAME = 0x04, + TDLS_CMD_TEST_RCV_NULL = 0x05, + TDLS_CMD_MIB_UPDATE = 0x06, + TDLS_CMD_TEST_SKIP_TX_FAIL = 0x07, + TDLS_CMD_UAPSD_CONF = 0x08, + TDLS_CMD_CH_SW_CONF = 0x09, + TDLS_CMD_TEST_SKIP_KEEP_ALIVE = 0x0a, + TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT = 0x0b, + TDLS_CMD_TEST_TX_TDLS_FRAME = 0x0c, + TDLS_CMD_TEST_PROHIBIT_SET_IN_AP = 0x0d, + TDLS_CMD_TEST_SCAN_DISABLE = 0x0e, + TDLS_CMD_TEST_DATA_FRAME_CONT = 0x0f, + TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP = 0x10, + TDLS_CMD_SETUP_CONF = 0x11, + TDLS_CMD_INFO = 0x12, + TDLS_CMD_TEST_DELAY = 0x13, + TDLS_CMD_KEY_INFO = 0x14, + TDLS_CMD_TEST_PTI_TX_FAIL = 0x15 +} TDLS_CMD_ID; + +typedef enum _TDLS_EVENT_HOST_ID { + TDLS_HOST_EVENT_TEAR_DOWN = 0x00, /* TDLS_EVENT_HOST_SUBID_TEAR_DOWN */ + TDLS_HOST_EVENT_TX_DONE, + TDLS_HOST_EVENT_FME_STATUS, /* TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME */ + TDLS_HOST_EVENT_STATISTICS +} TDLS_EVENT_HOST_ID; + +typedef enum _TDLS_EVENT_HOST_SUBID_TEAR_DOWN { + TDLS_HOST_EVENT_TD_PTI_TIMEOUT = 0x00, + TDLS_HOST_EVENT_TD_AGE_TIMEOUT, + TDLS_HOST_EVENT_TD_PTI_SEND_FAIL, + TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL, + TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX, + TDLS_HOST_EVENT_TD_NON_STATE3, + TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN +} TDLS_EVENT_HOST_SUBID_TEAR_DOWN; + +typedef enum _TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME { + TDLS_HOST_EVENT_SF_BA, + TDLS_HOST_EVENT_SF_BA_OK, + TDLS_HOST_EVENT_SF_BA_DECLINE, + TDLS_HOST_EVENT_SF_BA_PEER, + TDLS_HOST_EVENT_SF_BA_RSP_OK, + TDLS_HOST_EVENT_SF_BA_RSP_DECLINE +} TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME; + +/* payload specific type in the LLC/SNAP header */ +#define TDLS_FRM_PAYLOAD_TYPE 2 + +#define TDLS_FRM_CATEGORY 12 + +typedef enum _TDLS_FRM_ACTION_ID { + TDLS_FRM_ACTION_SETUP_REQ = 0x00, + TDLS_FRM_ACTION_SETUP_RSP, + TDLS_FRM_ACTION_CONFIRM, + TDLS_FRM_ACTION_TEARDOWN, + TDLS_FRM_ACTION_PTI, + TDLS_FRM_ACTION_CHAN_SWITCH_REQ, + TDLS_FRM_ACTION_CHAN_SWITCH_RSP, + TDLS_FRM_ACTION_PEER_PSM_REQ, + TDLS_FRM_ACTION_PEER_PSM_RSP, + TDLS_FRM_ACTION_PTI_RSP, /* 0x09 */ + TDLS_FRM_ACTION_DISCOVERY_REQ, + + TDLS_FRM_ACTION_EVENT_TEAR_DOWN_TO_SUPPLICANT = 0x30, + + TDLS_FRM_DATA_TEST_DATA = 0x80 +} TDLS_FRM_ACTION_ID; + +#define TDLS_FRM_ACTION_DISCOVERY_RESPONSE 14 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* 7.3.2.62 Link Identifier element */ +#define ELEM_ID_LINK_IDENTIFIER 101 +#define ELEM_LEN_LINK_IDENTIFIER 18 + +typedef struct _IE_LINK_IDENTIFIER_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aBSSID[6]; + UINT_8 aInitiator[6]; + UINT_8 aResponder[6]; +} __KAL_ATTRIB_PACKED__ IE_LINK_IDENTIFIER_T; + +#define TDLS_LINK_IDENTIFIER_IE(__ie__) ((IE_LINK_IDENTIFIER_T *)(__ie__)) + +/* test command use */ +typedef struct _PARAM_CUSTOM_TDLS_CMD_STRUCT_T { + + UINT_8 ucFmeType; /* TDLS_FRM_ACTION_ID */ + + UINT_8 ucToken; + UINT_16 u2Cap; + + /* bit0: TDLS, bit1: Peer U-APSD Buffer, bit2: Channel Switching */ +#define TDLS_EX_CAP_PEER_UAPSD BIT(0) +#define TDLS_EX_CAP_CHAN_SWITCH BIT(1) +#define TDLS_EX_CAP_TDLS BIT(2) + UINT_8 ucExCap; + + UINT_8 arSupRate[4]; + UINT_8 arSupChan[4]; + + UINT_32 u4Timeout; + +#define TDLS_FME_MAC_ADDR_LEN 6 + UINT_8 arRspAddr[TDLS_FME_MAC_ADDR_LEN]; + UINT_8 arBssid[TDLS_FME_MAC_ADDR_LEN]; + +/* + Linux Kernel-3.10 + struct station_parameters { + const u8 *supported_rates; + struct net_device *vlan; + u32 sta_flags_mask, sta_flags_set; + u32 sta_modify_mask; + int listen_interval; + u16 aid; + u8 supported_rates_len; + u8 plink_action; + u8 plink_state; + const struct ieee80211_ht_cap *ht_capa; + const struct ieee80211_vht_cap *vht_capa; + u8 uapsd_queues; + u8 max_sp; + enum nl80211_mesh_power_mode local_pm; + u16 capability; + const u8 *ext_capab; + u8 ext_capab_len; + }; +*/ + struct ieee80211_ht_cap rHtCapa; + struct ieee80211_vht_cap rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + struct station_parameters rPeerInfo; + +} PARAM_CUSTOM_TDLS_CMD_STRUCT_T; + +typedef struct _TDLS_MGMT_TX_INFO { + UINT8 aucPeer[6]; + UINT8 ucActionCode; + UINT8 ucDialogToken; + UINT16 u2StatusCode; + UINT32 u4SecBufLen; + UINT8 aucSecBuf[1000]; +} TDLS_MGMT_TX_INFO; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* check any TDLS link */ +#define TDLS_IS_NO_LINK_GOING(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt == 0) + +/* increase TDLS link count */ +#define TDLS_LINK_INCREASE(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt++) + +/* decrease TDLS link count */ +#define TDLS_LINK_DECREASE(__GlueInfo__) \ +do { \ + if ((__GlueInfo__)->rTdlsLink.cLinkCnt > 0) \ + (__GlueInfo__)->rTdlsLink.cLinkCnt--; \ +} while (0) + +/* get TDLS link count */ +#define TDLS_LINK_COUNT(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt) + +/* reset TDLS link count */ +#define TDLS_LINK_COUNT_RESET(__GlueInfo__) \ + ((__GlueInfo__)->rTdlsLink.cLinkCnt = 0) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Note: these functions are used only in tdls module, not other modules */ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt); + +TDLS_STATUS +TdlsDataFrameSend(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h new file mode 100644 index 0000000000000..12c9359f2e8f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wapi.h @@ -0,0 +1,104 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wapi.h#1 +*/ + +/*! \file wapi.h + \brief The wapi related define, macro and structure are described here. +*/ + +/* +** Log: wapi.h + * + * 07 20 2010 wh.su + * + * . + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the wapi function name and adding the generate wapi ie function + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some wapi structure define + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** \main\maintrunk.MT5921\1 2009-10-09 17:06:29 GMT mtk01088 +** +*/ + +#ifndef _WAPI_H +#define _WAPI_H + +#if CFG_SUPPORT_WAPI + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define WAPI_CIPHER_SUITE_WPI 0x01721400 /* WPI_SMS4 */ +#define WAPI_AKM_SUITE_802_1X 0x01721400 /* WAI */ +#define WAPI_AKM_SUITE_PSK 0x02721400 /* WAI_PSK */ + +#define ELEM_ID_WAPI 68 /* WAPI IE */ + +#define WAPI_IE(fp) ((P_WAPI_INFO_ELEM_T) fp) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID wapiGenerateWAPIIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo); + +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss); + +/* BOOLEAN */ +/* wapiUpdateTxKeyIdx ( */ +/* IN P_STA_RECORD_T prStaRec, */ +/* IN UINT_8 ucWlanIdx */ +/* ); */ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif +#endif /* _WAPI_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h new file mode 100644 index 0000000000000..5dc969f1cc05b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wlan_typedef.h @@ -0,0 +1,87 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/mgmt/wlan_typedef.h#1 +*/ + +/*! \file wlan_typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to all MGMT Protocol Stack. +*/ + +/* +** Log: wlan_typedef.h +*/ + +#ifndef _WLAN_TYPEDEF_H +#define _WLAN_TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for BSS_INFO_T structure, to describe the attributes used in a + * common BSS. + */ +typedef struct _BSS_INFO_T BSS_INFO_T, *P_BSS_INFO_T; + +typedef BSS_INFO_T AIS_BSS_INFO_T, *P_AIS_BSS_INFO_T; +typedef BSS_INFO_T P2P_BSS_INFO_T, *P_P2P_BSS_INFO_T; +typedef BSS_INFO_T BOW_BSS_INFO_T, *P_BOW_BSS_INFO_T; + +typedef struct _AIS_SPECIFIC_BSS_INFO_T AIS_SPECIFIC_BSS_INFO_T, *P_AIS_SPECIFIC_BSS_INFO_T; +typedef struct _P2P_SPECIFIC_BSS_INFO_T P2P_SPECIFIC_BSS_INFO_T, *P_P2P_SPECIFIC_BSS_INFO_T; +typedef struct _BOW_SPECIFIC_BSS_INFO_T BOW_SPECIFIC_BSS_INFO_T, *P_BOW_SPECIFIC_BSS_INFO_T; +/* CFG_SUPPORT_WFD */ +typedef struct _WFD_CFG_SETTINGS_T WFD_CFG_SETTINGS_T, *P_WFD_CFG_SETTINGS_T; + +typedef struct _WFD_DBG_CFG_SETTINGS_T WFD_DBG_CFG_SETTINGS_T, *P_WFD_DBG_CFG_SETTINGS_T; + +/* BSS related structures */ +/* Type definition for BSS_DESC_T structure, to describe parameter sets of a particular BSS */ +typedef struct _BSS_DESC_T BSS_DESC_T, *P_BSS_DESC_T, **PP_BSS_DESC_T; + +#if CFG_SUPPORT_HOTSPOT_2_0 +typedef struct _HS20_INFO_T HS20_INFO_T, *P_HS20_INFO_T; +#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _WLAN_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h new file mode 100644 index 0000000000000..09bc0b5d5151b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/mgmt/wnm.h @@ -0,0 +1,95 @@ +/* +** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/include/mgmt/wnm.h#1 +*/ + +/*! \file wnm.h + \brief This file contains the IEEE 802.11 family related 802.11v network management + for MediaTek 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wnm.h + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * +*/ + +#ifndef _WNM_H +#define _WNM_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _TIMINGMSMT_PARAM_T { + BOOLEAN fgInitiator; + UINT_8 ucTrigger; + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ + UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ + UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ +} TIMINGMSMT_PARAM_T, *P_TIMINGMSMT_PARAM_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +WLAN_STATUS +wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +VOID +wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler); + +VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA); + +#define WNM_UNIT_TEST 1 + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WNM_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h new file mode 100644 index 0000000000000..d34f2c9c36a8b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/adapter.h @@ -0,0 +1,1506 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/adapter.h#3 +*/ + +/*! \file adapter.h + \brief Definition of internal data structure for driver manipulation. + + In this file we define the internal data structure - ADAPTER_T which stands + for MiniPort ADAPTER(From Windows point of view) or stands for Network ADAPTER. +*/ + +/* +** Log: adapter.h +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have +** connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration + * with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration + * corresponding to network type. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve inorder issue under AP mode. + * + * data frame may TX before assoc response frame. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Remove ERP member in adapter structure + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * Action frame callback for GO Device Discoverability Req. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically + * continuous memory shortage after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce + * physically continuous memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 yuche.tsai + * [WCXRP00000533] [Volunteer Patch][MT6620][Driver] Provide a P2P function API for Legacy WiFi to query AP mode. + * Provide an API for Legacy WiFi to query the operation mode.. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as + * initial RSSI right after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid + * using a uninitialized MAC-RX RCPI. + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Change GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module + * with structure miss-align pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to + * target station for AAA module. + * Provide disconnect function for AAA module. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 george.huang + * [WCXRP00000400] [MT6620 Wi-Fi] support CTIA power mode setting + * Support CTIA power mode setting. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Add CWMin CWMax for AP to generate IE. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] + * Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Add a common IE buffer in P2P INFO structure. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 cp.wu + * NULL + * restore configuration as before. + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 yuche.tsai + * NULL + * Add an intend mode for BSS info. + * It is used to let P2P BSS Info to know which OP Mode it is going to become. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 02 2010 cp.wu + * NULL + * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 yuche.tsai + * + * Remove BSS info which is redonedent in Wifi Var.. + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P FSM Info in adapter. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P related field, additional include p2p_fsm.h if p2p is enabled. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 04 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * reserve field of privacy filter and RTS threshold setting. + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * 2) command sequence number is now increased atomically + * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move ucCmdSeqNum as instance variable + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * 4. correct some HAL implementation + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * and result is retrieved by get ATInfo instead + * * * 2) add 4 counter for recording aggregation statistics + * + * 12 28 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate redundant variables for connection_state +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-16 18:02:03 GMT mtk02752 +** add external reference to avoid compilation error +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:40:26 GMT mtk02752 +** eliminate unused member +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-08 17:36:08 GMT mtk02752 +** add RF test data members into P_ADAPTER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:45 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-28 10:29:57 GMT mtk01461 +** Add read WTSR for SDIO_STATUS_ENHANCE mode +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:37:35 GMT mtk01461 +** Add prPendingCmdInfoOfOID for temporarily saving the CMD_INFO_T before en-queue to rCmdQueue +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:57:51 GMT mtk01461 +** Add MGMT Buffer Info +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:34:12 GMT mtk01461 +** Add SW pre test CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:41:48 GMT mtk01461 +** Add fgIsWmmAssoc flag for TC assignment +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:51 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:51:52 GMT mtk01426 +** Add #if CFG_SDIO_RX_ENHANCE related data structure +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:17 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _ADAPTER_H +#define _ADAPTER_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if CFG_SUPPORT_HOTSPOT_2_0 +#include "hs20.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T SDIO_CTRL_T, *P_SDIO_CTRL_T; + +typedef struct _WLAN_INFO_T { + PARAM_BSSID_EX_T rCurrBssId; + + /* Scan Result */ + PARAM_BSSID_EX_T arScanResult[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 apucScanResultIEs[CFG_MAX_NUM_BSS_LIST]; + UINT_32 u4ScanResultNum; + + /* IE pool for Scanning Result */ + UINT_8 aucScanIEBuf[CFG_MAX_COMMON_IE_BUF_LEN]; + UINT_32 u4ScanIEBufferUsage; + + OS_SYSTIME u4SysTime; + + /* connection parameter (for Ad-Hoc) */ + UINT_16 u2BeaconPeriod; + UINT_16 u2AtimWindow; + + PARAM_RATES eDesiredRates; + CMD_LINK_ATTRIB eLinkAttr; +/* CMD_PS_PROFILE_T ePowerSaveMode; */ + CMD_PS_PROFILE_T arPowerSaveMode[NETWORK_TYPE_INDEX_NUM]; + + /* trigger parameter */ + ENUM_RSSI_TRIGGER_TYPE eRssiTriggerType; + PARAM_RSSI rRssiTriggerValue; + + /* Privacy Filter */ + ENUM_PARAM_PRIVACY_FILTER_T ePrivacyFilter; + + /* RTS Threshold */ + PARAM_RTS_THRESHOLD eRtsThreshold; + + /* Network Type */ + UINT_8 ucNetworkType; + + /* Network Type In Use */ + UINT_8 ucNetworkTypeInUse; + +} WLAN_INFO_T, *P_WLAN_INFO_T; + +/* Session for CONNECTION SETTINGS */ +typedef struct _CONNECTION_SETTINGS_T { + + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + + UINT_8 ucDelayTimeOfDisconnectEvent; + + BOOLEAN fgIsConnByBssidIssued; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + + BOOLEAN fgIsConnReqIssued; + BOOLEAN fgIsDisconnectedByNonRequest; + + UINT_8 ucSSIDLen; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + + ENUM_PARAM_OP_MODE_T eOPMode; + + ENUM_PARAM_CONNECTION_POLICY_T eConnectionPolicy; + + ENUM_PARAM_AD_HOC_MODE_T eAdHocMode; + + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + + BOOLEAN fgIsScanReqIssued; + + /* MIB attributes */ + UINT_16 u2BeaconPeriod; + + UINT_16 u2RTSThreshold; /* User desired setting */ + + UINT_16 u2DesiredNonHTRateSet; /* User desired setting */ + + UINT_8 ucAdHocChannelNum; /* For AdHoc */ + + ENUM_BAND_T eAdHocBand; /* For AdHoc */ + + UINT_32 u4FreqInKHz; /* Center frequency */ + + /* ATIM windows using for IBSS power saving function */ + UINT_16 u2AtimWindow; + + /* Features */ + BOOLEAN fgIsEnableRoaming; + + BOOLEAN fgIsAdHocQoSEnable; + + ENUM_PARAM_PHY_CONFIG_T eDesiredPhyConfig; + + /* Used for AP mode for desired channel and bandwidth */ + UINT_16 u2CountryCode; + UINT_16 u2CountryCodeBakup; + UINT_8 uc2G4BandwidthMode; /* 20/40M or 20M only */ + UINT_8 uc5GBandwidthMode; /* 20/40M or 20M only */ + + BOOLEAN fgTxShortGIDisabled; + BOOLEAN fgRxShortGIDisabled; + +#if CFG_SUPPORT_802_11D + BOOLEAN fgMultiDomainCapabilityEnabled; +#endif /* CFG_SUPPORT_802_11D */ + +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgWapiMode; + UINT_32 u4WapiSelectedGroupCipher; + UINT_32 u4WapiSelectedPairwiseCipher; + UINT_32 u4WapiSelectedAKMSuite; +#endif + + /* CR1486, CR1640 */ + /* for WPS, disable the privacy check for AP selection policy */ + BOOLEAN fgPrivacyCheckDisable; + + /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 bmfgApsdEnAc; + + /* for RSN info store, when upper layer set rsn info */ + RSN_INFO_T rRsnInfo; + +} CONNECTION_SETTINGS_T, *P_CONNECTION_SETTINGS_T; + +struct _BSS_INFO_T { + + ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ + ENUM_PARAM_MEDIA_STATE_T eConnectionStateIndicated; /* The Media State that report to HOST */ + + ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ +#if CFG_ENABLE_WIFI_DIRECT + ENUM_OP_MODE_T eIntendOPMode; +#endif + + BOOLEAN fgIsNetActive; /* TRUE if this network has been activated */ + + UINT_8 ucNetTypeIndex; /* ENUM_NETWORK_TYPE_INDEX_T */ + + UINT_8 ucReasonOfDisconnect; /* Used by media state indication */ + + UINT_8 ucSSIDLen; /* Length of SSID */ + +#if CFG_ENABLE_WIFI_DIRECT + ENUM_HIDDEN_SSID_TYPE_T eHiddenSsidType; /* For Hidden SSID usage. */ +#endif + + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; /* SSID used in this BSS */ + + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* The BSSID of the associated BSS */ + + UINT_8 aucOwnMacAddr[MAC_ADDR_LEN]; /* Owned MAC Address used in this BSS */ + + P_STA_RECORD_T prStaRecOfAP; /* For Infra Mode, and valid only if + * eConnectionState == MEDIA_STATE_CONNECTED + */ + LINK_T rStaRecOfClientList; /* For IBSS/AP Mode, all known STAs in current BSS */ + + UINT_16 u2CapInfo; /* Change Detection */ + + UINT_16 u2BeaconInterval; /* The Beacon Interval of this BSS */ + + UINT_16 u2ATIMWindow; /* For IBSS Mode */ + + UINT_16 u2AssocId; /* For Infra Mode, it is the Assoc ID assigned by AP. + */ + + UINT_8 ucDTIMPeriod; /* For Infra/AP Mode */ + + UINT_8 ucDTIMCount; /* For AP Mode, it is the DTIM value we should carried in + * the Beacon of next TBTT. + */ + + UINT_8 ucPhyTypeSet; /* Available PHY Type Set of this peer + * (This is deduced from received BSS_DESC_T) + */ + + UINT_8 ucNonHTBasicPhyType; /* The Basic PHY Type Index, used to setup Phy Capability */ + + UINT_8 ucConfigAdHocAPMode; /* The configuration of AdHoc/AP Mode. e.g. 11g or 11b */ + + UINT_8 ucBeaconTimeoutCount; /* For Infra/AP Mode, it is a threshold of Beacon Lost Count to + confirm connection was lost */ + + BOOLEAN fgHoldSameBssidForIBSS; /* For IBSS Mode, to keep use same BSSID to extend the life cycle of an IBSS */ + + BOOLEAN fgIsBeaconActivated; /* For AP/IBSS Mode, it is used to indicate that Beacon is sending */ + + P_MSDU_INFO_T prBeacon; /* For AP/IBSS Mode - Beacon Frame */ + + BOOLEAN fgIsIBSSMaster; /* For IBSS Mode - To indicate that we can reply ProbeResp Frame. + In current TBTT interval */ + + BOOLEAN fgIsShortPreambleAllowed; /* From Capability Info. of AssocResp Frame + AND of Beacon/ProbeResp Frame */ + BOOLEAN fgUseShortPreamble; /* Short Preamble is enabled in current BSS. */ + BOOLEAN fgUseShortSlotTime; /* Short Slot Time is enabled in current BSS. */ + + UINT_16 u2OperationalRateSet; /* Operational Rate Set of current BSS */ + UINT_16 u2BSSBasicRateSet; /* Basic Rate Set of current BSS */ + + UINT_8 ucAllSupportedRatesLen; /* Used for composing Beacon Frame in AdHoc or AP Mode */ + UINT_8 aucAllSupportedRates[RATE_NUM]; + + UINT_8 ucAssocClientCnt; /* TODO(Kevin): Number of associated clients */ + + BOOLEAN fgIsProtection; + BOOLEAN fgIsQBSS; /* fgIsWmmBSS; *//* For Infra/AP/IBSS Mode, it is used to indicate if we support WMM in + * current BSS. */ + BOOLEAN fgIsNetAbsent; /* TRUE: BSS is absent, FALSE: BSS is present */ + + UINT_32 u4RsnSelectedGroupCipher; + UINT_32 u4RsnSelectedPairwiseCipher; + UINT_32 u4RsnSelectedAKMSuite; + UINT_16 u2RsnSelectedCapInfo; + + /*------------------------------------------------------------------------*/ + /* Power Management related information */ + /*------------------------------------------------------------------------*/ + PM_PROFILE_SETUP_INFO_T rPmProfSetupInfo; + + /*------------------------------------------------------------------------*/ + /* WMM/QoS related information */ + /*------------------------------------------------------------------------*/ + UINT_8 ucWmmParamSetCount; /* Used to detect the change of EDCA parameters. For AP mode, + the value is used in WMM IE */ + + AC_QUE_PARMS_T arACQueParms[WMM_AC_INDEX_NUM]; + + UINT_8 aucCWminLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWminLog2 */ + UINT_8 aucCWmaxLog2ForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the CWmaxLog2 */ + AC_QUE_PARMS_T arACQueParmsForBcast[WMM_AC_INDEX_NUM]; /* For AP mode, broadcast the value */ + + /*------------------------------------------------------------------------*/ + /* 802.11n HT operation IE when (prStaRec->ucPhyTypeSet & PHY_TYPE_BIT_HT) */ + /* is true. They have the same definition with fields of */ + /* information element (CM) */ + /*------------------------------------------------------------------------*/ + ENUM_BAND_T eBand; + UINT_8 ucPrimaryChannel; + UINT_8 ucHtOpInfo1; + UINT_16 u2HtOpInfo2; + UINT_16 u2HtOpInfo3; + + /*------------------------------------------------------------------------*/ + /* Required protection modes (CM) */ + /*------------------------------------------------------------------------*/ + BOOLEAN fgErpProtectMode; + ENUM_HT_PROTECT_MODE_T eHtProtectMode; + ENUM_GF_MODE_T eGfOperationMode; + ENUM_RIFS_MODE_T eRifsOperationMode; + + BOOLEAN fgObssErpProtectMode; /* GO only */ + ENUM_HT_PROTECT_MODE_T eObssHtProtectMode; /* GO only */ + ENUM_GF_MODE_T eObssGfOperationMode; /* GO only */ + BOOLEAN fgObssRifsOperationMode; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* OBSS to decide if 20/40M bandwidth is permitted. */ + /* The first member indicates the following channel list length. */ + /*------------------------------------------------------------------------*/ + BOOLEAN fgAssoc40mBwAllowed; + BOOLEAN fg40mBwAllowed; + ENUM_CHNL_EXT_T eBssSCO; /* Real setting for HW + * 20/40M AP mode will always set 40M, + * but its OP IE can be changed. + */ + UINT_8 auc2G_20mReqChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_NonHtChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_PriChnlList[CHNL_LIST_SZ_2G + 1]; + UINT_8 auc2G_SecChnlList[CHNL_LIST_SZ_2G + 1]; + + UINT_8 auc5G_20mReqChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_NonHtChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_PriChnlList[CHNL_LIST_SZ_5G + 1]; + UINT_8 auc5G_SecChnlList[CHNL_LIST_SZ_5G + 1]; + + TIMER_T rObssScanTimer; + UINT_16 u2ObssScanInterval; /* in unit of sec */ + + BOOLEAN fgObssActionForcedTo20M; /* GO only */ + BOOLEAN fgObssBeaconForcedTo20M; /* GO only */ + + /*------------------------------------------------------------------------*/ + /* HW Related Fields (Kevin) */ + /*------------------------------------------------------------------------*/ + UINT_8 ucHwDefaultFixedRateCode; /* The default rate code copied to MAC TX Desc */ + UINT_16 u2HwLPWakeupGuardTimeUsec; + + UINT_8 ucBssFreeQuota; /* The value is updated from FW */ +#if CFG_ENABLE_GTK_FRAME_FILTER + P_IPV4_NETWORK_ADDRESS_LIST prIpV4NetAddrList; +#endif + UINT_16 u2DeauthReason; + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsProhibited; /* TRUE: AP prohibits TDLS links */ + BOOLEAN fgTdlsIsChSwProhibited; /* TRUE: AP prohibits TDLS chan switch */ +#endif /* CFG_SUPPORT_TDLS */ +}; + +struct _AIS_SPECIFIC_BSS_INFO_T { + UINT_8 ucRoamingAuthTypes; /* This value indicate the roaming type used in AIS_JOIN */ + + BOOLEAN fgIsIBSSActive; + + /*! \brief Global flag to let arbiter stay at standby and not connect to any network */ + BOOLEAN fgCounterMeasure; + UINT_8 ucWEPDefaultKeyID; + BOOLEAN fgTransmitKeyExist; /* Legacy wep Transmit key exist or not */ + + /* While Do CounterMeasure procedure, check the EAPoL Error report have send out */ + BOOLEAN fgCheckEAPoLTxDone; + + UINT_32 u4RsnaLastMICFailTime; + + /* Stored the current bss wpa rsn cap filed, used for roaming policy */ + /* UINT_16 u2RsnCap; */ + TIMER_T rPreauthenticationTimer; + + /* By the flow chart of 802.11i, + wait 60 sec before associating to same AP + or roaming to a new AP + or sending data in IBSS, + keep a timer for handle the 60 sec counterMeasure */ + TIMER_T rRsnaBlockTrafficTimer; + TIMER_T rRsnaEAPoLReportTimeoutTimer; + + /* For Keep the Tx/Rx Mic key for TKIP SW Calculate Mic */ + /* This is only one for AIS/AP */ + UINT_8 aucTxMicKey[8]; + UINT_8 aucRxMicKey[8]; + + /* Buffer for WPA2 PMKID */ + /* The PMKID cache lifetime is expire by media_disconnect_indication */ + UINT_32 u4PmkidCandicateCount; + PMKID_CANDICATE_T arPmkidCandicate[CFG_MAX_PMKID_CACHE]; + UINT_32 u4PmkidCacheCount; + PMKID_ENTRY_T arPmkidCache[CFG_MAX_PMKID_CACHE]; + BOOLEAN fgIndicatePMKID; +#if CFG_SUPPORT_802_11W + BOOLEAN fgMgmtProtection; + UINT_32 u4SaQueryStart; + UINT_32 u4SaQueryCount; + UINT_8 ucSaQueryTimedOut; + PUINT_8 pucSaQueryTransId; + TIMER_T rSaQueryTimer; + BOOLEAN fgBipKeyInstalled; +#endif +}; + +struct _BOW_SPECIFIC_BSS_INFO_T { + UINT_16 u2Reserved; /* Reserved for Data Type Check */ +}; + +#if CFG_SLT_SUPPORT +typedef struct _SLT_INFO_T { + + P_BSS_DESC_T prPseudoBssDesc; + UINT_16 u2SiteID; + UINT_8 ucChannel2G4; + UINT_8 ucChannel5G; + BOOLEAN fgIsDUT; + UINT_32 u4BeaconReceiveCnt; + /* ///////Deprecated///////// */ + P_STA_RECORD_T prPseudoStaRec; +} SLT_INFO_T, *P_SLT_INFO_T; +#endif + +/* Major member variables for WiFi FW operation. + Variables within this region will be ready for access after WIFI function is enabled. +*/ +typedef struct _WIFI_VAR_T { + BOOLEAN fgIsRadioOff; + + BOOLEAN fgIsEnterD3ReqIssued; + + BOOLEAN fgDebugCmdResp; + + CONNECTION_SETTINGS_T rConnSettings; + + SCAN_INFO_T rScanInfo; + +#if CFG_SUPPORT_ROAMING + ROAMING_INFO_T rRoamingInfo; +#endif /* CFG_SUPPORT_ROAMING */ + + AIS_FSM_INFO_T rAisFsmInfo; + + ENUM_PWR_STATE_T aePwrState[NETWORK_TYPE_INDEX_NUM]; + + BSS_INFO_T arBssInfo[NETWORK_TYPE_INDEX_NUM]; + + AIS_SPECIFIC_BSS_INFO_T rAisSpecificBssInfo; + +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings; + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + P_P2P_FSM_INFO_T prP2pFsmInfo; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + BOW_SPECIFIC_BSS_INFO_T rBowSpecificBssInfo; + BOW_FSM_INFO_T rBowFsmInfo; +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + DEAUTH_INFO_T arDeauthInfo[MAX_DEAUTH_INFO_COUNT]; + + /* Current Wi-Fi Settings and Flags */ + UINT_8 aucPermanentAddress[MAC_ADDR_LEN]; + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + UINT_8 aucDeviceAddress[MAC_ADDR_LEN]; + UINT_8 aucInterfaceAddress[MAC_ADDR_LEN]; + + UINT_8 ucAvailablePhyTypeSet; + + ENUM_PHY_TYPE_INDEX_T eNonHTBasicPhyType2G4; /* Basic Phy Type used by SCN according + * to the set of Available PHY Types + */ + + ENUM_PARAM_PREAMBLE_TYPE_T ePreambleType; + ENUM_REGISTRY_FIXED_RATE_T eRateSetting; + + BOOLEAN fgIsShortSlotTimeOptionEnable; + /* User desired setting, but will honor the capability of AP */ + + BOOLEAN fgEnableJoinToHiddenSSID; + BOOLEAN fgSupportWZCDisassociation; + + BOOLEAN fgSupportQoS; + BOOLEAN fgSupportAmpduTx; + BOOLEAN fgSupportAmpduRx; + BOOLEAN fgSupportTspec; + BOOLEAN fgSupportUAPSD; + BOOLEAN fgSupportULPSMP; + UINT_8 u8SupportRxSgi20; /* 0: default 1: enable 2:disble */ + UINT_8 u8SupportRxSgi40; + UINT_8 u8SupportRxGf; + UINT_8 u8SupportRxSTBC; +#if CFG_SUPPORT_CFG_FILE + UINT_8 ucApWpsMode; + UINT_8 ucCert11nMode; +#endif +#if CFG_SUPPORT_CE_FCC_TXPWR_LIMIT + UINT_8 ucCeFccTxPwrLimit; + UINT_8 ucCeFccTxPwrLimitCck; + UINT_8 ucCeFccTxPwrLimitOfdmHt20; + UINT_8 ucCeFccTxPwrLimitHt40; +#endif + +#if CFG_SLT_SUPPORT + SLT_INFO_T rSltInfo; +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 + HS20_INFO_T rHS20Info; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + PARAM_GET_CHN_LOAD rChnLoadInfo; +#endif + +} WIFI_VAR_T, *P_WIFI_VAR_T; /* end of _WIFI_VAR_T */ + +/* cnm_timer module */ +typedef struct { + LINK_T rLinkHead; + OS_SYSTIME rNextExpiredSysTime; + KAL_WAKE_LOCK_T rWakeLock; + BOOLEAN fgWakeLocked; +} ROOT_TIMER, *P_ROOT_TIMER; + +/* FW/DRV/NVRAM version information */ +typedef struct { + + /* NVRAM or Registry */ + UINT_16 u2Part1CfgOwnVersion; + UINT_16 u2Part1CfgPeerVersion; + UINT_16 u2Part2CfgOwnVersion; + UINT_16 u2Part2CfgPeerVersion; + + /* Firmware */ + UINT_16 u2FwProductID; + UINT_16 u2FwOwnVersion; + UINT_16 u2FwPeerVersion; + +} WIFI_VER_INFO_T, *P_WIFI_VER_INFO_T; + +#if CFG_ENABLE_WIFI_DIRECT +/* +* p2p function pointer structure +*/ + +typedef struct _P2P_FUNCTION_LINKER { + P2P_REMOVE prP2pRemove; +/* NIC_P2P_MEDIA_STATE_CHANGE prNicP2pMediaStateChange; */ +/* SCAN_UPDATE_P2P_DEVICE_DESC prScanUpdateP2pDeviceDesc; */ +/* P2P_FSM_RUN_EVENT_RX_PROBE_RESPONSE_FRAME prP2pFsmRunEventRxProbeResponseFrame; */ + P2P_GENERATE_P2P_IE prP2pGenerateWSC_IEForBeacon; +/* P2P_CALCULATE_WSC_IE_LEN_FOR_PROBE_RSP prP2pCalculateWSC_IELenForProbeRsp; */ +/* P2P_GENERATE_WSC_IE_FOR_PROBE_RSP prP2pGenerateWSC_IEForProbeRsp; */ +/* SCAN_REMOVE_P2P_BSS_DESC prScanRemoveP2pBssDesc; */ +/* P2P_HANDLE_SEC_CHECK_RSP prP2pHandleSecCheckRsp; */ + P2P_NET_REGISTER prP2pNetRegister; + P2P_NET_UNREGISTER prP2pNetUnregister; + P2P_CALCULATE_P2P_IE_LEN prP2pCalculateP2p_IELenForAssocReq; /* All IEs generated from supplicant. */ + P2P_GENERATE_P2P_IE prP2pGenerateP2p_IEForAssocReq; /* All IEs generated from supplicant. */ +} P2P_FUNCTION_LINKER, *P_P2P_FUNCTION_LINKER; + +#endif + +/* + *State Machine: + *-->STOP: Turn on/off WiFi + *-->DISABLE: Screen was off (wlanHandleSystemSuspend) + *-->ENABLE: Screen was on (wlanHandleSystemResume) + *----->clear DISABLE + *-->RUNNING: Screen was on && Tx/Rx was ongoing (wlanHardStartXmit/kalRxIndicatePkts) +*/ +struct GL_PER_MON_T { + TIMER_T rPerfMonTimer; + ULONG ulPerfMonFlag; + ULONG ulLastTxBytes; + ULONG ulLastRxBytes; + ULONG ulP2PLastTxBytes; + ULONG ulP2PLastRxBytes; + /*in bps*/ + ULONG ulThroughput; + /*in ms*/ + UINT32 u4UpdatePeriod; + UINT32 u4TarPerfLevel; + UINT32 u4CurrPerfLevel; +}; + +/* + * Major ADAPTER structure + * Major data structure for driver operation + */ +struct _ADAPTER_T { + UINT_8 ucRevID; + + UINT_16 u2NicOpChnlNum; + + BOOLEAN fgIsEnableWMM; + BOOLEAN fgIsWmmAssoc; /* This flag is used to indicate that WMM is enable in current BSS */ + + UINT_32 u4OsPacketFilter; /* packet filter used by OS */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_32 u4CSUMFlags; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + ENUM_BAND_T aePreferBand[NETWORK_TYPE_INDEX_NUM]; + + /* ADAPTER flags */ + UINT_32 u4Flags; + UINT_32 u4HwFlags; + + BOOLEAN fgIsRadioOff; + + BOOLEAN fgIsEnterD3ReqIssued; + + UINT_8 aucMacAddress[MAC_ADDR_LEN]; + + ENUM_PHY_TYPE_INDEX_T eCurrentPhyType; /* Current selection basing on the set of Available PHY Types */ + +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + UINT_32 u4CoalescingBufCachedSize; + PUINT_8 pucCoalescingBufCached; +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* Buffer for CMD_INFO_T, Mgt packet and mailbox message */ + BUF_INFO_T rMgtBufInfo; + BUF_INFO_T rMsgBufInfo; + PUINT_8 pucMgtBufCached; + UINT_32 u4MgtBufCachedSize; + UINT_8 aucMsgBuf[MSG_BUFFER_SIZE]; +#if CFG_DBG_MGT_BUF + UINT_32 u4MemAllocDynamicCount; /* Debug only */ + UINT_32 u4MemFreeDynamicCount; /* Debug only */ +#endif + + STA_RECORD_T arStaRec[CFG_STA_REC_NUM]; + + /* Element for TX PATH */ + TX_CTRL_T rTxCtrl; + QUE_T rFreeCmdList; + CMD_INFO_T arHifCmdDesc[CFG_TX_MAX_CMD_PKT_NUM]; + + /* Element for RX PATH */ + RX_CTRL_T rRxCtrl; + + P_SDIO_CTRL_T prSDIOCtrl; + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + /* Element for MT6620 E1 HIFSYS workaround */ + BOOLEAN fgIsClockGatingEnabled; +#endif + + /* Buffer for Authentication Event */ + /* Move to glue layer and refine the kal function */ + /* Reference to rsnGeneratePmkidIndication function at rsn.c */ + UINT_8 aucIndicationEventBuffer[(CFG_MAX_PMKID_CACHE * 20) + 8]; + + UINT_32 u4IntStatus; + + ENUM_ACPI_STATE_T rAcpiState; + + BOOLEAN fgIsIntEnable; + BOOLEAN fgIsIntEnableWithLPOwnSet; + + BOOLEAN fgIsFwOwn; + BOOLEAN fgWiFiInSleepyState; + + UINT_32 u4PwrCtrlBlockCnt; + + QUE_T rPendingCmdQueue; + + P_GLUE_INFO_T prGlueInfo; + + UINT_8 ucCmdSeqNum; + UINT_8 ucTxSeqNum; + +#if 1 /* CFG_SUPPORT_WAPI */ + BOOLEAN fgUseWapi; +#endif + + /* RF Test flags */ + BOOLEAN fgTestMode; + + /* WLAN Info for DRIVER_CORE OID query */ + WLAN_INFO_T rWlanInfo; + +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2PRegistered; + ENUM_NET_REG_STATE_T rP2PNetRegState; + BOOLEAN fgIsWlanLaunched; + P_P2P_INFO_T prP2pInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + OS_SYSTIME rP2pLinkQualityUpdateTime; + BOOLEAN fgIsP2pLinkQualityValid; + EVENT_LINK_QUALITY rP2pLinkQuality; +#endif + + /* FSM Timer */ + TIMER_T rP2pFsmTimeoutTimer; +#endif + + /* Online Scan Option */ + BOOLEAN fgEnOnlineScan; + + /* Online Scan Option */ + BOOLEAN fgDisBcnLostDetection; + + /* MAC address */ + PARAM_MAC_ADDRESS rMyMacAddr; + + /* Wake-up Event for WOL */ + UINT_32 u4WakeupEventEnable; + + /* Event Buffering */ + EVENT_STATISTICS rStatStruct; + OS_SYSTIME rStatUpdateTime; + BOOLEAN fgIsStatValid; + + EVENT_LINK_QUALITY rLinkQuality; + OS_SYSTIME rLinkQualityUpdateTime; + BOOLEAN fgIsLinkQualityValid; + OS_SYSTIME rLinkRateUpdateTime; + BOOLEAN fgIsLinkRateValid; + + /* WIFI_VAR_T */ + WIFI_VAR_T rWifiVar; + + /* MTK WLAN NIC driver IEEE 802.11 MIB */ + IEEE_802_11_MIB_T rMib; + + /* Mailboxs for inter-module communication */ + MBOX_T arMbox[MBOX_ID_TOTAL_NUM]; + + /* Timers for OID Pending Handling */ + TIMER_T rOidTimeoutTimer; + + TIMER_T rReturnIndicatedRfbListTimer; + + /* Root Timer for cnm_timer module */ + ROOT_TIMER rRootTimer; + + /* RLM maintenance */ + ENUM_CHNL_EXT_T eRfSco; + ENUM_SYS_PROTECT_MODE_T eSysProtectMode; + ENUM_GF_MODE_T eSysHtGfMode; + ENUM_RIFS_MODE_T eSysTxRifsMode; + ENUM_SYS_PCO_PHASE_T eSysPcoPhase; + + P_DOMAIN_INFO_ENTRY prDomainInfo; + + /* QM */ + QUE_MGT_T rQM; + + CNM_INFO_T rCnmInfo; + + UINT_32 u4PowerMode; + + UINT_32 u4CtiaPowerMode; + BOOLEAN fgEnCtiaPowerMode; + + UINT_32 fgEnArpFilter; + + UINT_32 u4UapsdAcBmp; + + UINT_32 u4MaxSpLen; + + UINT_32 u4PsCurrentMeasureEn; + + /* Version Information */ + WIFI_VER_INFO_T rVerInfo; + + /* 5GHz support (from F/W) */ + BOOLEAN fgIsHw5GBandDisabled; + BOOLEAN fgEnable5GBand; + BOOLEAN fgIsEepromUsed; + BOOLEAN fgIsEfuseValid; + BOOLEAN fgIsEmbbededMacAddrValid; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + BOOLEAN fgIsPowerLimitTableValid; +#endif + + /* Packet Forwarding Tracking */ + INT_32 i4PendingFwdFrameCount; + +#if CFG_SUPPORT_RDD_TEST_MODE + UINT_8 ucRddStatus; +#endif + + BOOLEAN fgDisStaAgingTimeoutDetection; +#if CFG_SUPPORT_CFG_FILE + P_WLAN_CFG_T prWlanCfg; + WLAN_CFG_T rWlanCfg; +#endif +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + KAL_WAKE_LOCK_T rApWakeLock; +#endif + UINT_32 u4FwCompileFlag0; + UINT_32 u4FwCompileFlag1; + KAL_WAKE_LOCK_T rTxThreadWakeLock; + KAL_WAKE_LOCK_T rAhbIsrWakeLock; + +#if CFG_SUPPORT_ROAMING_ENC + BOOLEAN fgIsRoamingEncEnabled; +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +#if (CFG_SUPPORT_TDLS == 1) + BOOLEAN fgTdlsIsSup; +#endif /* CFG_SUPPORT_TDLS */ + + UINT_8 ucScanTime; + +#if CFG_SUPPORT_DBG_POWERMODE + BOOLEAN fgEnDbgPowerMode; /* dbg privilege power mode, always keep in active */ +#endif + + UINT_32 u4AirDelayTotal; /* dbg privilege power mode, always keep in active */ + ULONG ulSuspendFlag; + struct GL_PER_MON_T rPerMonitor; +}; /* end of _ADAPTER_T */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define SUSPEND_FLAG_FOR_WAKEUP_REASON (0) +#define SUSPEND_FLAG_CLEAR_WHEN_RESUME (1) + +/*----------------------------------------------------------------------------*/ +/* Macros for BSS_INFO_T - Flag of Net Active */ +/*----------------------------------------------------------------------------*/ +#define IS_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive) +#define IS_BSS_ACTIVE(_prBssInfo) ((_prBssInfo)->fgIsNetActive) + +#define IS_AIS_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_AIS_INDEX) +#define IS_P2P_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_P2P_INDEX) +#define IS_BOW_ACTIVE(_prAdapter) IS_NET_ACTIVE(_prAdapter, NETWORK_TYPE_BOW_INDEX) + +#define SET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = TRUE; } + +#define UNSET_NET_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)].fgIsNetActive = FALSE; } + +#define BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; \ + _prBssInfo->fgIsNetActive = FALSE; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + COPY_MAC_ADDR(_prBssInfo->aucBSSID, _aucZeroMacAddr); \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = FALSE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } + +#if CFG_ENABLE_BT_OVER_WIFI +#define BOW_BSS_INFO_INIT(_prAdapter, _NetTypeIndex) \ + { \ + P_BSS_INFO_T _prBssInfo = &(_prAdapter->rWifiVar.arBssInfo[(_NetTypeIndex)]); \ + \ + _prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; \ + _prBssInfo->eCurrentOPMode = OP_MODE_BOW; \ + _prBssInfo->ucNetTypeIndex = (_NetTypeIndex); \ + _prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; \ + LINK_INITIALIZE(&_prBssInfo->rStaRecOfClientList); \ + _prBssInfo->fgIsBeaconActivated = TRUE; \ + _prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; \ + _prBssInfo->fgIsNetAbsent = FALSE; \ + } +#endif + +#define PERF_MON_DISABLE_BIT_OFF (0) +#define PERF_MON_STOP_BIT_OFF (1) +#define PERF_MON_RUNNING_BIT_OFF (2) + +#define THROUGHPUT_L1_THRESHOLD (20*1024*1024) +#define THROUGHPUT_L2_THRESHOLD (60*1024*1024) +#define THROUGHPUT_L3_THRESHOLD (135*1024*1024) + +/*----------------------------------------------------------------------------*/ +/* Macros for Power State */ +/*----------------------------------------------------------------------------*/ +#define SET_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_IDLE; } + +#define SET_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_ACTIVE; } + +#define SET_NET_PWR_STATE_PS(_prAdapter, _NetTypeIndex) \ + {_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] = PWR_STATE_PS; } + +#define IS_NET_PWR_STATE_ACTIVE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_ACTIVE) + +#define IS_NET_PWR_STATE_IDLE(_prAdapter, _NetTypeIndex) \ + (_prAdapter->rWifiVar.aePwrState[(_NetTypeIndex)] == PWR_STATE_IDLE) + +#define IS_SCN_PWR_STATE_ACTIVE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_ACTIVE) + +#define IS_SCN_PWR_STATE_IDLE(_prAdapter) \ + (_prAdapter->rWifiVar.rScanInfo.eScanPwrState == SCAN_PWR_STATE_IDLE) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _ADAPTER_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h new file mode 100644 index 0000000000000..6c4c1b76622b2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/bow.h @@ -0,0 +1,322 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/bow.h#1 +*/ + +/* +** Log: bow.h + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 22 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Submit missing BoW header files. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW structure. + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add Activity Report definition. + * + * 10 18 2010 chinghwa.yu + * [WCXRP00000110] [MT6620 Wi-Fi] [Driver] Fix BoW Connected event size + * Fix wrong BoW event size. + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * basic implementation for EVENT_BT_OVER_WIFI + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * sync. with design document for interface change. + * + * 04 02 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * Wi-Fi driver no longer needs to implement 802.11 PAL, thus replaced by wrapping command/event definitions + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * correct typo. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * update for all command/event needed to be supported by 802.11 PAL. + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * +*/ + +#ifndef _BOW_H_ +#define _BOW_H_ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define BOWDEVNAME "bow0" + +#define MAX_BOW_NUMBER_OF_CHANNEL_2G4 14 +#define MAX_BOW_NUMBER_OF_CHANNEL_5G 4 +/* (MAX_BOW_NUMBER_OF_CHANNEL_2G4 + MAX_BOW_NUMBER_OF_CHANNEL_5G) */ +#define MAX_BOW_NUMBER_OF_CHANNEL 18 + +#define MAX_ACTIVITY_REPORT 2 +#define MAX_ACTIVITY_REPROT_TIME 660 + +#define ACTIVITY_REPORT_STATUS_SUCCESS 0 +#define ACTIVITY_REPORT_STATUS_FAILURE 1 +#define ACTIVITY_REPORT_STATUS_TIME_INVALID 2 +#define ACTIVITY_REPORT_STATUS_OTHERS 3 + +#define ACTIVITY_REPORT_SCHEDULE_UNKNOWN 0 /* Does not know the schedule of the interference */ +#define ACTIVITY_REPORT_SCHEDULE_KNOWN 1 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _BT_OVER_WIFI_COMMAND_HEADER_T { + UINT_8 ucCommandId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_COMMAND_HEADER_T, *P_AMPC_COMMAND_HEADER_T; + +typedef struct _BT_OVER_WIFI_COMMAND { + AMPC_COMMAND_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_COMMAND, *P_AMPC_COMMAND; + +typedef struct _BT_OVER_WIFI_EVENT_HEADER_T { + UINT_8 ucEventId; + UINT_8 ucSeqNumber; + UINT_16 u2PayloadLength; +} AMPC_EVENT_HEADER_T, *P_AMPC_EVENT_HEADER_T; + +typedef struct _BT_OVER_WIFI_EVENT { + AMPC_EVENT_HEADER_T rHeader; + UINT_8 aucPayload[0]; +} AMPC_EVENT, *P_AMPC_EVENT; + +typedef struct _CHANNEL_DESC_T { + UINT_8 ucChannelBand; + UINT_8 ucChannelNum; +} CHANNEL_DESC, P_CHANNEL_DESC; + +/* Command Structures */ +typedef struct _BOW_SETUP_CONNECTION { +/* Fixed to 2.4G */ + UINT_8 ucChannelNum; + UINT_8 ucReserved1; + UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucReserved2; + +/* Pending, for future BOW 5G supporting. */ +/* UINT_8 aucPeerAddress[6]; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 ucPAL_Capabilities; + INT_8 cMaxTxPower; + UINT_8 ucChannelListNum; + CHANNEL_DESC arChannelList[1]; +*/ +} BOW_SETUP_CONNECTION, *P_BOW_SETUP_CONNECTION; + +typedef struct _BOW_DESTROY_CONNECTION { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_DESTROY_CONNECTION, *P_BOW_DESTROY_CONNECTION; + +typedef struct _BOW_SET_PTK { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; + UINT_8 aucTemporalKey[16]; +} BOW_SET_PTK, *P_BOW_SET_PTK; + +typedef struct _BOW_READ_RSSI { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_RSSI, *P_BOW_READ_RSSI; + +typedef struct _BOW_READ_LINK_QUALITY { + UINT_8 aucPeerAddress[6]; + UINT_8 aucReserved[2]; +} BOW_READ_LINK_QUALITY, *P_BOW_READ_LINK_QUALITY; + +typedef struct _BOW_SHORT_RANGE_MODE { + UINT_8 aucPeerAddress[6]; + INT_8 cTxPower; + UINT_8 ucReserved; +} BOW_SHORT_RANGE_MODE, *P_BOW_SHORT_RANGE_MODE; + +/* Event Structures */ +typedef struct _BOW_COMMAND_STATUS { + UINT_8 ucStatus; + UINT_8 ucReserved[3]; +} BOW_COMMAND_STATUS, *P_BOW_COMMAND_STATUS; + +typedef struct _BOW_MAC_STATUS { + UINT_8 aucMacAddr[6]; + UINT_8 ucAvailability; + UINT_8 ucNumOfChannel; + CHANNEL_DESC arChannelList[MAX_BOW_NUMBER_OF_CHANNEL]; +} BOW_MAC_STATUS, *P_BOW_MAC_STATUS; + +typedef struct _BOW_LINK_CONNECTED { + CHANNEL_DESC rChannel; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_CONNECTED, *P_BOW_LINK_CONNECTED; + +typedef struct _BOW_LINK_DISCONNECTED { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_LINK_DISCONNECTED, *P_BOW_LINK_DISCONNECTED; + +typedef struct _BOW_RSSI { + INT_8 cRssi; + UINT_8 aucReserved[3]; +} BOW_RSSI, *P_BOW_RSSI; + +typedef struct _BOW_LINK_QUALITY { + UINT_8 ucLinkQuality; + UINT_8 aucReserved[3]; +} BOW_LINK_QUALITY, *P_BOW_LINK_QUALITY; + +typedef enum _ENUM_BOW_CMD_ID_T { + BOW_CMD_ID_GET_MAC_STATUS = 1, + BOW_CMD_ID_SETUP_CONNECTION, + BOW_CMD_ID_DESTROY_CONNECTION, + BOW_CMD_ID_SET_PTK, + BOW_CMD_ID_READ_RSSI, + BOW_CMD_ID_READ_LINK_QUALITY, + BOW_CMD_ID_SHORT_RANGE_MODE, + BOW_CMD_ID_GET_CHANNEL_LIST, +} ENUM_BOW_CMD_ID_T, *P_ENUM_BOW_CMD_ID_T; + +typedef enum _ENUM_BOW_EVENT_ID_T { + BOW_EVENT_ID_COMMAND_STATUS = 1, + BOW_EVENT_ID_MAC_STATUS, + BOW_EVENT_ID_LINK_CONNECTED, + BOW_EVENT_ID_LINK_DISCONNECTED, + BOW_EVENT_ID_RSSI, + BOW_EVENT_ID_LINK_QUALITY, + BOW_EVENT_ID_CHANNEL_LIST, + BOW_EVENT_ID_CHANNEL_SELECTED, +} ENUM_BOW_EVENT_ID_T, *P_ENUM_BOW_EVENT_ID_T; + +typedef enum _ENUM_BOW_DEVICE_STATE { + BOW_DEVICE_STATE_DISCONNECTED = 0, + BOW_DEVICE_STATE_DISCONNECTING, + BOW_DEVICE_STATE_ACQUIRING_CHANNEL, + BOW_DEVICE_STATE_STARTING, + BOW_DEVICE_STATE_SCANNING, + BOW_DEVICE_STATE_CONNECTING, + BOW_DEVICE_STATE_CONNECTED, + BOW_DEVICE_STATE_NUM +} ENUM_BOW_DEVICE_STATE, *P_ENUM_BOW_DEVICE_STATE; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h new file mode 100644 index 0000000000000..c1ecb303b877f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/cmd_buf.h @@ -0,0 +1,150 @@ +/* +** Id: +*/ + +/*! \file "cmd_buf.h" + \brief In this file we define the structure for Command Packet. + + In this file we define the structure for Command Packet and the control unit + of MGMT Memory Pool. +*/ + +/* +** Log: cmd_buf.h + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by + * ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow + * under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Enable change log +*/ + +#ifndef _CMD_BUF_H +#define _CMD_BUF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _COMMAND_TYPE { + COMMAND_TYPE_GENERAL_IOCTL, + COMMAND_TYPE_NETWORK_IOCTL, + COMMAND_TYPE_SECURITY_FRAME, + COMMAND_TYPE_MANAGEMENT_FRAME, + COMMAND_TYPE_NUM +} COMMAND_TYPE, *P_COMMAND_TYPE; + +typedef VOID(*PFN_CMD_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +typedef VOID(*PFN_CMD_TIMEOUT_HANDLER) (IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +struct _CMD_INFO_T { + QUE_ENTRY_T rQueEntry; + + COMMAND_TYPE eCmdType; + + UINT_16 u2InfoBufLen; /* This is actual CMD buffer length */ + PUINT_8 pucInfoBuffer; /* May pointer to structure in prAdapter */ + P_NATIVE_PACKET prPacket; /* only valid when it's a security frame */ + + ENUM_NETWORK_TYPE_INDEX_T eNetworkType; + UINT_8 ucStaRecIndex; /* only valid when it's a security frame */ + + PFN_CMD_DONE_HANDLER pfCmdDoneHandler; + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler; + + BOOLEAN fgIsOid; /* Used to check if we need indicate */ + + UINT_8 ucCID; + BOOLEAN fgSetQuery; + BOOLEAN fgNeedResp; + BOOLEAN fgDriverDomainMCR; /* Access Driver Domain MCR, for CMD_ID_ACCESS_REG only */ + UINT_8 ucCmdSeqNum; + UINT_32 u4SetInfoLen; /* Indicate how many byte we read for Set OID */ + + /* information indicating by OID/ioctl */ + PVOID pvInformationBuffer; + UINT_32 u4InformationBufferLength; + + /* private data */ + UINT_32 u4PrivateData; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter); + +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length); + +VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* Routines for CMDs */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanSendSetQueryCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h new file mode 100644 index 0000000000000..0fdb9dcadeeff --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hal.h @@ -0,0 +1,618 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hal.h#1 +*/ + +/*! \file "hal.h" + \brief The declaration of hal functions + + N/A +*/ + +/* +** Log: hal.h + * + * 04 01 2011 tsaiyuan.hsu + * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues + * fix the klocwork issues, 57500, 57501, 57502 and 57503. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 09 01 2010 cp.wu + * NULL + * move HIF CR initialization from where after sdioSetupCardFeature() to wlanAdapterStart() + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change zero-padding for TX port access to HAL. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * 4. correct some HAL implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-16 18:02:26 GMT mtk02752 +** include precomp.h +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:16 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 13:54:15 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-11 10:36:01 GMT mtk01084 +** modify HAL functions +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-09 22:56:28 GMT mtk01084 +** modify HW access routines +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-10-29 19:50:09 GMT mtk01084 +** add new macro HAL_TX_PORT_WR +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-23 16:08:10 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-13 21:58:50 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-05-18 14:28:10 GMT mtk01084 +** fix issue in HAL_DRIVER_OWN_BY_SDIO_CMD52() +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-11 17:26:33 GMT mtk01084 +** modify the bit definition to check driver own status +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:30:22 GMT mtk01461 +** Fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:50:34 GMT mtk01461 +** Redefine HAL_PORT_RD/WR macro for SW pre test +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-24 09:46:49 GMT mtk01084 +** fix LINT error +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 16:53:38 GMT mtk01084 +** add HAL_DRIVER_OWN_BY_SDIO_CMD52() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-18 20:53:13 GMT mtk01426 +** Fixed lint warn +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:20 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _HAL_H +#define _HAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* Macros for flag operations for the Adapter structure */ +#define HAL_SET_FLAG(_M, _F) ((_M)->u4HwFlags |= (_F)) +#define HAL_CLEAR_FLAG(_M, _F) ((_M)->u4HwFlags &= ~(_F)) +#define HAL_TEST_FLAG(_M, _F) ((_M)->u4HwFlags & (_F)) +#define HAL_TEST_FLAGS(_M, _F) (((_M)->u4HwFlags & (_F)) == (_F)) + +#if defined(_HIF_SDIO) +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + /* DBGLOG(HAL, ERROR, ("HAL_MCR_RD access fail! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)*_pu4Value)); */ \ + } \ + } else { \ + /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_RD access! 0x%x\n", (UINT32)_u4Offset)); */ \ + } \ +} while (0) + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +do { \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + /* DBGLOG(HAL, ERROR, ("HAL_MCR_WR access fail! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ + } \ + } else { \ + /* DBGLOG(HAL, WARN, ("ignore HAL_MCR_WR access! 0x%x: 0x%x\n", */ \ + /* (UINT32)_u4Offset, (UINT32)_u4Value)); */ \ + } \ +} while (0) + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_RD access fail! 0x%x\n", _u4Port); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_RD access! 0x%x\n", _u4Port); \ + } \ +} + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + /*fgResult = FALSE; */\ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_PORT_WR access fail! 0x%x\n", _u4Port); \ + } \ + else { \ + /*fgResult = TRUE;*/ } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_PORT_WR access! 0x%x\n", _u4Port); \ + } \ +} + +#if 0 /* only for SDIO */ +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf) == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "HAL_BYTE_WR access fail! 0x%x\n", _u4Port); \ + } \ + else { \ + /* Todo:: Nothing*/ \ + } \ + } \ + else { \ + DBGLOG(HAL, WARN, "ignore HAL_BYTE_WR access! 0x%x\n", _u4Port); \ + } \ +} +#endif + +#define HAL_DRIVER_OWN_BY_SDIO_CMD52(_prAdapter, _pfgDriverIsOwnReady) \ +{ \ + UINT_8 ucBuf = BIT(1); \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (HAL_TEST_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR) == FALSE) { \ + if (kalDevReadAfterWriteWithSdioCmd52(_prAdapter->prGlueInfo, MCR_WHLPCR_BYTE1, &ucBuf, 1) \ + == FALSE) {\ + HAL_SET_FLAG(_prAdapter, ADAPTER_FLAG_HW_ERR); \ + fgIsBusAccessFailed = TRUE; \ + DBGLOG(HAL, ERROR, "kalDevReadAfterWriteWithSdioCmd52 access fail!\n"); \ + } \ + else { \ + *_pfgDriverIsOwnReady = (ucBuf & BIT(0)) ? TRUE : FALSE; \ + } \ + } else { \ + DBGLOG(HAL, WARN, "ignore HAL_DRIVER_OWN_BY_SDIO_CMD52 access!\n"); \ + } \ +} + +#else /* #if defined(_HIF_SDIO) */ +#define HAL_MCR_RD(_prAdapter, _u4Offset, _pu4Value) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegRead(_prAdapter->prGlueInfo, _u4Offset, _pu4Value) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_MCR_WR(_prAdapter, _u4Offset, _u4Value) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevRegWrite(_prAdapter->prGlueInfo, _u4Offset, _u4Value) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_PORT_RD(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevPortRead(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#define HAL_PORT_WR(_prAdapter, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ + if (kalDevPortWrite(_prAdapter->prGlueInfo, _u4Port, _u4Len, _pucBuf, _u4ValidBufSize) \ + == FALSE) \ + fgIsBusAccessFailed = TRUE; \ +} + +#if 0 /* only for SDIO */ +#define HAL_BYTE_WR(_prAdapter, _u4Port, _ucBuf) \ +{ \ + if (_prAdapter->rAcpiState == ACPI_STATE_D3) { \ + ASSERT(0); \ + } \ +kalDevWriteWithSdioCmd52(_prAdapter->prGlueInfo, _u4Port, _ucBuf); \ +} +#endif + +#endif /* #if defined(_HIF_SDIO) */ + +#define HAL_READ_RX_PORT(prAdapter, u4PortId, u4Len, pvBuf, _u4ValidBufSize) \ +{ \ + ASSERT(u4PortId < 2); \ + HAL_PORT_RD(prAdapter, \ + ((u4PortId == 0) ? MCR_WRDR0 : MCR_WRDR1), \ + u4Len, \ + pvBuf, \ + _u4ValidBufSize/*temp!!*//*4Kbyte*/); \ +} + +#define HAL_WRITE_TX_PORT(_prAdapter, _ucTxPortIdx, _u4Len, _pucBuf, _u4ValidBufSize) \ +{ \ + ASSERT(_ucTxPortIdx < 2); \ + if ((_u4ValidBufSize - _u4Len) >= sizeof(UINT_32)) { \ + /* fill with single dword of zero as TX-aggregation termination */ \ + *(PUINT_32) (&((_pucBuf)[ALIGN_4(_u4Len)])) = 0; \ + } \ + HAL_PORT_WR(_prAdapter, \ + (_ucTxPortIdx == 0) ? MCR_WTDR0 : MCR_WTDR1, \ + _u4Len, \ + _pucBuf, \ + _u4ValidBufSize/*temp!!*//*4KByte*/); \ +} + +/* The macro to read the given MCR several times to check if the wait + condition come true. */ +#define HAL_MCR_RD_AND_WAIT(_pAdapter, _offset, _pReadValue, _waitCondition, _waitDelay, _waitCount, _status) \ +{ \ + UINT_32 count; \ + (_status) = FALSE; \ + for (count = 0; count < (_waitCount); count++) { \ + HAL_MCR_RD((_pAdapter), (_offset), (_pReadValue)); \ + if ((_waitCondition)) { \ + (_status) = TRUE; \ + break; \ + } \ + kalUdelay((_waitDelay)); \ + } \ +} + +/* The macro to write 1 to a R/S bit and read it several times to check if the + command is done */ +#define HAL_MCR_WR_AND_WAIT(_pAdapter, _offset, _writeValue, _busyMask, _waitDelay, _waitCount, _status) \ +{ \ + UINT_32 u4Temp; \ + UINT_32 u4Count = _waitCount; \ + (_status) = FALSE; \ + HAL_MCR_WR((_pAdapter), (_offset), (_writeValue)); \ + do { \ + kalUdelay((_waitDelay)); \ + HAL_MCR_RD((_pAdapter), (_offset), &u4Temp); \ + if (!(u4Temp & (_busyMask))) { \ + (_status) = TRUE; \ + break; \ + } \ + u4Count--; \ + } while (u4Count); \ +} + +#define HAL_GET_CHIP_ID_VER(_prAdapter, pu2ChipId, pu2Version) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + *pu2ChipId = (UINT_16)(u4Value & WCIR_CHIP_ID); \ + *pu2Version = (UINT_16)(u4Value & WCIR_REVISION_ID) >> 16; \ +} + +#define HAL_WAIT_WIFI_FUNC_READY(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + UINT_32 i; \ + for (i = 0; i < 100; i++) { \ + HAL_MCR_RD(_prAdapter, \ + MCR_WCIR, \ + &u4Value); \ + if (u4Value & WCIR_WLAN_READY) { \ + break; \ + } \ + NdisMSleep(10); \ + } \ +} + +#define HAL_INTR_DISABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_CLR) + +#define HAL_INTR_ENABLE(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_INT_EN_SET) + +#define HAL_INTR_ENABLE_AND_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + (WHLPCR_INT_EN_SET | WHLPCR_FW_OWN_REQ_SET)) + +#define HAL_LP_OWN_SET(_prAdapter) \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_SET) + +#define HAL_LP_OWN_CLR_OK(_prAdapter, _pfgResult) \ +{ \ + UINT_32 i; \ + UINT_32 u4RegValue; \ + UINT_32 u4LoopCnt = 2048 / 8; \ + *_pfgResult = TRUE; \ + /* Software get LP ownership */ \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHLPCR, \ + WHLPCR_FW_OWN_REQ_CLR) \ + for (i = 0; i < u4LoopCnt; i++) { \ + HAL_MCR_RD(_prAdapter, MCR_WHLPCR, &u4RegValue); \ + if (u4RegValue & WHLPCR_IS_DRIVER_OWN) { \ + break; \ + } \ + else { \ + kalUdelay(8); \ + } \ + } \ + if (i == u4LoopCnt) { \ + *_pfgResult = FALSE; \ + /*ERRORLOG(("LP cannot be own back (%ld)", u4LoopCnt));*/ \ + /* check the time of LP instructions need to perform from Sleep to On */ \ + /*ASSERT(0); */ \ + } \ +} + +#define HAL_GET_ABNORMAL_INTERRUPT_REASON_CODE(_prAdapter, pu4AbnormalReason) \ +{ \ + HAL_MCR_RD(_prAdapter, \ + MCR_WASR, \ + pu4AbnormalReason); \ +} + +#define HAL_DISABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_RX_ENHANCE_MODE_EN); \ +} + +#define HAL_ENABLE_RX_ENHANCE_MODE(_prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_RX_ENHANCE_MODE_EN); \ +} + +#define HAL_CFG_MAX_HIF_RX_LEN_NUM(_prAdapter, _ucNumOfRxLen) \ +{ \ + UINT_32 u4Value, ucNum; \ + ucNum = ((_ucNumOfRxLen >= 16) ? 0 : _ucNumOfRxLen); \ + u4Value = 0; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + u4Value &= ~WHCR_MAX_HIF_RX_LEN_NUM; \ + u4Value |= ((((UINT_32)ucNum) << 4) & WHCR_MAX_HIF_RX_LEN_NUM); \ + HAL_MCR_WR(_prAdapter, \ + MCR_WHCR, \ + u4Value); \ +} + +#define HAL_SET_INTR_STATUS_READ_CLEAR(prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value & ~WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = TRUE;\ +} + +#define HAL_SET_INTR_STATUS_WRITE_1_CLEAR(prAdapter) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, \ + MCR_WHCR, \ + &u4Value); \ + HAL_MCR_WR(prAdapter, \ + MCR_WHCR, \ + u4Value | WHCR_W_INT_CLR_CTRL); \ + prAdapter->prGlueInfo->rHifInfo.fgIntReadClear = FALSE;\ +} + +/* Note: enhance mode structure may also carried inside the buffer, + if the length of the buffer is long enough */ +#define HAL_READ_INTR_STATUS(prAdapter, length, pvBuf) \ + HAL_PORT_RD(prAdapter, \ + MCR_WHISR, \ + length, \ + pvBuf, \ + length) + +#define HAL_READ_TX_RELEASED_COUNT(_prAdapter, aucTxReleaseCount) \ +{ \ + PUINT_32 pu4Value = (PUINT_32)aucTxReleaseCount; \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR0, \ + &pu4Value[0]); \ + HAL_MCR_RD(_prAdapter, \ + MCR_WTSR1, \ + &pu4Value[1]); \ +} + +#define HAL_READ_RX_LENGTH(prAdapter, pu2Rx0Len, pu2Rx1Len) \ +{ \ + UINT_32 u4Value; \ + u4Value = 0; \ + HAL_MCR_RD(prAdapter, \ + MCR_WRPLR, \ + &u4Value); \ + *pu2Rx0Len = (UINT_16)u4Value; \ + *pu2Rx1Len = (UINT_16)(u4Value >> 16); \ +} + +#define HAL_GET_INTR_STATUS_FROM_ENHANCE_MODE_STRUCT(pvBuf, u2Len, pu4Status) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvBuf; \ + *pu4Status = pu4Buf[0]; \ +} + +#define HAL_GET_TX_STATUS_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4BufOut, u4LenBufOut) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT(u4LenBufOut >= 8); \ + pu4BufOut[0] = pu4Buf[1]; \ + pu4BufOut[1] = pu4Buf[2]; \ +} + +#define HAL_GET_RX_LENGTH_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu2Rx0Num, au2Rx0Len, pu2Rx1Num, au2Rx1Len) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + ASSERT((sizeof(au2Rx0Len) / sizeof(UINT_16)) >= 16); \ + ASSERT((sizeof(au2Rx1Len) / sizeof(UINT_16)) >= 16); \ + *pu2Rx0Num = (UINT_16)pu4Buf[3]; \ + *pu2Rx1Num = (UINT_16)(pu4Buf[3] >> 16); \ + kalMemCopy(au2Rx0Len, &pu4Buf[4], 8); \ + kalMemCopy(au2Rx1Len, &pu4Buf[12], 8); \ +} + +#define HAL_GET_MAILBOX_FROM_ENHANCE_MODE_STRUCT(pvInBuf, pu4Mailbox0, pu4Mailbox1) \ +{ \ + PUINT_32 pu4Buf = (PUINT_32)pvInBuf; \ + *pu4Mailbox0 = (UINT_16)pu4Buf[21]; \ + *pu4Mailbox1 = (UINT_16)pu4Buf[22]; \ +} + +#define HAL_IS_TX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_TX_DONE_INT) ? TRUE : FALSE) + +#define HAL_IS_RX_DONE_INTR(u4IntrStatus) \ + ((u4IntrStatus & (WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT)) ? TRUE : FALSE) + +#define HAL_IS_ABNORMAL_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_ABNORMAL_INT) ? TRUE : FALSE) + +#define HAL_IS_FW_OWNBACK_INTR(u4IntrStatus) \ + ((u4IntrStatus & WHISR_FW_OWN_BACK_INT) ? TRUE : FALSE) + +#define HAL_PUT_MAILBOX(prAdapter, u4MboxId, u4Data) \ +{ \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_WR(prAdapter, \ + ((u4MboxId == 0) ? MCR_H2DSM0R : MCR_H2DSM1R), \ + u4Data); \ +} + +#define HAL_GET_MAILBOX(prAdapter, u4MboxId, pu4Data) \ +{ \ + ASSERT(u4MboxId < 2); \ + HAL_MCR_RD(prAdapter, \ + ((u4MboxId == 0) ? MCR_D2HRM0R : MCR_D2HRM1R), \ + pu4Data); \ +} + +#define HAL_SET_MAILBOX_READ_CLEAR(prAdapter, fgEnableReadClear) \ +{ \ + UINT_32 u4Value; \ + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value);\ + HAL_MCR_WR(prAdapter, MCR_WHCR, \ + (fgEnableReadClear) ? \ + (u4Value | WHCR_W_MAILBOX_RD_CLR_EN) : \ + (u4Value & ~WHCR_W_MAILBOX_RD_CLR_EN)); \ + prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear = fgEnableReadClear;\ +} + +#define HAL_GET_MAILBOX_READ_CLEAR(prAdapter) (prAdapter->prGlueInfo->rHifInfo.fgMbxReadClear) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _HAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h new file mode 100644 index 0000000000000..b9aa154b097ef --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_rx.h @@ -0,0 +1,220 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_rx.h#1 +*/ + +/*! \file "hif_rx.h" + \brief Provide HIF RX Header Information between F/W and Driver + + N/A +*/ + +/* +** Log: hif_rx.h + * + * 09 01 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * follow-ups for HIF_RX_HEADER_T update: + * 1) add TCL + * 2) add RCPI + * 3) add ChannelNumber + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:44:00 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-09 13:59:20 GMT MTK02468 +** Added HIF_RX_HDR parsing macros +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 19:54:54 GMT mtk02752 +** adopt HIF_RX_HEADER_T in new data path +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-29 19:51:19 GMT mtk01084 +** modify FW/ driver interface +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:33:58 GMT mtk01461 +** Add define of HW_APPENED_LEN +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:51:02 GMT mtk01461 +** Rename ENUM_HIF_RX_PKT_TYPE_T +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 12:05:03 GMT mtk01426 +** Remove __KAL_ATTRIB_PACKED__ and add hifDataTypeCheck() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:18:52 GMT mtk01426 +** Add comment to HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:23 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _HIF_RX_H +#define _HIF_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/*! HIF_RX_HEADER_T */ +/* DW 0, Byte 1 */ +#define HIF_RX_HDR_PACKET_TYPE_MASK BITS(0, 1) +#define HIF_RX_HDR_SEC_MODE_MASK BITS(2, 5) +#define HIF_RX_HDR_SEC_MODE_OFFSET 2 + +/* DW 1, Byte 0 */ +#define HIF_RX_HDR_HEADER_LEN BITS(2, 7) +#define HIF_RX_HDR_HEADER_LEN_OFFSET 2 +#define HIF_RX_HDR_HEADER_OFFSET_MASK BITS(0, 1) + +/* DW 1, Byte 1 */ +#define HIF_RX_HDR_80211_HEADER_FORMAT BIT(0) +#define HIF_RX_HDR_DO_REORDER BIT(1) +#define HIF_RX_HDR_PAL BIT(2) +#define HIF_RX_HDR_TCL BIT(3) +#define HIF_RX_HDR_NETWORK_IDX_MASK BITS(4, 7) +#define HIF_RX_HDR_NETWORK_IDX_OFFSET 4 + +/* DW 1, Byte 2, 3 */ +#define HIF_RX_HDR_SEQ_NO_MASK BITS(0, 11) +#define HIF_RX_HDR_TID_MASK BITS(12, 14) +#define HIF_RX_HDR_TID_OFFSET 12 +#define HIF_RX_HDR_BAR_FRAME BIT(15) + +#define HIF_RX_HDR_FLAG_AMP_WDS BIT(0) +#define HIF_RX_HDR_FLAG_802_11_FORMAT BIT(1) +#define HIF_RX_HDR_FLAG_BAR_FRAME BIT(2) +#define HIF_RX_HDR_FLAG_DO_REORDERING BIT(3) +#define HIF_RX_HDR_FLAG_CTRL_WARPPER_FRAME BIT(4) + +#define HIF_RX_HW_APPENDED_LEN 4 + +/* For DW 2, Byte 3 - ucHwChannelNum */ +#define HW_CHNL_NUM_MAX_2G4 14 +#define HW_CHNL_NUM_MAX_4G_5G (255 - HW_CHNL_NUM_MAX_2G4) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef struct _HIF_RX_HEADER_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucHerderLenOffset; + UINT_8 uc80211_Reorder_PAL_TCL; + UINT_16 u2SeqNoTid; + UINT_8 ucStaRecIdx; + UINT_8 ucRcpi; + UINT_8 ucHwChannelNum; + UINT_8 ucReserved; +} HIF_RX_HEADER_T, *P_HIF_RX_HEADER_T; + +typedef enum _ENUM_HIF_RX_PKT_TYPE_T { + HIF_RX_PKT_TYPE_DATA = 0, + HIF_RX_PKT_TYPE_EVENT, + HIF_RX_PKT_TYPE_TX_LOOPBACK, + HIF_RX_PKT_TYPE_MANAGEMENT, + HIF_RX_PKT_TYPE_NUM +} ENUM_HIF_RX_PKT_TYPE_T, *P_ENUM_HIF_RX_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define HIF_RX_HDR_SIZE sizeof(HIF_RX_HEADER_T) + +#define HIF_RX_HDR_GET_80211_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_80211_HEADER_FORMAT) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_REORDER_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_DO_REORDER) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_PAL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_PAL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_TCL_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_TCL) ? TRUE : FALSE)) +#define HIF_RX_HDR_GET_NETWORK_IDX(_prHifRxHdr) \ + ((((_prHifRxHdr)->uc80211_Reorder_PAL_TCL) & HIF_RX_HDR_NETWORK_IDX_MASK)\ + >> HIF_RX_HDR_NETWORK_IDX_OFFSET) + +#define HIF_RX_HDR_GET_SEC_MODE(_prHifRxHdr) \ + ((((_prHifRxHdr)->u2PacketType) & HIF_RX_HDR_SEC_MODE_MASK) >> HIF_RX_HDR_SEC_MODE_OFFSET) + +#define HIF_RX_HDR_GET_TID(_prHifRxHdr) \ + ((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_TID_MASK)\ + >> HIF_RX_HDR_TID_OFFSET) +#define HIF_RX_HDR_GET_SN(_prHifRxHdr) \ + (((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_SEQ_NO_MASK) +#define HIF_RX_HDR_GET_BAR_FLAG(_prHifRxHdr) \ + (((((_prHifRxHdr)->u2SeqNoTid) & HIF_RX_HDR_BAR_FRAME) ? TRUE : FALSE)) + +#define HIF_RX_HDR_GET_CHNL_NUM(_prHifRxHdr) \ + ((((_prHifRxHdr)->ucHwChannelNum) > HW_CHNL_NUM_MAX_4G_5G) ? \ + (((_prHifRxHdr)->ucHwChannelNum) - HW_CHNL_NUM_MAX_4G_5G) : \ + ((_prHifRxHdr)->ucHwChannelNum)) + +/* To do: support more bands other than 2.4G and 5G */ +#define HIF_RX_HDR_GET_RF_BAND(_prHifRxHdr) \ + ((((_prHifRxHdr)->ucHwChannelNum) <= HW_CHNL_NUM_MAX_2G4) ? \ + BAND_2G4 : BAND_5G) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static inline VOID hifDataTypeCheck(VOID); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + * We'll need this for porting driver to different RTOS. + */ +static inline VOID hifDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_RX_HEADER_T) == 12); + +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h new file mode 100644 index 0000000000000..17252f2c7760c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/hif_tx.h @@ -0,0 +1,214 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/hif_tx.h#1 +*/ + +/* +** Log: hif_tx.h + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill extra information for revised HIF_TX_HEADER. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate + * 2) add packet type for indicating management frames + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * 2. follow MSDN defined behavior when associates to another AP + * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 01 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-10 16:43:40 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-24 19:55:11 GMT mtk02752 +** adopt HIF_TX_HEADER_T in new data path +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-23 17:54:13 GMT mtk02752 +** CMD_HDR_SIZE = (sizeof(WIFI_CMD_T)) to follow up CM's CMD/EVENT documentation +** +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-17 22:41:10 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-17 17:34:07 GMT mtk02752 +** remove HIF_TX_BUFF_COUNT_TC0 (move to nic_tx.h) +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-17 12:14:12 GMT mtk02752 +** add initial value for HIF_TX_BUFF_COUNT_TC5 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-13 13:54:18 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-04 14:11:14 GMT mtk01084 +** modify SW TX data format +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-29 19:51:53 GMT mtk01084 +** modify FW/ driver interface +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-20 12:22:46 GMT mtk01461 +** Add SeqNum field to CMD Header +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:40:52 GMT mtk01461 +** Update the Log Sign +*/ + +#ifndef _HIF_TX_H +#define _HIF_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Maximum buffer size for individual HIF TCQ Buffer */ +#define HIF_TX_BUFF_MAX_SIZE 1552 /* Reserved field was not included */ + +/* Maximum buffer count for individual HIF TCQ */ +#define HIF_TX_BUFF_COUNT_TC0 3 +#define HIF_TX_BUFF_COUNT_TC1 3 +#define HIF_TX_BUFF_COUNT_TC2 3 +#define HIF_TX_BUFF_COUNT_TC3 3 +#define HIF_TX_BUFF_COUNT_TC4 2 + +#define TX_HDR_SIZE sizeof(HIF_TX_HEADER_T) + +#define CMD_HDR_SIZE sizeof(WIFI_CMD_T) + +#define CMD_PKT_SIZE_FOR_IMAGE 2048 /* !< 2048 Bytes CMD payload buffer */ + +/*! NIC_HIF_TX_HEADER_T */ +/* DW 0, Byte 0,1 */ +#define HIF_TX_HDR_TX_BYTE_COUNT_MASK BITS(0, 11) +#define HIF_TX_HDR_USER_PRIORITY_OFFSET 12 + +/* DW 0, Byte 2 */ +#define HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK BITS(0, 7) + +/* DW 0, Byte 3 */ +#define HIF_TX_HDR_IP_CSUM BIT(0) +#define HIF_TX_HDR_TCP_CSUM BIT(1) +#define HIF_TX_HDR_RESOURCE_MASK BITS(2, 5) +#define HIF_TX_HDR_RESOURCE_OFFSET 2 +#define HIF_TX_HDR_PACKET_TYPE_MASK BITS(6, 7) +#define HIF_TX_HDR_PACKET_TYPE_OFFSET 6 + +/* DW 1, Byte 0 */ +#define HIF_TX_HDR_WLAN_HEADER_LEN_MASK BITS(0, 5) + +/* DW 1, Byte 1 */ +#define HIF_TX_HDR_FORMAT_ID_MASK BITS(0, 2) +#define HIF_TX_HDR_NETWORK_TYPE_MASK BITS(4, 5) +#define HIF_TX_HDR_NETWORK_TYPE_OFFSET 4 +#define HIF_TX_HDR_FLAG_1X_FRAME_MASK BIT(6) +#define HIF_TX_HDR_FLAG_1X_FRAME_OFFSET 6 +#define HIF_TX_HDR_FLAG_802_11_FORMAT_MASK BIT(7) +#define HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET 7 + +/* DW2, Byte 3 */ +#define HIF_TX_HDR_PS_FORWARDING_TYPE_MASK BITS(0, 1) +#define HIF_TX_HDR_PS_SESSION_ID_MASK BITS(2, 4) +#define HIF_TX_HDR_PS_SESSION_ID_OFFSET 2 +#define HIF_TX_HDR_BURST_END_MASK BIT(5) +#define HIF_TX_HDR_BURST_END_OFFSET 5 + +/* DW3, Byte 1 */ +#define HIF_TX_HDR_NEED_ACK BIT(0) +#define HIF_TX_HDR_BIP BIT(1) +#define HIF_TX_HDR_BASIC_RATE BIT(2) +#define HIF_TX_HDR_NEED_TX_DONE_STATUS BIT(3) +#define HIF_TX_HDR_RTS BIT(4) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _HIF_HW_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + UINT_8 aucBuffer[0]; +} HIF_HW_TX_HEADER_T, *P_HIF_HW_TX_HEADER_T; + +typedef struct _HIF_TX_HEADER_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucWlanHeaderLength; + UINT_8 ucPktFormtId_Flags; + UINT_16 u2LLH; /* for BOW */ + UINT_16 u2SeqNo; /* for BOW */ + UINT_8 ucStaRecIdx; + UINT_8 ucForwardingType_SessionID_Reserved; + UINT_8 ucPacketSeqNo; + UINT_8 ucAck_BIP_BasicRate; + UINT_8 aucReserved[2]; +} HIF_TX_HEADER_T, *P_HIF_TX_HEADER_T; + +typedef enum _ENUM_HIF_TX_PKT_TYPE_T { + HIF_TX_PKT_TYPE_DATA = 0, + HIF_TX_PKT_TYPE_CMD, + HIF_TX_PKT_TYPE_HIF_LOOPBACK, + HIF_TX_PKT_TYPE_MANAGEMENT, + HIF_TX_PKT_TYPE_NUM +} ENUM_HIF_TX_PKT_TYPE_T, *P_ENUM_HIF_TX_PKT_TYPE_T; + +typedef enum _ENUM_HIF_OOB_CTRL_PKT_TYPE_T { + HIF_OOB_CTRL_PKT_TYPE_LOOPBACK = 1, + HIF_OOB_CTRL_PKT_TYP_NUM +} ENUM_HIF_OOB_CTRL_PKT_TYPE_T, *P_ENUM_HIF_OOB_CTRL_PKT_TYPE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define TFCB_FRAME_PAD_TO_DW(u2Length) ALIGN_4(u2Length) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* Kevin: we don't have to call following function to inspect the data structure. + * It will check automatically while at compile time. + */ +static inline VOID hif_txDataTypeCheck(VOID); + +static inline VOID hif_txDataTypeCheck(VOID) +{ + DATA_STRUCT_INSPECTING_ASSERT(sizeof(HIF_TX_HEADER_T) == 16); + +} + +#endif /*_HIF_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h new file mode 100644 index 0000000000000..ff38d30c3cf2f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mac.h @@ -0,0 +1,2323 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/mac.h#1 +*/ + +/*! \file "mac.h" + \brief Brief description. + + Detail description. +*/ + +/* +** Log: mac.h + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h + * and let the sw structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 05 06 2011 wh.su + * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send + * the wrong beacon make driver got incorrect support rate set + * Add the length check before access the ie length filed. + * + * 05 06 2011 wh.su + * [WCXRP00000699] [MT6620 Wi-Fi][Driver] Add the ie pointer check for avoid TP-LINK AP send + * the wrong beacon make driver got incorrect support rate set + * adding the length check before processing next ie.. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discover ability support. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Some action frame define is not belong to P2P. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Add some service discovery MAC define, phase I. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 13 2010 cp.wu + * [WCXRP00000256] [MT6620 Wi-Fi][Driver] Eliminate potential issues which is identified by Klockwork + * suppress warning reported by Klockwork. + * + * 11 01 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * revert to previous revision. (this file is not necessary to be changed) + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 02 2010 yuche.tsai + * NULL + * 1. Add P2P MAC define. + * 2. Add scan device found event + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add WFA specific OUI. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P IE ID & Vendor OUI TYPE for P2P. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge MAC.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added OFFSET_BAR_SSC_SN +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:00:24 GMT MTK02468 +** Added offsets and masks for the BA Parameter Set filed +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:26 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _MAC_H +#define _MAC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* 3 --------------- Constants for Ethernet/802.11 MAC --------------- */ +/* MAC Address */ +#define MAC_ADDR_LEN 6 + +#define MAC_ADDR_LOCAL_ADMIN BIT(1) + +#define ETH_P_IPV4 0x0800 +#define ETH_P_IPX 0x8137 /* Novell IPX */ +#define ETH_P_AARP 0x80F3 /* AppleTalk Address Resolution Protocol (AARP) */ +#define ETH_P_IPV6 0x86DD + +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 + +#define IP_PROTOCOL_TCP 6 +#define IP_PROTOCOL_UDP 17 + +#define IPV4_HDR_IP_IDENTIFICATION_OFFSET 4 +#define IPV4_HDR_IP_PROTOCOL_OFFSET 9 +#define IPV4_HDR_IP_CSUM_OFFSET 10 +#define IPV4_HDR_IP_SRC_ADDR_OFFSET 12 +#define IPV4_HDR_IP_DST_ADDR_OFFSET 16 + +#define IPV6_HDR_IP_PROTOCOL_OFFSET 6 +#define IPV6_HDR_IP_SRC_ADDR_OFFSET 8 +#define IPV6_HDR_IP_DST_ADDR_OFFSET 24 +#define IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET 32 +#define IPV6_HDR_IP_DST_ADDR_MAC_LOW_OFFSET 37 +#define IPV6_PROTOCOL_ICMPV6 0x3A +#define IPV6_ADDR_LEN 16 +#define IPV6_HDR_LEN 40 + +#define ARP_OPERATION_OFFSET 6 +#define ARP_SNEDER_MAC_OFFSET 8 +#define ARP_SENDER_IP_OFFSET 14 +#define ARP_TARGET_MAC_OFFSET 18 +#define ARP_TARGET_IP_OFFSET 24 +#define ARP_OPERATION_REQUEST 0x0001 +#define ARP_OPERATION_RESPONSE 0x0002 + +#define ICMPV6_TYPE_OFFSET 0 +#define ICMPV6_FLAG_OFFSET 4 +#define ICMPV6_TARGET_ADDR_OFFSET 8 +#define ICMPV6_TARGET_LL_ADDR_TYPE_OFFSET 24 +#define ICMPV6_TARGET_LL_ADDR_LEN_OFFSET 25 +#define ICMPV6_TARGET_LL_ADDR_TA_OFFSET 26 + +#define ICMPV6_FLAG_ROUTER_BIT BIT(7) +#define ICMPV6_FLAG_SOLICITED_BIT BIT(6) +#define ICMPV6_FLAG_OVERWRITE_BIT BIT(5) +#define ICMPV6_TYPE_NEIGHBOR_SOLICITATION 0x87 +#define ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT 0x88 + +#define TCP_HDR_TCP_CSUM_OFFSET 16 +#define UDP_HDR_UDP_CSUM_OFFSET 6 + +#define LLC_LEN 8 /* LLC(3) + SNAP(3) + EtherType(2) */ + +#define NULL_MAC_ADDR {0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#define BC_MAC_ADDR {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} + +/* Ethernet Frame Field Size, in byte */ +#define ETHER_HEADER_LEN 14 +#define ETHER_TYPE_LEN 2 +#define ETHER_MIN_PKT_SZ 60 +#define ETHER_MAX_PKT_SZ 1514 + +/* IEEE 802.11 WLAN Frame Field Size, in byte */ +#define WLAN_MAC_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_HEADER_A4_LEN 30 /* Address 4 included */ +#define WLAN_MAC_HEADER_QOS_LEN 26 /* QoS Control included */ +#define WLAN_MAC_HEADER_QOS_HTC_LEN 30 /* QoS Control and HTC included */ +#define WLAN_MAC_HEADER_A4_QOS_LEN 32 /* Address 4 and QoS Control included */ +#define WLAN_MAC_HEADER_A4_QOS_HTC_LEN 36 /* Address 4, QoS Control and HTC included */ +#define WLAN_MAC_MGMT_HEADER_LEN 24 /* Address 4 excluded */ +#define WLAN_MAC_MGMT_HEADER_HTC_LEN 28 /* HTC included */ + +#define QOS_CTRL_LEN 2 +#define HT_CTRL_LEN 4 + +#define WLAN_MAC_CTS_ACK_LEN (WLAN_MAC_CTS_ACK_FRAME_HEADER_LEN + FCS_LEN) + +/* 6.2.1.1.2 Semantics of the service primitive */ +#define MSDU_MAX_LENGTH 2304 + +/* 7.1.3.3.3 Broadcast BSSID */ +#define BC_BSSID BC_MAC_ADDR + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.3.1.6 Listen Interval field */ +#define DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD 2 /* In unit of AP's DTIM interval, */ +#define DEFAULT_LISTEN_INTERVAL 10 + +/* 7.3.2.1 Broadcast(Wildcard) SSID */ +#define BC_SSID "" +#define BC_SSID_LEN 0 + +/* 7.3.2.2 Data Rate Value */ +#define RATE_1M 2 /* 1M in unit of 500kb/s */ +#define RATE_2M 4 /* 2M */ +#define RATE_5_5M 11 /* 5.5M */ +#define RATE_11M 22 /* 11M */ +#define RATE_22M 44 /* 22M */ +#define RATE_33M 66 /* 33M */ +#define RATE_6M 12 /* 6M */ +#define RATE_9M 18 /* 9M */ +#define RATE_12M 24 /* 12M */ +#define RATE_18M 36 /* 18M */ +#define RATE_24M 48 /* 24M */ +#define RATE_36M 72 /* 36M */ +#define RATE_48M 96 /* 48M */ +#define RATE_54M 108 /* 54M */ +/* 7.3.2.14 BSS membership selector */ +#define RATE_HT_PHY 127 /* BSS Selector - Clause 20. HT PHY */ +#define RATE_MASK BITS(0, 6) /* mask bits for the rate */ +#define RATE_BASIC_BIT BIT(7) /* mask bit for the rate belonging to the BSSBasicRateSet */ + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 9.2.10 DIFS */ +#define DIFS 2 /* 2 x aSlotTime */ + +/* 11.3 STA Authentication and Association */ +#define STA_STATE_1 0 /* Accept Class 1 frames */ +#define STA_STATE_2 1 /* Accept Class 1 & 2 frames */ +#define STA_STATE_3 2 /* Accept Class 1,2 & 3 frames */ + +/* 15.4.8.5 802.11k RCPI-dBm mapping*/ +#define NDBM_LOW_BOUND_FOR_RCPI 110 +#define RCPI_LOW_BOUND 0 +#define RCPI_HIGH_BOUND 220 +#define RCPI_MEASUREMENT_NOT_AVAILABLE 255 + +/* PHY characteristics */ +/* 17.4.4/18.3.3/19.8.4 Slot Time (aSlotTime) */ +#define SLOT_TIME_LONG 20 /* Long Slot Time */ +#define SLOT_TIME_SHORT 9 /* Short Slot Time */ + +#define SLOT_TIME_HR_DSSS SLOT_TIME_LONG /* 802.11b aSlotTime */ +#define SLOT_TIME_OFDM SLOT_TIME_SHORT /* 802.11a aSlotTime(20M Spacing) */ +#define SLOT_TIME_OFDM_10M_SPACING 13 /* 802.11a aSlotTime(10M Spacing) */ +#define SLOT_TIME_ERP_LONG SLOT_TIME_LONG /* 802.11g aSlotTime(Long) */ +#define SLOT_TIME_ERP_SHORT SLOT_TIME_SHORT /* 802.11g aSlotTime(Short) */ + +/* 17.4.4/18.3.3/19.8.4 Contention Window (aCWmin & aCWmax) */ +#define CWMIN_OFDM 15 /* 802.11a aCWmin */ +#define CWMAX_OFDM 1023 /* 802.11a aCWmax */ + +#define CWMIN_HR_DSSS 31 /* 802.11b aCWmin */ +#define CWMAX_HR_DSSS 1023 /* 802.11b aCWmax */ + +#define CWMIN_ERP_0 31 /* 802.11g aCWmin(0) - for only have 1/2/5/11Mbps Rates */ +#define CWMIN_ERP_1 15 /* 802.11g aCWmin(1) */ +#define CWMAX_ERP 1023 /* 802.11g aCWmax */ + +/* Short Inter-Frame Space (aSIFSTime) */ +/* 15.3.3 802.11b aSIFSTime */ +#define SIFS_TIME_HR_DSSS 10 +/* 17.4.4 802.11a aSIFSTime */ +#define SIFS_TIME_OFDM 16 +/* 19.8.4 802.11g aSIFSTime */ +#define SIFS_TIME_ERP 10 + +/* 15.4.6.2 Number of operating channels */ +#define CH_1 0x1 +#define CH_2 0x2 +#define CH_3 0x3 +#define CH_4 0x4 +#define CH_5 0x5 +#define CH_6 0x6 +#define CH_7 0x7 +#define CH_8 0x8 +#define CH_9 0x9 +#define CH_10 0xa +#define CH_11 0xb +#define CH_12 0xc +#define CH_13 0xd +#define CH_14 0xe + +#define MAXIMUM_OPERATION_CHANNEL_LIST 46 + +/* 3 --------------- IEEE 802.11 PICS --------------- */ +/* Annex D - dot11OperationEntry 2 */ +#define DOT11_RTS_THRESHOLD_MIN 0 +#define DOT11_RTS_THRESHOLD_MAX 2347 /* from Windows DDK */ +/* #define DOT11_RTS_THRESHOLD_MAX 3000 // from Annex D */ + +#define DOT11_RTS_THRESHOLD_DEFAULT \ + DOT11_RTS_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 5 */ +#define DOT11_FRAGMENTATION_THRESHOLD_MIN 256 +#define DOT11_FRAGMENTATION_THRESHOLD_MAX 2346 /* from Windows DDK */ +/* #define DOT11_FRAGMENTATION_THRESHOLD_MAX 3000 // from Annex D */ + +#define DOT11_FRAGMENTATION_THRESHOLD_DEFAULT \ + DOT11_FRAGMENTATION_THRESHOLD_MAX + +/* Annex D - dot11OperationEntry 6 */ +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MIN 1 +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_TRANSMIT_MSDU_LIFETIME_TU_DEFAULT 4095 /* 802.11 define 512 */ + /* MT5921 only aceept N <= 4095 */ + +/* Annex D - dot11OperationEntry 7 */ +#define DOT11_RECEIVE_LIFETIME_TU_MIN 1 +#define DOT11_RECEIVE_LIFETIME_TU_MAX 0xFFFFffff +#define DOT11_RECEIVE_LIFETIME_TU_DEFAULT 4096 /* 802.11 define 512 */ + +/* Annex D - dot11StationConfigEntry 12 */ +#define DOT11_BEACON_PERIOD_MIN 1 /* TU. */ +#define DOT11_BEACON_PERIOD_MAX 0xffff /* TU. */ +#define DOT11_BEACON_PERIOD_DEFAULT 100 /* TU. */ + +/* Annex D - dot11StationConfigEntry 13 */ +#define DOT11_DTIM_PERIOD_MIN 1 /* TU. */ +#define DOT11_DTIM_PERIOD_MAX 255 /* TU. */ +#define DOT11_DTIM_PERIOD_DEFAULT 1 /* TU. */ + +/* Annex D - dot11RegDomainsSupportValue */ +#define REGULATION_DOMAIN_FCC 0x10 /* FCC (US) */ +#define REGULATION_DOMAIN_IC 0x20 /* IC or DOC (Canada) */ +#define REGULATION_DOMAIN_ETSI 0x30 /* ETSI (Europe) */ +#define REGULATION_DOMAIN_SPAIN 0x31 /* Spain */ +#define REGULATION_DOMAIN_FRANCE 0x32 /* France */ +#define REGULATION_DOMAIN_JAPAN 0x40 /* MKK (Japan) */ +#define REGULATION_DOMAIN_CHINA 0x50 /* China */ +#define REGULATION_DOMAIN_OTHER 0x00 /* Other */ + +/* 3 --------------- IEEE 802.11 MAC header fields --------------- */ +/* 7.1.3.1 Masks for the subfields in the Frame Control field */ +#define MASK_FC_PROTOCOL_VER BITS(0, 1) +#define MASK_FC_TYPE BITS(2, 3) +#define MASK_FC_SUBTYPE BITS(4, 7) +#define MASK_FC_SUBTYPE_QOS_DATA BIT(7) +#define MASK_FC_TO_DS BIT(8) +#define MASK_FC_FROM_DS BIT(9) +#define MASK_FC_MORE_FRAG BIT(10) +#define MASK_FC_RETRY BIT(11) +#define MASK_FC_PWR_MGT BIT(12) +#define MASK_FC_MORE_DATA BIT(13) +#define MASK_FC_PROTECTED_FRAME BIT(14) +#define MASK_FC_ORDER BIT(15) + +#define MASK_FRAME_TYPE (MASK_FC_TYPE | MASK_FC_SUBTYPE) +#define MASK_TO_DS_FROM_DS (MASK_FC_TO_DS | MASK_FC_FROM_DS) + +#define MAX_NUM_OF_FC_SUBTYPES 16 +#define OFFSET_OF_FC_SUBTYPE 4 + +/* 7.1.3.1.2 MAC frame types and subtypes */ +#define MAC_FRAME_TYPE_MGT 0 +#define MAC_FRAME_TYPE_CTRL BIT(2) +#define MAC_FRAME_TYPE_DATA BIT(3) +#define MAC_FRAME_TYPE_QOS_DATA (MAC_FRAME_TYPE_DATA | MASK_FC_SUBTYPE_QOS_DATA) + +#define MAC_FRAME_ASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0000) +#define MAC_FRAME_ASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0010) +#define MAC_FRAME_REASSOC_REQ (MAC_FRAME_TYPE_MGT | 0x0020) +#define MAC_FRAME_REASSOC_RSP (MAC_FRAME_TYPE_MGT | 0x0030) +#define MAC_FRAME_PROBE_REQ (MAC_FRAME_TYPE_MGT | 0x0040) +#define MAC_FRAME_PROBE_RSP (MAC_FRAME_TYPE_MGT | 0x0050) +#define MAC_FRAME_BEACON (MAC_FRAME_TYPE_MGT | 0x0080) +#define MAC_FRAME_ATIM (MAC_FRAME_TYPE_MGT | 0x0090) +#define MAC_FRAME_DISASSOC (MAC_FRAME_TYPE_MGT | 0x00A0) +#define MAC_FRAME_AUTH (MAC_FRAME_TYPE_MGT | 0x00B0) +#define MAC_FRAME_DEAUTH (MAC_FRAME_TYPE_MGT | 0x00C0) +#define MAC_FRAME_ACTION (MAC_FRAME_TYPE_MGT | 0x00D0) +#define MAC_FRAME_ACTION_NO_ACK (MAC_FRAME_TYPE_MGT | 0x00E0) + +#define MAC_FRAME_CONTRL_WRAPPER (MAC_FRAME_TYPE_CTRL | 0x0070) +#define MAC_FRAME_BLOCK_ACK_REQ (MAC_FRAME_TYPE_CTRL | 0x0080) +#define MAC_FRAME_BLOCK_ACK (MAC_FRAME_TYPE_CTRL | 0x0090) +#define MAC_FRAME_PS_POLL (MAC_FRAME_TYPE_CTRL | 0x00A0) +#define MAC_FRAME_RTS (MAC_FRAME_TYPE_CTRL | 0x00B0) +#define MAC_FRAME_CTS (MAC_FRAME_TYPE_CTRL | 0x00C0) +#define MAC_FRAME_ACK (MAC_FRAME_TYPE_CTRL | 0x00D0) +#define MAC_FRAME_CF_END (MAC_FRAME_TYPE_CTRL | 0x00E0) +#define MAC_FRAME_CF_END_CF_ACK (MAC_FRAME_TYPE_CTRL | 0x00F0) + +#define MAC_FRAME_DATA (MAC_FRAME_TYPE_DATA | 0x0000) +#define MAC_FRAME_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0010) +#define MAC_FRAME_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0020) +#define MAC_FRAME_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0030) +#define MAC_FRAME_NULL (MAC_FRAME_TYPE_DATA | 0x0040) +#define MAC_FRAME_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0050) +#define MAC_FRAME_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0060) +#define MAC_FRAME_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x0070) +#define MAC_FRAME_QOS_DATA (MAC_FRAME_TYPE_DATA | 0x0080) +#define MAC_FRAME_QOS_DATA_CF_ACK (MAC_FRAME_TYPE_DATA | 0x0090) +#define MAC_FRAME_QOS_DATA_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00A0) +#define MAC_FRAME_QOS_DATA_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00B0) +#define MAC_FRAME_QOS_NULL (MAC_FRAME_TYPE_DATA | 0x00C0) +#define MAC_FRAME_QOS_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00E0) +#define MAC_FRAME_QOS_CF_ACK_CF_POLL (MAC_FRAME_TYPE_DATA | 0x00F0) + +/* 7.1.3.2 Mask for the AID value in the Duration/ID field */ +#define MASK_DI_DURATION BITS(0, 14) +#define MASK_DI_AID BITS(0, 13) +#define MASK_DI_AID_MSB BITS(14, 15) +#define MASK_DI_CFP_FIXED_VALUE BIT(15) + +/* 7.1.3.4 Masks for the subfields in the Sequence Control field */ +#define MASK_SC_SEQ_NUM BITS(4, 15) +#define MASK_SC_SEQ_NUM_OFFSET 4 +#define MASK_SC_FRAG_NUM BITS(0, 3) +#define INVALID_SEQ_CTRL_NUM 0x000F /* According to 6.2.1.1.2 + * FRAG_NUM won't equal to 15 + */ + +/* 7.1.3.5 QoS Control field */ +#define TID_NUM 16 +#define TID_MASK BITS(0, 3) +#define EOSP BIT(4) +#define ACK_POLICY BITS(5, 6) +#define A_MSDU_PRESENT BIT(7) + +#define MASK_QC_TID BITS(0, 3) +#define MASK_QC_EOSP BIT(4) +#define MASK_QC_EOSP_OFFSET 4 +#define MASK_QC_ACK_POLICY BITS(5, 6) +#define MASK_QC_ACK_POLICY_OFFSET 5 +#define MASK_QC_A_MSDU_PRESENT BIT(7) + +/* 7.1.3.5a HT Control field */ +#define HT_CTRL_LINK_ADAPTATION_CTRL BITS(0, 15) +#define HT_CTRL_CALIBRATION_POSITION BITS(16, 17) +#define HT_CTRL_CALIBRATION_SEQUENCE BITS(18, 19) +#define HT_CTRL_CSI_STEERING BITS(22, 23) +#define HT_CTRL_NDP_ANNOUNCEMENT BIT(24) +#define HT_CTRL_AC_CONSTRAINT BIT(30) +#define HT_CTRL_RDG_MORE_PPDU BIT(31) + +#define LINK_ADAPTATION_CTRL_TRQ BIT(1) +#define LINK_ADAPTATION_CTRL_MAI_MRQ BIT(2) +#define LINK_ADAPTATION_CTRL_MAI_MSI BITS(3, 5) +#define LINK_ADAPTATION_CTRL_MFSI BITS(6, 8) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_CMD BITS(9, 11) +#define LINK_ADAPTATION_CTRL_MFB_ASELC_DATA BITS(12, 15) + +/* 7.1.3.5.3 Ack Policy subfield*/ +#define ACK_POLICY_NORMAL_ACK_IMPLICIT_BA_REQ 0 +#define ACK_POLICY_NO_ACK 1 +#define ACK_POLICY_NO_EXPLICIT_ACK_PSMP_ACK 2 +#define ACK_POLICY_BA 3 + +/* 7.1.3.7 FCS field */ +#define FCS_LEN 4 + +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +#define PSPOLL_FRAME_LEN 16 /* w/o FCS */ + +/* 7.2.7.1 BAR */ +#define OFFSET_BAR_SSC_SN 4 + +/* 8.3.2.2 TKIP MPDU formats */ +#define TKIP_MIC_LEN 8 + +/* 2009.11.30 mtk02468: Moved these definitions to the right place */ +#if 0 +/* Block Ack Parameter Set field */ +#define BA_PARM_BA_POLICY BIT(1) +#define BA_PARM_TID BITS(2, 5) +#define BA_PARM_BUFFER_SIZE BITS(6, 15) +#endif + +#define BA_POLICY_IMMEDIATE BIT(1) + +/* Block Ack Starting Sequence Control field */ +#define BA_START_SEQ_CTL_FRAG_NUM BITS(0, 3) +#define BA_START_SEQ_CTL_SSN BITS(4, 15) + +/* BAR Control field */ +#define BAR_CONTROL_NO_ACK_POLICY BIT(0) +#define BAR_CONTROL_MULTI_TID BIT(1) +#define BAR_CONTROL_COMPRESSED_BA BIT(2) +#define BAR_CONTROL_TID_INFO BITS(12, 15) +#define BAR_CONTROL_TID_INFO_OFFSET 12 + +/* TID Value */ +#define BAR_INFO_TID_VALUE BITS(12, 15) + +#define BAR_COMPRESSED_VARIANT_FRAME_LEN (16 + 4) + +/* 3 --------------- IEEE 802.11 frame body fields --------------- */ +/* 3 Management frame body components (I): Fixed Fields. */ +/* 7.3.1.1 Authentication Algorithm Number field */ +#define AUTH_ALGORITHM_NUM_FIELD_LEN 2 + +#define AUTH_ALGORITHM_NUM_OPEN_SYSTEM 0 /* Open System */ +#define AUTH_ALGORITHM_NUM_SHARED_KEY 1 /* Shared Key */ +#define AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION 2 /* Fast BSS Transition */ + +/* 7.3.1.2 Authentication Transaction Sequence Number field */ +#define AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN 2 +#define AUTH_TRANSACTION_SEQ_1 1 +#define AUTH_TRANSACTION_SEQ_2 2 +#define AUTH_TRANSACTION_SEQ_3 3 +#define AUTH_TRANSACTION_SEQ_4 4 + +/* 7.3.1.3 Beacon Interval field */ +#define BEACON_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.4 Capability Information field */ +#define CAP_INFO_FIELD_LEN 2 +#define CAP_INFO_ESS BIT(0) +#define CAP_INFO_IBSS BIT(1) +#define CAP_INFO_BSS_TYPE (CAP_INFO_ESS | CAP_INFO_IBSS) +#define CAP_INFO_CF_POLLABLE BIT(2) +#define CAP_INFO_CF_POLL_REQ BIT(3) +#define CAP_INFO_CF (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) +#define CAP_INFO_PRIVACY BIT(4) +#define CAP_INFO_SHORT_PREAMBLE BIT(5) +#define CAP_INFO_PBCC BIT(6) +#define CAP_INFO_CH_AGILITY BIT(7) +#define CAP_INFO_SPEC_MGT BIT(8) +#define CAP_INFO_QOS BIT(9) +#define CAP_INFO_SHORT_SLOT_TIME BIT(10) +#define CAP_INFO_APSD BIT(11) +#define CAP_INFO_RESERVED BIT(12) +#define CAP_INFO_DSSS_OFDM BIT(13) +#define CAP_INFO_DELAYED_BLOCK_ACK BIT(14) +#define CAP_INFO_IMM_BLOCK_ACK BIT(15) +/* STA usage of CF-Pollable and CF-Poll Request subfields */ +/* STA: not CF-Pollable */ +#define CAP_CF_STA_NOT_POLLABLE 0x0000 +/* STA: CF-Pollable, not requesting on the CF-Polling list */ +#define CAP_CF_STA_NOT_ON_LIST CAP_INFO_CF_POLL_REQ +/* STA: CF-Pollable, requesting on the CF-Polling list */ +#define CAP_CF_STA_ON_LIST CAP_INFO_CF_POLLABLE +/* STA: CF-Pollable, requesting never to be polled */ +#define CAP_CF_STA_NEVER_POLLED (CAP_INFO_CF_POLLABLE | CAP_INFO_CF_POLL_REQ) + +/* AP usage of CF-Pollable and CF-Poll Request subfields */ +/* AP: No point coordinator (PC) */ +#define CAP_CF_AP_NO_PC 0x0000 +/* AP: PC at AP for delivery only (no polling) */ +#define CAP_CF_AP_DELIVERY_ONLY CAP_INFO_CF_POLL_REQ +/* AP: PC at AP for delivery and polling */ +#define CAP_CF_AP_DELIVERY_POLLING CAP_INFO_CF_POLLABLE + +/* 7.3.1.5 Current AP Address field */ +#define CURR_AP_ADDR_FIELD_LEN MAC_ADDR_LEN + +/* 7.3.1.6 Listen Interval field */ +#define LISTEN_INTERVAL_FIELD_LEN 2 + +/* 7.3.1.7 Reason Code field */ +#define REASON_CODE_FIELD_LEN 2 + +#define REASON_CODE_RESERVED 0 /* Reseved */ +#define REASON_CODE_UNSPECIFIED 1 /* Unspecified reason */ +#define REASON_CODE_PREV_AUTH_INVALID 2 /* Previous auth no longer valid */ +#define REASON_CODE_DEAUTH_LEAVING_BSS 3 /* Deauth because sending STA is leaving BSS */ +#define REASON_CODE_DISASSOC_INACTIVITY 4 /* Disassoc due to inactivity */ +#define REASON_CODE_DISASSOC_AP_OVERLOAD 5 /* Disassoc because AP is unable to handle all assoc STAs */ +#define REASON_CODE_CLASS_2_ERR 6 /* Class 2 frame rx from nonauth STA */ +#define REASON_CODE_CLASS_3_ERR 7 /* Class 3 frame rx from nonassoc STA */ +#define REASON_CODE_DISASSOC_LEAVING_BSS 8 /* Disassoc because sending STA is leaving BSS */ +#define REASON_CODE_ASSOC_BEFORE_AUTH 9 /* STA requesting (re)assoc is not auth with responding STA */ +#define REASON_CODE_DISASSOC_PWR_CAP_UNACCEPTABLE 10 /* Disassoc because the info in Power Capability is + unacceptable */ +#define REASON_CODE_DISASSOC_SUP_CHS_UNACCEPTABLE 11 /* Disassoc because the info in Supported Channels is + unacceptable */ +#define REASON_CODE_INVALID_INFO_ELEM 13 /* Invalid information element */ +#define REASON_CODE_MIC_FAILURE 14 /* MIC failure */ +#define REASON_CODE_4_WAY_HANDSHAKE_TIMEOUT 15 /* 4-way handshake timeout */ +#define REASON_CODE_GROUP_KEY_UPDATE_TIMEOUT 16 /* Group key update timeout */ +#define REASON_CODE_DIFFERENT_INFO_ELEM 17 /* Info element in 4-way handshake different from + (Re-)associate request/Probe response/Beacon */ +#define REASON_CODE_MULTICAST_CIPHER_NOT_VALID 18 /* Multicast Cipher is not valid */ +#define REASON_CODE_UNICAST_CIPHER_NOT_VALID 19 /* Unicast Cipher is not valid */ +#define REASON_CODE_AKMP_NOT_VALID 20 /* AKMP is not valid */ +#define REASON_CODE_UNSUPPORTED_RSNE_VERSION 21 /* Unsupported RSNE version */ +#define REASON_CODE_INVALID_RSNE_CAPABILITIES 22 /* Invalid RSNE Capabilities */ +#define REASON_CODE_IEEE_802_1X_AUTH_FAILED 23 /* IEEE 802.1X Authentication failed */ +#define REASON_CODE_CIPHER_REJECT_SEC_POLICY 24 /* Cipher suite rejected because of the security policy */ +#define REASON_CODE_DISASSOC_UNSPECIFIED_QOS 32 /* Disassoc for unspecified, QoS-related reason */ +#define REASON_CODE_DISASSOC_LACK_OF_BANDWIDTH 33 /* Disassoc because QAP lacks sufficient bandwidth + for this QSTA */ +#define REASON_CODE_DISASSOC_ACK_LOST_POOR_CHANNEL 34 /* Disassoc because of too many ACKs lost for AP transmissions + and/or poor channel conditions */ +#define REASON_CODE_DISASSOC_TX_OUTSIDE_TXOP_LIMIT 35 /* Disassoc because QSTA is transmitting outside the limits of + its TXOPs */ +#define REASON_CODE_PEER_WHILE_LEAVING 36 /* QSTA is leaving the QBSS or resetting */ +#define REASON_CODE_PEER_REFUSE_DLP 37 /* Peer does not want to use this mechanism */ +#define REASON_CODE_PEER_SETUP_REQUIRED 38 /* Frames received but a setup is reqired */ +#define REASON_CODE_PEER_TIME_OUT 39 /* Time out */ +#define REASON_CODE_PEER_CIPHER_UNSUPPORTED 45 /* Peer does not support the requested cipher suite */ +#define REASON_CODE_BEACON_TIMEOUT 100 /* for beacon timeout, defined by mediatek */ +#define REASON_CODE_BSS_SECURITY_CHANGE 101 /* for BSS security change, defined by mediatek */ +/* 7.3.1.8 AID field */ +#define AID_FIELD_LEN 2 +#define AID_MASK BITS(0, 13) +#define AID_MSB BITS(14, 15) +#define AID_MIN_VALUE 1 +#define AID_MAX_VALUE 2007 + +/* 7.3.1.9 Status Code field */ +#define STATUS_CODE_FIELD_LEN 2 + +#define STATUS_CODE_RESERVED 0 /* Reserved - Used by TX Auth */ +#define STATUS_CODE_SUCCESSFUL 0 /* Successful */ +#define STATUS_CODE_UNSPECIFIED_FAILURE 1 /* Unspecified failure */ +#define STATUS_CODE_CAP_NOT_SUPPORTED 10 /* Cannot support all requested cap in the Cap Info field */ +#define STATUS_CODE_REASSOC_DENIED_WITHOUT_ASSOC 11 /* Reassoc denied due to inability to confirm that + assoc exists */ +#define STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD 12 /* Assoc denied due to reason outside the scope of this std. */ +#define STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED 13 /* Responding STA does not support the specified + auth algorithm */ +#define STATUS_CODE_AUTH_OUT_OF_SEQ 14 /* Rx an auth frame with auth transaction seq num + out of expected seq */ +#define STATUS_CODE_AUTH_REJECTED_CHAL_FAIL 15 /* Auth rejected because of challenge failure */ +#define STATUS_CODE_AUTH_REJECTED_TIMEOUT 16 /* Auth rejected due to timeout waiting for next frame + in sequence */ +#define STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD 17 /* Assoc denied because AP is unable to handle additional + assoc STAs */ +#define STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED 18 /* Assoc denied due to requesting STA not supporting + all of basic rates */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_PREAMBLE 19 /* Assoc denied due to requesting STA not supporting short + preamble */ +#define STATUS_CODE_ASSOC_DENIED_NO_PBCC 20 /* Assoc denied due to requesting STA not supporting PBCC */ +#define STATUS_CODE_ASSOC_DENIED_NO_CH_AGILITY 21 /* Assoc denied due to requesting STA not supporting channel + agility */ +#define STATUS_CODE_ASSOC_REJECTED_NO_SPEC_MGT 22 /* Assoc rejected because Spectrum Mgt capability is required */ +#define STATUS_CODE_ASSOC_REJECTED_PWR_CAP 23 /* Assoc rejected because the info in Power Capability + is unacceptable */ +#define STATUS_CODE_ASSOC_REJECTED_SUP_CHS 24 /* Assoc rejected because the info in Supported Channels + is unacceptable */ +#define STATUS_CODE_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 /* Assoc denied due to requesting STA not supporting + short slot time */ +#define STATUS_CODE_ASSOC_DENIED_NO_DSSS_OFDM 26 /* Assoc denied due to requesting STA not supporting + DSSS-OFDM */ +#if CFG_SUPPORT_802_11W +#define STATUS_CODE_ASSOC_REJECTED_TEMPORARILY 30 /* IEEE 802.11w, Assoc denied due to the SA query */ +#define STATUS_CODE_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 /* IEEE 802.11w, Assoc denied due to the MFP select + policy */ +#endif +#define STATUS_CODE_UNSPECIFIED_QOS_FAILURE 32 /* Unspecified, QoS-related failure */ +#define STATUS_CODE_ASSOC_DENIED_BANDWIDTH 33 /* Assoc denied due to insufficient bandwidth to handle another + QSTA */ +#define STATUS_CODE_ASSOC_DENIED_POOR_CHANNEL 34 /* Assoc denied due to excessive frame loss rates and/or poor + channel conditions */ +#define STATUS_CODE_ASSOC_DENIED_NO_QOS_FACILITY 35 /* Assoc denied due to requesting STA not supporting QoS + facility */ +#define STATUS_CODE_REQ_DECLINED 37 /* Request has been declined */ +#define STATUS_CODE_REQ_INVALID_PARAMETER_VALUE 38 /* Request has not been successful as one or more parameters + have invalid values */ +#define STATUS_CODE_REQ_NOT_HONORED_TSPEC 39 /* TS not created because request cannot be honored. + Suggested TSPEC provided. */ +#define STATUS_CODE_INVALID_INFO_ELEMENT 40 /* Invalid information element */ +#define STATUS_CODE_INVALID_GROUP_CIPHER 41 /* Invalid group cipher */ +#define STATUS_CODE_INVALID_PAIRWISE_CIPHER 42 /* Invalid pairwise cipher */ +#define STATUS_CODE_INVALID_AKMP 43 /* Invalid AKMP */ +#define STATUS_CODE_UNSUPPORTED_RSN_IE_VERSION 44 /* Unsupported RSN information element version */ +#define STATUS_CODE_INVALID_RSN_IE_CAP 45 /* Invalid RSN information element capabilities */ +#define STATUS_CODE_CIPHER_SUITE_REJECTED 46 /* Cipher suite rejected because of security policy */ +#define STATUS_CODE_REQ_NOT_HONORED_TS_DELAY 47 /* TS not created because request cannot be honored. + Attempt to create a TS later. */ +#define STATUS_CODE_DIRECT_LINK_NOT_ALLOWED 48 /* Direct Link is not allowed in the BSS by policy */ +#define STATUS_CODE_DESTINATION_STA_NOT_PRESENT 49 /* Destination STA is not present within this QBSS */ +#define STATUS_CODE_DESTINATION_STA_NOT_QSTA 50 /* Destination STA is not a QSTA */ +#define STATUS_CODE_ASSOC_DENIED_LARGE_LIS_INTERVAL 51 /* Association denied because the ListenInterval is too large */ + +/* proprietary definition of reserved field of Status Code */ +#define STATUS_CODE_JOIN_FAILURE 0xFFF0 /* Join failure */ +#define STATUS_CODE_JOIN_TIMEOUT 0xFFF1 /* Join timeout */ +#define STATUS_CODE_AUTH_TIMEOUT 0xFFF2 /* Authentication timeout */ +#define STATUS_CODE_ASSOC_TIMEOUT 0xFFF3 /* (Re)Association timeout */ +#define STATUS_CODE_CCX_CCKM_REASSOC_FAILURE 0xFFF4 /* CCX CCKM reassociation failure */ + +/* 7.3.1.10 Timestamp field */ +#define TIMESTAMP_FIELD_LEN 8 + +/* 7.3.1.11 Category of Action field */ +#define CATEGORY_SPEC_MGT 0 +#define CATEGORY_QOS_ACTION 1 /* QoS action */ +#define CATEGORY_DLS_ACTION 2 /* Direct Link Protocol (DLP) action */ +#define CATEGORY_BLOCK_ACK_ACTION 3 /* Block ack action */ +#define CATEGORY_PUBLIC_ACTION 4 /* Public action */ +#define CATEGORY_RM_ACTION 5 /* Radio measurement action */ +#define CATEGORY_HT_ACTION 7 +#if CFG_SUPPORT_802_11W +#define CATEGORY_SA_QUERT_ACTION 8 +#endif +#define CATEGORY_WNM_ACTION 10 /* 802.11v Wireless Network Management */ +#define CATEGORY_UNPROTECTED_WNM_ACTION 11 /* 802.11v Wireless Network Management */ +#define CATEGORY_WME_MGT_NOTIFICATION 17 /* WME management notification */ +#define CATEGORY_VENDOR_SPECIFIC_ACTION 127 + +/* 7.3.1.14 Block Ack Parameter Set field */ +#define BA_PARAM_SET_ACK_POLICY_MASK BIT(1) +#define BA_PARAM_SET_ACK_POLICY_MASK_OFFSET 1 +#define BA_PARAM_SET_TID_MASK BITS(2, 5) +#define BA_PARAM_SET_TID_MASK_OFFSET 2 +#define BA_PARAM_SET_BUFFER_SIZE_MASK BITS(6, 15) +#define BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET 6 + +#define BA_PARAM_SET_ACK_POLICY_IMMEDIATE_BA 1 +#define BA_PARAM_SET_ACK_POLICY_DELAYED_BA 0 + +/* 3 Management frame body components (II): Information Elements. */ +/* 7.3.2 Element IDs of information elements */ +#define ELEM_HDR_LEN 2 + +#define ELEM_ID_SSID 0 /* SSID */ +#define ELEM_ID_SUP_RATES 1 /* Supported rates */ +#define ELEM_ID_FH_PARAM_SET 2 /* FH parameter set */ +#define ELEM_ID_DS_PARAM_SET 3 /* DS parameter set */ +#define ELEM_ID_CF_PARAM_SET 4 /* CF parameter set */ +#define ELEM_ID_TIM 5 /* TIM */ +#define ELEM_ID_IBSS_PARAM_SET 6 /* IBSS parameter set */ +#define ELEM_ID_COUNTRY_INFO 7 /* Country information */ +#define ELEM_ID_HOPPING_PATTERN_PARAM 8 /* Hopping pattern parameters */ +#define ELEM_ID_HOPPING_PATTERN_TABLE 9 /* Hopping pattern table */ +#define ELEM_ID_REQUEST 10 /* Request */ +#define ELEM_ID_BSS_LOAD 11 /* BSS load */ +#define ELEM_ID_EDCA_PARAM_SET 12 /* EDCA parameter set */ +#define ELEM_ID_TSPEC 13 /* Traffic specification (TSPEC) */ +#define ELEM_ID_TCLAS 14 /* Traffic classification (TCLAS) */ +#define ELEM_ID_SCHEDULE 15 /* Schedule */ +#define ELEM_ID_CHALLENGE_TEXT 16 /* Challenge text */ + +#define ELEM_ID_PWR_CONSTRAINT 32 /* Power constraint */ +#define ELEM_ID_PWR_CAP 33 /* Power capability */ +#define ELEM_ID_TPC_REQ 34 /* TPC request */ +#define ELEM_ID_TPC_REPORT 35 /* TPC report */ +#define ELEM_ID_SUP_CHS 36 /* Supported channels */ +#define ELEM_ID_CH_SW_ANNOUNCEMENT 37 /* Channel switch announcement */ +#define ELEM_ID_MEASUREMENT_REQ 38 /* Measurement request */ +#define ELEM_ID_MEASUREMENT_REPORT 39 /* Measurement report */ +#define ELEM_ID_QUIET 40 /* Quiet */ +#define ELEM_ID_IBSS_DFS 41 /* IBSS DFS */ +#define ELEM_ID_ERP_INFO 42 /* ERP information */ +#define ELEM_ID_TS_DELAY 43 /* TS delay */ +#define ELEM_ID_TCLAS_PROCESSING 44 /* TCLAS processing */ +#define ELEM_ID_HT_CAP 45 /* HT Capabilities subelement */ +#define ELEM_ID_QOS_CAP 46 /* QoS capability */ +#define ELEM_ID_RSN 48 /* RSN IE */ +#define ELEM_ID_EXTENDED_SUP_RATES 50 /* Extended supported rates */ +#define ELEM_ID_TIMEOUT_INTERVAL 56 /* 802.11w SA Timeout interval */ +#define ELEM_ID_SUP_OPERATING_CLASS 59 /* Supported Operating Classes */ +#define ELEM_ID_HT_OP 61 /* HT Operation */ +#define ELEM_ID_SCO 62 /* Secondary Channel Offset */ +#define ELEM_ID_RRM_ENABLED_CAP 70 /* Radio Resource Management Enabled Capabilities */ +#define ELEM_ID_20_40_BSS_COEXISTENCE 72 /* 20/40 BSS Coexistence */ +#define ELEM_ID_20_40_INTOLERANT_CHNL_REPORT 73 /* 20/40 BSS Intolerant Channel Report */ +#define ELEM_ID_OBSS_SCAN_PARAMS 74 /* Overlapping BSS Scan Parameters */ +#define ELEM_ID_INTERWORKING 107 /* Interworking with External Network */ +#define ELEM_ID_ADVERTISEMENT_PROTOCOL 108 /* Advertisement Protocol */ +#define ELEM_ID_ROAMING_CONSORTIUM 111 /* Roaming Consortium */ +#define ELEM_ID_EXTENDED_CAP 127 /* Extended capabilities */ + +#define ELEM_ID_VENDOR 221 /* Vendor specific IE */ +#define ELEM_ID_WPA ELEM_ID_VENDOR /* WPA IE */ +#define ELEM_ID_WMM ELEM_ID_VENDOR /* WMM IE */ +#define ELEM_ID_P2P ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WFD ELEM_ID_VENDOR /* WiFi Direct */ +#define ELEM_ID_WSC ELEM_ID_VENDOR /* WSC IE */ + +#define ELEM_ID_RESERVED 255 /* Reserved */ + +/* 7.3.2.1 SSID element */ +#define ELEM_MAX_LEN_SSID 32 + +/* 7.3.2.2 Supported Rates */ +#define ELEM_MAX_LEN_SUP_RATES 8 + +/* 7.3.2.4 DS Parameter Set */ +#define ELEM_MAX_LEN_DS_PARAMETER_SET 1 + +/* 7.3.2.5 CF Parameter Set */ +#define ELEM_CF_PARM_LEN 8 + +/* 7.3.2.6 TIM */ +#define ELEM_MIX_LEN_TIM 4 +#define ELEM_MAX_LEN_TIM 254 + +/* 7.3.2.7 IBSS Parameter Set element */ +#define ELEM_MAX_LEN_IBSS_PARAMETER_SET 2 + +/* 7.3.2.8 Challenge Text element */ +#define ELEM_MIN_LEN_CHALLENGE_TEXT 1 +#define ELEM_MAX_LEN_CHALLENGE_TEXT 253 + +/* 7.3.2.9 Country Information element */ +/* Country IE should contain at least 3-bytes country code string and one subband triplet. */ +#define ELEM_MIN_LEN_COUNTRY_INFO 6 + +#define ELEM_ID_COUNTRY_INFO_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_SUBBAND_TRIPLET_LEN_FIXED 3 +#define ELEM_ID_COUNTRY_INFO_REGULATORY_TRIPLET_LEN_FIXED 3 + +/* 7.3.2.13 ERP Information element */ +#define ELEM_MAX_LEN_ERP 1 +/* -- bits in the ERP Information element */ +#define ERP_INFO_NON_ERP_PRESENT BIT(0) /* NonERP_Present bit */ +#define ERP_INFO_USE_PROTECTION BIT(1) /* Use_Protection bit */ +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) /* Barker_Preamble_Mode bit */ + +/* 7.3.2.14 Extended Supported Rates */ +#define ELEM_MAX_LEN_EXTENDED_SUP_RATES 255 + +#if CFG_SUPPORT_DFS +/* 7.3.2.19 Supported Channels element */ +#define ELEM_MAX_LEN_SUPPORTED_CHANNELS 7 +#endif + +/* 7.3.2.21 Measurement Request element */ +#define ELEM_RM_TYPE_BASIC_REQ 0 +#define ELEM_RM_TYPE_CCA_REQ 1 +#define ELEM_RM_TYPE_RPI_HISTOGRAM_REQ 2 +#define ELEM_RM_TYPE_CHNL_LOAD_REQ 3 +#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REQ 4 +#define ELEM_RM_TYPE_BEACON_REQ 5 +#define ELEM_RM_TYPE_FRAME_REQ 6 +#define ELEM_RM_TYPE_STA_STATISTICS_REQ 7 +#define ELEM_RM_TYPE_LCI_REQ 8 +#define ELEM_RM_TYPE_TS_REQ 9 +#define ELEM_RM_TYPE_MEASURE_PAUSE_REQ 255 + +/* 7.3.2.22 Measurement Report element */ +#define ELEM_RM_TYPE_BASIC_REPORT 0 +#define ELEM_RM_TYPE_CCA_REPORT 1 +#define ELEM_RM_TYPE_RPI_HISTOGRAM_REPORT 2 +#define ELEM_RM_TYPE_CHNL_LOAD_REPORT 3 +#define ELEM_RM_TYPE_NOISE_HISTOGRAM_REPORT 4 +#define ELEM_RM_TYPE_BEACON_REPORT 5 +#define ELEM_RM_TYPE_FRAME_REPORT 6 +#define ELEM_RM_TYPE_STA_STATISTICS_REPORT 7 +#define ELEM_RM_TYPE_LCI_REPORT 8 +#define ELEM_RM_TYPE_TS_REPORT 9 +/*Auto Channel Selection*/ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +#define ELEM_RM_TYPE_ACS_CHN 1 +#define ELEM_RM_TYPE_LTE_CHN 2 +#endif + +/* 7.3.2.25 RSN information element */ +#define ELEM_MAX_LEN_WPA 34 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_RSN 38 /* one pairwise, one AKM suite, one PMKID */ +#define ELEM_MAX_LEN_WAPI 38 /* one pairwise, one AKM suite, one BKID */ +#define ELEM_MAX_LEN_WSC 200 /* one pairwise, one AKM suite, one BKID */ + +#if CFG_SUPPORT_802_11W +#define ELEM_WPA_CAP_MFPR BIT(6) +#define ELEM_WPA_CAP_MFPC BIT(7) +#endif + +/* 7.3.2.27 Extended Capabilities information element */ +#define ELEM_EXT_CAP_20_40_COEXIST_SUPPORT BIT(0) +#define ELEM_EXT_CAP_PSMP_CAP BIT(4) +#define ELEM_EXT_CAP_SERVICE_INTERVAL_GRANULARITY BIT(5) +#define ELEM_EXT_CAP_SCHEDULE_PSMP BIT(6) + +#define ELEM_EXT_CAP_BSS_TRANSITION_BIT 19 +#define ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT 27 +#define ELEM_EXT_CAP_INTERWORKING_BIT 31 +#define ELEM_EXT_CAP_WNM_NOTIFICATION_BIT 46 + +#if CFG_SUPPORT_HOTSPOT_2_0 +#define ELEM_MAX_LEN_EXT_CAP (6) +#else +#define ELEM_MAX_LEN_EXT_CAP (3 - ELEM_HDR_LEN) +#endif + +/* 7.3.2.30 TSPEC element */ +#define TS_INFO_TRAFFIC_TYPE_MASK BIT(0) /* WMM: 0 (Asynchronous TS of low-duty cycles) */ +#define TS_INFO_TID_OFFSET 1 +#define TS_INFO_TID_MASK BITS(1, 4) +#define TS_INFO_DIRECTION_OFFSET 5 +#define TS_INFO_DIRECTION_MASK BITS(5, 6) +#define TS_INFO_ACCESS_POLICY_OFFSET 7 +#define TS_INFO_ACCESS_POLICY_MASK BITS(7, 8) +#define TS_INFO_AGGREGATION_MASK BIT(9) /* WMM: 0 */ +#define TS_INFO_APSD_MASK BIT(10) +#define TS_INFO_UP_OFFSET 11 +#define TS_INFO_UP_MASK BITS(11, 13) +#define TS_INFO_ACK_POLICY_OFFSET 14 +#define TS_INFO_ACK_POLICY_MASK BITS(14, 15) +#define TS_INFO_SCHEDULE_MASK 16 + +/* 7.3.2.56 HT capabilities element */ +#define ELEM_MAX_LEN_HT_CAP (28 - ELEM_HDR_LEN) /* sizeof(IE_HT_CAP_T)-2 */ + +/* 7.3.2.56.2 HT capabilities Info field */ +#define HT_CAP_INFO_LDPC_CAP BIT(0) +#define HT_CAP_INFO_SUP_CHNL_WIDTH BIT(1) +#define HT_CAP_INFO_SM_POWER_SAVE BITS(2, 3) +#define HT_CAP_INFO_HT_GF BIT(4) +#define HT_CAP_INFO_SHORT_GI_20M BIT(5) +#define HT_CAP_INFO_SHORT_GI_40M BIT(6) +#define HT_CAP_INFO_TX_STBC BIT(7) +#define HT_CAP_INFO_RX_STBC BITS(8, 9) +#define HT_CAP_INFO_HT_DELAYED_BA BIT(10) +#define HT_CAP_INFO_MAX_AMSDU_LEN BIT(11) +#define HT_CAP_INFO_DSSS_CCK_IN_40M BIT(12) +#define HT_CAP_INFO_40M_INTOLERANT BIT(14) +#define HT_CAP_INFO_LSIG_TXOP_SUPPORT BIT(15) + +#define HT_CAP_INFO_RX_STBC_NO_SUPPORTED 0 +#define HT_CAP_INFO_RX_STBC_1_SS BIT(8) +#define HT_CAP_INFO_RX_STBC_2_SS BIT(9) +#define HT_CAP_INFO_RX_STBC_3_SS HT_CAP_INFO_RX_STBC + +/* 7.3.2.56.3 A-MPDU Parameters field */ +#define AMPDU_PARAM_MAX_AMPDU_LEN_EXP BITS(0, 1) +#define AMPDU_PARAM_MIN_START_SPACING BITS(2, 4) + +#define AMPDU_PARAM_MAX_AMPDU_LEN_8K 0 +#define AMPDU_PARAM_MAX_AMPDU_LEN_16K BIT(0) +#define AMPDU_PARAM_MAX_AMPDU_LEN_32K BIT(1) +#define AMPDU_PARAM_MAX_AMPDU_LEN_64K BITS(0, 1) + +#define AMPDU_PARAM_MSS_NO_RESTRICIT 0 +#define AMPDU_PARAM_MSS_1_4_US BIT(2) +#define AMPDU_PARAM_MSS_1_2_US BIT(3) +#define AMPDU_PARAM_MSS_1_US BITS(2, 3) +#define AMPDU_PARAM_MSS_2_US BIT(4) +#define AMPDU_PARAM_MSS_4_US (BIT(4) | BIT(2)) +#define AMPDU_PARAM_MSS_8_US (BIT(4) | BIT(3)) +#define AMPDU_PARAM_MSS_16_US BITS(2, 4) + +/* 7.3.2.56.4 Supported MCS Set field (TX rate: octects 12~15) */ +#define SUP_MCS_TX_SET_DEFINED BIT(0) +#define SUP_MCS_TX_RX_SET_NOT_EQUAL BIT(1) +#define SUP_MCS_TX_MAX_NUM_SS BITS(2, 3) +#define SUP_MCS_TX_UNEQUAL_MODULATION BIT(4) + +#define SUP_MCS_TX_MAX_NUM_1_SS 0 +#define SUP_MCS_TX_MAX_NUM_2_SS BIT(2) +#define SUP_MCS_TX_MAX_NUM_3_SS BIT(3) +#define SUP_MCS_TX_MAX_NUM_4_SS BITS(2, 3) + +#define SUP_MCS_RX_BITMASK_OCTET_NUM 10 +#define SUP_MCS_RX_DEFAULT_HIGHEST_RATE 0 /* Not specify */ + +/* 7.3.2.56.5 HT Extended Capabilities field */ +#define HT_EXT_CAP_PCO BIT(0) +#define HT_EXT_CAP_PCO_TRANSITION_TIME BITS(1, 2) +#define HT_EXT_CAP_MCS_FEEDBACK BITS(8, 9) +#define HT_EXT_CAP_HTC_SUPPORT BIT(10) +#define HT_EXT_CAP_RD_RESPONDER BIT(11) + +#define HT_EXT_CAP_PCO_TRANS_TIME_NONE 0 +#define HT_EXT_CAP_PCO_TRANS_TIME_400US BIT(1) +#define HT_EXT_CAP_PCO_TRANS_TIME_1_5MS BIT(2) +#define HT_EXT_CAP_PCO_TRANS_TIME_5MS BITS(1, 2) + +#define HT_EXT_CAP_MCS_FEEDBACK_NO_FB 0 +#define HT_EXT_CAP_MCS_FEEDBACK_UNSOLICITED BIT(9) +#define HT_EXT_CAP_MCS_FEEDBACK_BOTH BITS(8, 9) + +/* 7.3.2.56.6 Transmit Beamforming Capabilities field */ + +/* 7.3.2.56.7 Antenna Selection Capability field */ +#define ASEL_CAP_CAPABLE BIT(0) +#define ASEL_CAP_CSI_FB_BY_TX_ASEL_CAPABLE BIT(1) +#define ASEL_CAP_ANT_INDICES_FB_BY_TX_ASEL_CAPABLE BIT(2) +#define ASEL_CAP_EXPLICIT_CSI_FB_CAPABLE BIT(3) +#define ASEL_CAP_ANT_INDICES_CAPABLE BIT(4) +#define ASEL_CAP_RX_ASEL_CAPABLE BIT(5) +#define ASEL_CAP_TX_SOUNDING_CAPABLE BIT(6) + +/* 7.3.2.57 HT Operation element */ +#define ELEM_MAX_LEN_HT_OP (24 - ELEM_HDR_LEN) /* sizeof(IE_HT_OP_T)-2 */ + +#define HT_OP_INFO1_SCO BITS(0, 1) +#define HT_OP_INFO1_STA_CHNL_WIDTH BIT(2) +#define HT_OP_INFO1_RIFS_MODE BIT(3) + +#define HT_OP_INFO2_HT_PROTECTION BITS(0, 1) +#define HT_OP_INFO2_NON_GF_HT_STA_PRESENT BIT(2) +#define HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT BIT(4) + +#define HT_OP_INFO3_DUAL_BEACON BIT(6) +#define HT_OP_INFO3_DUAL_CTS_PROTECTION BIT(7) +#define HT_OP_INFO3_STBC_BEACON BIT(8) +#define HT_OP_INFO3_LSIG_TXOP_FULL_SUPPORT BIT(9) +#define HT_OP_INFO3_PCO_ACTIVE BIT(10) +#define HT_OP_INFO3_PCO_PHASE BIT(11) + +/* 7.3.2.59 OBSS Scan Parameter element */ +#define ELEM_MAX_LEN_OBSS_SCAN (16 - ELEM_HDR_LEN) + +/* 7.3.2.60 20/40 BSS Coexistence element */ +#define ELEM_MAX_LEN_20_40_BSS_COEXIST (3 - ELEM_HDR_LEN) + +#define BSS_COEXIST_INFO_REQ BIT(0) +#define BSS_COEXIST_40M_INTOLERANT BIT(1) +#define BSS_COEXIST_20M_REQ BIT(2) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ BIT(3) +#define BSS_COEXIST_OBSS_SCAN_EXEMPTION_GRANT BIT(4) + +/* 802.11u 7.3.2.92 Interworking IE */ +#define ELEM_MAX_LEN_INTERWORKING (11 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.93 Advertisement Protocol IE */ +#define ELEM_MAX_LEN_ADV_PROTOCOL (4 - ELEM_HDR_LEN) + +/* 802.11u 7.3.2.96 Roaming Consortium IE */ +#define ELEM_MAX_LEN_ROAMING_CONSORTIUM (19 - ELEM_HDR_LEN) + +#define IW_IE_LENGTH_ANO 1 +#define IW_IE_LENGTH_ANO_VENUE 3 +#define IW_IE_LENGTH_ANO_HESSID 7 +#define IW_IE_LENGTH_ANO_VENUE_HESSID 9 + +/* 3 Management frame body components (III): 7.4 Action frame format details. */ +/* 7.4.1 Spectrum Measurement Action frame details */ +#define ACTION_MEASUREMENT_REQ 0 /* Spectrum measurement request */ +#define ACTION_MEASUREMENT_REPORT 1 /* Spectrum measurement report */ +#define ACTION_TPC_REQ 2 /* TPC request */ +#define ACTION_TPC_REPORT 3 /* TPC report */ +#define ACTION_CHNL_SWITCH 4 /* Channel Switch Announcement */ + +/* 7.4.2 QoS Action frame details */ +#define ACTION_ADDTS_REQ 0 /* ADDTS request */ +#define ACTION_ADDTS_RSP 1 /* ADDTS response */ +#define ACTION_DELTS 2 /* DELTS */ +#define ACTION_SCHEDULE 3 /* Schedule */ + +#define ACTION_ADDTS_REQ_FRAME_LEN (24+3+63) /* WMM TSPEC IE: 63 */ +#define ACTION_ADDTS_RSP_FRAME_LEN (24+4+63) /* WMM Status Code: 1; WMM TSPEC IE: 63 */ + +/* 7.4.3 DLS Action frame details */ +#define ACTION_DLS_REQ 0 /* DLS request */ +#define ACTION_DLS_RSP 1 /* DLS response */ +#define ACTION_DLS_TEARDOWN 2 /* DLS teardown */ + +/* 7.4.4 Block ack Action frame details */ +#define ACTION_ADDBA_REQ 0 /* ADDBA request */ +#define ACTION_ADDBA_RSP 1 /* ADDBA response */ +#define ACTION_DELBA 2 /* DELBA */ + +#define ACTION_ADDBA_REQ_FRAME_LEN (24+9) +#define ACTION_ADDBA_RSP_FRAME_LEN (24+9) + +#define ACTION_DELBA_INITIATOR_MASK BIT(11) +#define ACTION_DELBA_TID_MASK BITS(12, 15) +#define ACTION_DELBA_TID_OFFSET 12 +#define ACTION_DELBA_FRAME_LEN (24+6) + +/* 7.4.6 Radio Measurement Action frame details */ +#define ACTION_RM_REQ 0 /* Radio measurement request */ +#define ACTION_RM_REPORT 1 /* Radio measurement report */ +#define ACTION_LM_REQ 2 /* Link measurement request */ +#define ACTION_LM_REPORT 3 /* Link measurement report */ +#define ACTION_NEIGHBOR_REPORT_REQ 4 /* Neighbor report request */ +#define ACTION_NEIGHBOR_REPORT_RSP 5 /* Neighbor report response */ + +/* 7.4.7 Public Action frame details */ +#define ACTION_PUBLIC_20_40_COEXIST 0 /* 20/40 BSS coexistence */ + +#if CFG_SUPPORT_802_11W +/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ +#define ACTION_SA_QUERY_REQUEST 0 +#define ACTION_SA_QUERY_RESPONSE 1 + +#define ACTION_SA_QUERY_TR_ID_LEN 2 + +/* Timeout Interval Type */ +#define ACTION_SA_TIMEOUT_REASSOC_DEADLINE 1 +#define ACTION_SA_TIMEOUT_KEY_LIFETIME 2 +#define ACTION_SA_TIMEOUT_ASSOC_COMEBACK 3 +#endif + +/* 7.4.10.1 HT action frame details */ +#define ACTION_HT_NOTIFY_CHANNEL_WIDTH 0 /* Notify Channel Width */ +#define ACTION_HT_SM_POWER_SAVE 1 /* SM Power Save */ +#define ACTION_HT_PSMP 2 /* PSMP */ +#define ACTION_HT_SET_PCO_PHASE 3 /* Set PCO Phase */ +#define ACTION_HT_CSI 4 /* CSI */ +#define ACTION_HT_NON_COMPRESSED_BEAMFORM 5 /* Non-compressed Beamforming */ +#define ACTION_HT_COMPRESSED_BEAMFORM 6 /* Compressed Beamforming */ +#define ACTION_HT_ANT_SEL_INDICES_FB 7 /* Antenna Selection Indices Feedback */ + +/* 802.11v Wireless Network Management */ +#define ACTION_WNM_TIMING_MEASUREMENT_REQUEST 27 + +#define ACTION_UNPROTECTED_WNM_TIM 0 +#define ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT 1 + +#define ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN 12 + +/* 3 --------------- WFA frame body fields --------------- */ +#define VENDOR_OUI_WFA { 0x00, 0x50, 0xF2 } +#define VENDOR_OUI_WFA_SPECIFIC { 0x50, 0x6F, 0x9A } +#define VENDOR_OUI_TYPE_WPA 1 +#define VENDOR_OUI_TYPE_WMM 2 +#define VENDOR_OUI_TYPE_WPS 4 +#define VENDOR_OUI_TYPE_P2P 9 +#define VENDOR_OUI_TYPE_WFD 10 +#define VENDOR_OUI_TYPE_HS20 16 + +#define VENDOR_OUI_TYPE_LEN 4 /* Length of OUI and Type */ + +/* VERSION(2 octets for WPA) / SUBTYPE(1 octet)-VERSION(1 octet) fields for WMM in WFA IE */ +#define VERSION_WPA 0x0001 /* Little Endian Format */ +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_INFO 0x0100 +#define VENDOR_OUI_SUBTYPE_VERSION_WMM_PARAM 0x0101 + +/* SUBTYPE(1 octet) for WMM */ +#define VENDOR_OUI_SUBTYPE_WMM_INFO 0x00 /* WMM Spec version 1.1 */ +#define VENDOR_OUI_SUBTYPE_WMM_PARAM 0x01 +#define VENDOR_OUI_SUBTYPE_WMM_TSPEC 0x02 + +/* VERSION(1 octet) for WMM */ +#define VERSION_WMM 0x01 /* WMM Spec version 1.1 */ + +/* WMM-2.1.6 QoS Control Field */ +#define WMM_QC_UP_MASK BITS(0, 2) +#define WMM_QC_EOSP BIT(4) +#define WMM_QC_ACK_POLICY_MASK BITS(5, 6) +#define WMM_QC_ACK_POLICY_OFFSET 5 +#define WMM_QC_ACK_POLICY_ACKNOWLEDGE 0 +#define WMM_QC_ACK_POLICY_NOT_ACKNOWLEDGE (1 << WMM_QC_ACK_POLICY_OFFSET) + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE 6 + +/* HOTSPOT 2.0 Indication IE*/ +#define ELEM_MAX_LEN_HS20_INDICATION 5 +#define ELEM_MIN_LEN_HS20_INDICATION 4 + +/* Hotspot Configuration*/ +#define ELEM_HS_CONFIG_DGAF_DISABLED_MASK BIT(0) /* Downstream Group-Addressed Forwarding */ + +/* 3 Control frame body */ +/* 7.2.1.7 BlockAckReq */ +#define CTRL_BAR_BAR_CONTROL_OFFSET 16 +#define CTRL_BAR_BAR_INFORMATION_OFFSET 18 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack(1) +#endif + +typedef struct _LLC_SNAP_HEADER_T { + UINT_8 ucDSAP; + UINT_8 ucSSAP; + UINT_8 ucControl; + UINT_8 aucCode[3]; + UINT_16 u2Type; +} __KAL_ATTRIB_PACKED__ LLC_SNAP_HEADER_T, *P_LLC_SNAP_HEADER_T; + +/* 3 MAC Header. */ +/* Ethernet Frame Header */ +typedef struct _ETH_FRAME_HEADER_T { + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_16 u2TypeLen; +} __KAL_ATTRIB_PACKED__ ETH_FRAME_HEADER_T, *P_ETH_FRAME_HEADER_T; + +/* Ethernet Frame Structure */ +typedef struct _ETH_FRAME_T { + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_16 u2TypeLen; + UINT_8 aucData[1]; +} __KAL_ATTRIB_PACKED__ ETH_FRAME_T, *P_ETH_FRAME_T; + +/* IEEE 802.11 WLAN Frame Structure */ +/* WLAN MAC Header (without Address 4 and QoS Control fields) */ +typedef struct _WLAN_MAC_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_T, *P_WLAN_MAC_HEADER_T; + +/* WLAN MAC Header (QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_QOS_T, *P_WLAN_MAC_HEADER_QOS_T; + +/* WLAN MAC Header (HT Control fields included) */ +typedef struct _WLAN_MAC_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_HT_T, *P_WLAN_MAC_HEADER_HT_T; + +/* WLAN MAC Header (Address 4 included) */ +typedef struct _WLAN_MAC_HEADER_A4_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_T, *P_WLAN_MAC_HEADER_A4_T; + +/* WLAN MAC Header (Address 4 and QoS Control fields included) */ +typedef struct _WLAN_MAC_HEADER_A4_QOS_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_QOS_T, *P_WLAN_MAC_HEADER_A4_QOS_T; + +typedef struct _WLAN_MAC_HEADER_A4_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_8 aucAddr4[MAC_ADDR_LEN]; + UINT_16 u2QosCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_HEADER_A4_HT_T, *P_WLAN_MAC_HEADER_A4_HT_T; + +/* 7.2.3 WLAN MAC Header for Management Frame - MMPDU */ +typedef struct _WLAN_MAC_MGMT_HEADER_T { + UINT_16 u2FrameCtrl; + UINT_16 u2Duration; + UINT_8 aucDestAddr[MAC_ADDR_LEN]; + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_T, *P_WLAN_MAC_MGMT_HEADER_T; + +/* WLAN MAC Header for Management Frame (HT Control fields included) */ +typedef struct _WLAN_MAC_MGMT_HEADER_HT_T { + UINT_16 u2FrameCtrl; + UINT_16 u2DurationID; + UINT_8 aucAddr1[MAC_ADDR_LEN]; + UINT_8 aucAddr2[MAC_ADDR_LEN]; + UINT_8 aucAddr3[MAC_ADDR_LEN]; + UINT_16 u2SeqCtrl; + UINT_32 u4HtCtrl; +} __KAL_ATTRIB_PACKED__ WLAN_MAC_MGMT_HEADER_HT_T, *P_WLAN_MAC_MGMT_HEADER_HT_T; + +/* 3 WLAN CONTROL Frame */ +/* 7.2.1.4 WLAN Control Frame - PS-POLL Frame */ +typedef struct _CTRL_PSPOLL_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2AID; /* AID */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_8 aucTA[MAC_ADDR_LEN]; /* TA */ +} __KAL_ATTRIB_PACKED__ CTRL_PSPOLL_FRAME_T, *P_CTRL_PSPOLL_FRAME_T; + +/* BAR */ +typedef struct _CTRL_BAR_FRAME_T { + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* RA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* TA */ + UINT_16 u2BarControl; + UINT_8 aucBarInfo[2]; /* Variable size */ +} __KAL_ATTRIB_PACKED__ CTRL_BAR_FRAME_T, *P_CTRL_BAR_FRAME_T; + +/* 3 WLAN Management Frame. */ +/* 7.2.3.1 WLAN Management Frame - Beacon Frame */ +typedef struct _WLAN_BEACON_FRAME_T { + /* Beacon header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_T, *P_WLAN_BEACON_FRAME_T; + +typedef struct _WLAN_BEACON_FRAME_BODY_T { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[1]; /* Various IEs, start from SSID */ +} __KAL_ATTRIB_PACKED__ WLAN_BEACON_FRAME_BODY_T, *P_WLAN_BEACON_FRAME_BODY_T; + +/* 7.2.3.3 WLAN Management Frame - Disassociation Frame */ +typedef struct _WLAN_DISASSOC_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Disassociation frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DISASSOC_FRAME_T, *P_WLAN_DISASSOC_FRAME_T; + +/* 7.2.3.4 WLAN Management Frame - Association Request frame */ +typedef struct _WLAN_ASSOC_REQ_FRAME_T { + /* Association Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_REQ_FRAME_T, *P_WLAN_ASSOC_REQ_FRAME_T; + +/* 7.2.3.5 WLAN Management Frame - Association Response frame */ +typedef struct _WLAN_ASSOC_RSP_FRAME_T { + /* Association Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Association Response frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2StatusCode; /* Status code */ + UINT_16 u2AssocId; /* Association ID */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + supported rates, and etc. */ +} __KAL_ATTRIB_PACKED__ WLAN_ASSOC_RSP_FRAME_T, *P_WLAN_ASSOC_RSP_FRAME_T; + +/* 7.2.3.6 WLAN Management Frame - Reassociation Request frame */ +typedef struct _WLAN_REASSOC_REQ_FRAME_T { + /* Reassociation Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Reassociation Request frame body */ + UINT_16 u2CapInfo; /* Capability information */ + UINT_16 u2ListenInterval; /* Listen interval */ + UINT_8 aucCurrentAPAddr[MAC_ADDR_LEN]; /* Current AP address */ + UINT_8 aucInfoElem[1]; /* Information elements, include WPA IE */ +} __KAL_ATTRIB_PACKED__ WLAN_REASSOC_REQ_FRAME_T, *P_WLAN_REASSOC_REQ_FRAME_T; + +/* 7.2.3.7 WLAN Management Frame - Reassociation Response frame + (the same as Association Response frame) */ +typedef WLAN_ASSOC_RSP_FRAME_T WLAN_REASSOC_RSP_FRAME_T, *P_WLAN_REASSOC_RSP_FRAME_T; + +/* 7.2.3.9 WLAN Management Frame - Probe Response Frame */ +typedef WLAN_BEACON_FRAME_T WLAN_PROBE_RSP_FRAME_T, *P_WLAN_PROBE_RSP_FRAME_T; + +/* 7.2.3.10 WLAN Management Frame - Authentication Frame */ +typedef struct _WLAN_AUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Authentication frame body */ + UINT_16 u2AuthAlgNum; /* Authentication algorithm number */ + UINT_16 u2AuthTransSeqNo; /* Authentication transaction sequence number */ + UINT_16 u2StatusCode; /* Status code */ + UINT_8 aucInfoElem[1]; /* Various IEs for Fast BSS Transition */ +} __KAL_ATTRIB_PACKED__ WLAN_AUTH_FRAME_T, *P_WLAN_AUTH_FRAME_T; + +/* 7.2.3.11 WLAN Management Frame - Deauthentication Frame */ +typedef struct _WLAN_DEAUTH_FRAME_T { + /* Authentication MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Deauthentication frame body */ + UINT_16 u2ReasonCode; /* Reason code */ + UINT_8 aucInfoElem[1]; /* Various IEs, possible no. */ +} __KAL_ATTRIB_PACKED__ WLAN_DEAUTH_FRAME_T, *P_WLAN_DEAUTH_FRAME_T; + +/* 3 Information Elements. */ +/* 7.3.2 Generic element format */ +typedef struct _IE_HDR_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucInfo[1]; +} __KAL_ATTRIB_PACKED__ IE_HDR_T, *P_IE_HDR_T; + +/* 7.3.2.1 SSID element */ +typedef struct _IE_SSID_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; +} __KAL_ATTRIB_PACKED__ IE_SSID_T, *P_IE_SSID_T; + +/* 7.3.2.2 Supported Rates element */ +typedef struct _IE_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucSupportedRates[ELEM_MAX_LEN_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_RATE_T, *P_IE_SUPPORTED_RATE_T; + +/* 7.3.2.4 DS Parameter Set element */ +typedef struct _IE_DS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCurrChnl; +} __KAL_ATTRIB_PACKED__ IE_DS_PARAM_SET_T, *P_IE_DS_PARAM_SET_T; + +/* 7.3.2.5 CF Parameter Set element */ +typedef struct _IE_CF_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCFPCount; + UINT_8 ucCFPPeriod; + UINT_16 u2CFPMaxDur; + UINT_16 u2DurRemaining; +} __KAL_ATTRIB_PACKED__ IE_CF_PARAM_SET_T, *P_IE_CF_PARAM_SET_T; + +/* 7.3.2.6 TIM */ +typedef struct _IE_TIM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucDTIMCount; + UINT_8 ucDTIMPeriod; + UINT_8 ucBitmapControl; + UINT_8 aucPartialVirtualMap[1]; +} __KAL_ATTRIB_PACKED__ IE_TIM_T, *P_IE_TIM_T; + +/* 7.3.2.7 IBSS Parameter Set element */ +typedef struct _IE_IBSS_PARAM_SET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ATIMWindow; +} __KAL_ATTRIB_PACKED__ IE_IBSS_PARAM_SET_T, *P_IE_IBSS_PARAM_SET_T; + +/* 7.3.2.8 Challenge Text element */ +typedef struct _IE_CHALLENGE_TEXT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucChallengeText[ELEM_MAX_LEN_CHALLENGE_TEXT]; +} __KAL_ATTRIB_PACKED__ IE_CHALLENGE_TEXT_T, *P_IE_CHALLENGE_TEXT_T; + +/* 7.3.2.9 Country information element */ +#if CFG_SUPPORT_802_11D +/*! \brief COUNTRY_INFO_TRIPLET is defined for the COUNTRY_INFO_ELEM structure. */ +typedef struct _COUNTRY_INFO_TRIPLET_T { + UINT_8 ucParam1; /*!< If param1 >= 201, this triplet is referred to as + Regulatory Triplet in 802_11J. */ + UINT_8 ucParam2; + UINT_8 ucParam3; +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_TRIPLET_T, *P_COUNTRY_INFO_TRIPLET_T; + +typedef struct _COUNTRY_INFO_SUBBAND_TRIPLET_T { + UINT_8 ucFirstChnlNum; /*!< First Channel Number */ + UINT_8 ucNumOfChnl; /*!< Number of Channels */ + INT_8 cMaxTxPwrLv; /*!< Maximum Transmit Power Level */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_SUBBAND_TRIPLET_T, *P_COUNTRY_INFO_SUBBAND_TRIPLET_T; + +typedef struct _COUNTRY_INFO_REGULATORY_TRIPLET_T { + UINT_8 ucRegExtId; /*!< Regulatory Extension Identifier, should + be greater than or equal to 201 */ + UINT_8 ucRegClass; /*!< Regulatory Class */ + UINT_8 ucCoverageClass; /*!< Coverage Class, unsigned 1-octet value 0~31 + , 32~255 reserved */ +} __KAL_ATTRIB_PACKED__ COUNTRY_INFO_REGULATORY_TRIPLET_T, *P_COUNTRY_INFO_REGULATORY_TRIPLET_T; + +typedef struct _IE_COUNTRY_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCountryStr[3]; + COUNTRY_INFO_SUBBAND_TRIPLET_T arCountryStr[1]; +} __KAL_ATTRIB_PACKED__ IE_COUNTRY_T, *P_IE_COUNTRY_T; +#endif /* CFG_SUPPORT_802_11D */ + +/* 7.3.2.13 ERP element */ +typedef struct _IE_ERP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucERP; +} __KAL_ATTRIB_PACKED__ IE_ERP_T, *P_IE_ERP_T; + +/* 7.3.2.14 Extended Supported Rates element */ +typedef struct _IE_EXT_SUPPORTED_RATE_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucExtSupportedRates[ELEM_MAX_LEN_EXTENDED_SUP_RATES]; +} __KAL_ATTRIB_PACKED__ IE_EXT_SUPPORTED_RATE_T, *P_IE_EXT_SUPPORTED_RATE_T; + +/* 7.3.2.15 Power Constraint element */ +typedef struct _IE_POWER_CONSTRAINT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucLocalPowerConstraint; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CONSTRAINT_T, *P_IE_POWER_CONSTRAINT_T; + +/* 7.3.2.16 Power Capability element */ +typedef struct _IE_POWER_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cMinTxPowerCap; /* Unit: dBm */ + INT_8 cMaxTxPowerCap; /* Unit: dBm */ +} __KAL_ATTRIB_PACKED__ IE_POWER_CAP_T, *P_IE_POWER_CAP_T; + +/* 7.3.2.17 TPC request element */ +typedef struct _IE_TPC_REQ_T { + UINT_8 ucId; + UINT_8 ucLength; +} __KAL_ATTRIB_PACKED__ IE_TPC_REQ_T, *P_IE_TPC_REQ_T; + +/* 7.3.2.18 TPC report element */ +typedef struct _IE_TPC_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + INT_8 cTxPower; /* Unit: dBm */ + INT_8 cLinkMargin; /* Unit: dB */ +} __KAL_ATTRIB_PACKED__ IE_TPC_REPORT_T, *P_IE_TPC_REPORT_T; + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +/* 7.3.2.19 Supported Channels element*/ +typedef struct _IE_SUPPORTED_CHANNELS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelNum[ELEM_MAX_LEN_SUPPORTED_CHANNELS * 2]; +} __KAL_ATTRIB_PACKED__ IE_SUPPORTED_CHANNELS_T, *P_IE_SUPPORTED_CHANNELS_T; + +/* 7.3.2.20 Channel Switch Announcement element*/ +typedef struct _IE_CHANNEL_SWITCH_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucChannelSwitchMode; + UINT_8 ucNewChannelNum; + UINT_8 ucChannelSwitchCount; +} __KAL_ATTRIB_PACKED__ IE_CHANNEL_SWITCH_T, *P_IE_CHANNEL_SWITCH_T; +#endif + +/* 7.3.2.21 Measurement Request element */ +typedef struct _IE_MEASUREMENT_REQ_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucToken; + UINT_8 ucRequestMode; + UINT_8 ucMeasurementType; + UINT_8 aucRequestFields[1]; +} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REQ_T, *P_IE_MEASUREMENT_REQ_T; + +typedef struct _SM_BASIC_REQ_T { + UINT_8 ucChannel; + UINT_32 au4StartTime[2]; + UINT_16 u2Duration; +} __KAL_ATTRIB_PACKED__ SM_BASIC_REQ_T, *P_SM_BASIC_REQ_T; + +/* SM_COMMON_REQ_T is not specified in Spec. Use it as common structure of SM */ +typedef SM_BASIC_REQ_T SM_REQ_COMMON_T, *P_SM_REQ_COMMON_T; +typedef SM_BASIC_REQ_T SM_CCA_REQ_T, *P_SM_CCA_REQ_T; +typedef SM_BASIC_REQ_T SM_RPI_HISTOGRAM_REQ_T, *P_SM_RPI_HISTOGRAM_REQ_T; + +typedef struct _RM_CHNL_LOAD_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REQ_T, *P_RM_CHNL_LOAD_REQ_T; + +typedef RM_CHNL_LOAD_REQ_T RM_NOISE_HISTOGRAM_REQ_T, *P_RM_NOISE_HISTOGRAM_REQ_T; + +typedef struct _RM_BCN_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucMeasurementMode; + UINT_8 aucBssid[6]; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_BCN_REQ_T, *P_RM_BCN_REQ_T; + +typedef struct _RM_FRAME_REQ_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucFrameReqType; + UINT_8 aucMacAddr[6]; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_FRAME_REQ_T, *P_RM_FRAME_REQ_T; + +typedef struct _RM_STA_STATS_REQ_T { + UINT_8 aucPeerMacAddr[6]; + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 ucGroupID; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_STA_STATS_REQ_T, *P_RM_STA_STATS_REQ_T; + +typedef struct _RM_LCI_REQ_T { + UINT_8 ucLocationSubject; + UINT_8 ucLatitudeResolution; + UINT_8 ucLongitudeResolution; + UINT_8 ucAltitudeResolution; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_LCI_REQ_T, *P_RM_LCI_REQ_T; + +typedef struct _RM_TS_MEASURE_REQ_T { + UINT_16 u2RandomInterval; + UINT_16 u2Duration; + UINT_8 aucPeerStaAddr[6]; + UINT_8 ucTrafficID; + UINT_8 ucBin0Range; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_TS_MEASURE_REQ_T, *P_RM_TS_MEASURE_REQ_T; + +typedef struct _RM_MEASURE_PAUSE_REQ_T { + UINT_16 u2PauseTime; + UINT_8 aucSubElements[1]; +} __KAL_ATTRIB_PACKED__ RM_MEASURE_PAUSE_REQ_T, *P_RM_MEASURE_PAUSE_REQ_T; + +/* 7.3.2.22 Measurement Report element */ +typedef struct _IE_MEASUREMENT_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucToken; + UINT_8 ucReportMode; + UINT_8 ucMeasurementType; + UINT_8 aucReportFields[1]; +} __KAL_ATTRIB_PACKED__ IE_MEASUREMENT_REPORT_T, *P_IE_MEASUREMENT_REPORT_T; + +typedef struct _SM_BASIC_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucMap; +} __KAL_ATTRIB_PACKED__ SM_BASIC_REPORT_T, *P_SM_BASIC_REPORT_T; + +typedef struct _SM_CCA_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucCcaBusyFraction; +} __KAL_ATTRIB_PACKED__ SM_CCA_REPORT_T, *P_SM_CCA_REPORT_T; + +typedef struct _SM_RPI_REPORT_T { + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 aucRPI[8]; +} __KAL_ATTRIB_PACKED__ SM_RPI_REPORT_T, *P_SM_RPI_REPORT_T; + +typedef struct _RM_CHNL_LOAD_REPORT_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucChnlLoad; +} __KAL_ATTRIB_PACKED__ RM_CHNL_LOAD_REPORT_T, *P_RM_CHNL_LOAD_REPORT_T; + +typedef struct _RM_IPI_REPORT_T { + UINT_8 ucRegulatoryClass; + UINT_8 ucChannel; + UINT_32 u4StartTime[2]; + UINT_16 u2Duration; + UINT_8 ucAntennaId; + INT_8 cANPI; + UINT_8 aucIPI[11]; +} __KAL_ATTRIB_PACKED__ RM_IPI_REPORT_T, *P_RM_IPI_REPORT_T; + +/* 7.3.2.23 Quiet element */ +typedef struct _IE_QUIET_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCount; + UINT_8 ucPeriod; + UINT_16 u2Duration; + UINT_16 u2Offset; +} __KAL_ATTRIB_PACKED__ IE_QUIET_T, *P_IE_QUIET_T; + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_EXT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCapabilities[5]; +} __KAL_ATTRIB_PACKED__ IE_EXT_CAP_T, *P_EXT_CAP_T; + +/* 7.3.2.27 hs20 Extended Capabilities element */ +typedef struct _IE_HS20_EXT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCapabilities[6]; +} __KAL_ATTRIB_PACKED__ IE_HS20_EXT_CAP_T, *P_HS20_EXT_CAP_T; + + +/* 7.3.2.27 Extended Capabilities element */ +typedef struct _IE_RRM_ENABLED_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucCap[5]; +} __KAL_ATTRIB_PACKED__ IE_RRM_ENABLED_CAP_T, *P_IE_RRM_ENABLED_CAP_T; + +/* 7.3.2.51 Timeout Interval element (TIE) */ +typedef struct _IE_TIMEOUT_INTERVAL_T { + UINT_8 ucId; + UINT_8 ucLength; +#define IE_TIMEOUT_INTERVAL_TYPE_RESERVED 0 +#define IE_TIMEOUT_INTERVAL_TYPE_REASSOC 1 +#define IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME 2 +#define IE_TIMEOUT_INTERVAL_TYPE_ASSOC_COMEBACK 3 + UINT_8 ucType; + UINT_32 u4Value; +} __KAL_ATTRIB_PACKED__ IE_TIMEOUT_INTERVAL_T; + +/* 7.3.2.56 HT Capabilities element */ +typedef struct _SUP_MCS_SET_FIELD { + UINT_8 aucRxMcsBitmask[SUP_MCS_RX_BITMASK_OCTET_NUM]; + UINT_16 u2RxHighestSupportedRate; + UINT_32 u4TxRateInfo; +} __KAL_ATTRIB_PACKED__ SUP_MCS_SET_FIELD, *P_SUP_MCS_SET_FIELD; + +typedef struct _IE_HT_CAP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2HtCapInfo; + UINT_8 ucAmpduParam; + SUP_MCS_SET_FIELD rSupMcsSet; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; +} __KAL_ATTRIB_PACKED__ IE_HT_CAP_T, *P_IE_HT_CAP_T; + +/* 7.3.2.57 HT Operation element */ +typedef struct _IE_HT_OP_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucPrimaryChannel; + UINT_8 ucInfo1; + UINT_16 u2Info2; + UINT_16 u2Info3; + UINT_8 aucBasicMcsSet[16]; +} __KAL_ATTRIB_PACKED__ IE_HT_OP_T, *P_IE_HT_OP_T; + +/* 7.3.2.25 RSN Information element format */ +typedef struct _RSN_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ RSN_INFO_ELEM_T, *P_RSN_INFO_ELEM_T; + +/* 7.3.2.26 WPA Information element format */ +typedef struct _WPA_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UCHAR aucOui[3]; + UCHAR ucOuiType; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2PairwiseKeyCipherSuiteCount; + UCHAR aucPairwiseKeyCipherSuite1[4]; +} __KAL_ATTRIB_PACKED__ WPA_INFO_ELEM_T, *P_WPA_INFO_ELEM_T; + +/* 7.3.2.58 20/40 BSS Intolerant Channel Report element */ +typedef struct _IE_INTOLERANT_CHNL_REPORT_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucRegulatoryClass; + UINT_8 aucChannelList[1]; +} __KAL_ATTRIB_PACKED__ IE_INTOLERANT_CHNL_REPORT_T, *P_IE_INTOLERANT_CHNL_REPORT_T; + +/* 7.3.2.59 OBSS Scan Parameters element */ +typedef struct _IE_OBSS_SCAN_PARAM_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_16 u2ScanPassiveDwell; + UINT_16 u2ScanActiveDwell; + UINT_16 u2TriggerScanInterval; + UINT_16 u2ScanPassiveTotalPerChnl; + UINT_16 u2ScanActiveTotalPerChnl; + UINT_16 u2WidthTransDelayFactor; + UINT_16 u2ScanActivityThres; +} __KAL_ATTRIB_PACKED__ IE_OBSS_SCAN_PARAM_T, *P_IE_OBSS_SCAN_PARAM_T; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_20_40_COEXIST_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucData; +} __KAL_ATTRIB_PACKED__ IE_20_40_COEXIST_T, *P_IE_20_40_COEXIST_T; + +/* 7.3.2.60 20/40 BSS Coexistence element */ +typedef struct _IE_SUP_OPERATING_CLASS_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 ucCur; + UINT_8 ucSup[255]; +} __KAL_ATTRIB_PACKED__ IE_SUP_OPERATING_CLASS_T, *P_IE_SUP_OPERATING_CLASS_T; + +/* 3 7.4 Action Frame. */ +/* 7.4 Action frame format */ +typedef struct _WLAN_ACTION_FRAME { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucActionDetails[1]; /* Action details */ +} __KAL_ATTRIB_PACKED__ WLAN_ACTION_FRAME, *P_WLAN_ACTION_FRAME; + +/* 7.4.1.1 Spectrum Measurement Request frame format */ +typedef struct _ACTION_SM_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ ACTION_SM_REQ_FRAME, *P_ACTION_SM_REQ_FRAME; + +/* 7.4.1.2 Spectrum Measurement Report frame format */ +typedef ACTION_SM_REQ_FRAME ACTION_SM_REPORT_FRAME, *P_ACTION_SM_REPORT_FRAME; + +/* 7.4.1.5 Channel Switch Announcement frame format */ +typedef struct _ACTION_CHANNEL_SWITCH_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucInfoElem[5]; /* Information elements */ +} __KAL_ATTRIB_PACKED__ _ACTION_CHANNEL_SWITCH_FRAME, *P_ACTION_CHANNEL_SWITCH_FRAME; + +/* 7.4.2.1 ADDTS Request frame format */ +typedef struct _ACTION_ADDTS_REQ_FRAME { + /* ADDTS Request MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_REQ_FRAME, *P_ACTION_ADDTS_REQ_FRAME; + +/* 7.4.2.2 ADDTS Response frame format */ +typedef struct _ACTION_ADDTS_RSP_FRAME { + /* ADDTS Response MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* ADDTS Response frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucStatusCode; /* WMM Status Code is of one byte */ + UINT_8 aucInfoElem[1]; /* Information elements, such as + TS Delay, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDTS_RSP_FRAME, *P_ACTION_ADDTS_RSP_FRAME; + +/* 7.4.2.3 DELTS frame format */ +typedef struct _ACTION_DELTS_FRAME { + /* DELTS MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* DELTS frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 aucTsInfo[3]; /* TS Info */ +} __KAL_ATTRIB_PACKED__ ACTION_DELTS_FRAME, *P_ACTION_DELTS_FRAME; + +/* 7.4.4.1 ADDBA Request frame format */ +typedef struct _ACTION_ADDBA_REQ_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; + UINT_8 aucBAStartSeqCtrl[2]; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_FRAME_T, *P_ACTION_ADDBA_REQ_FRAME_T; + +typedef struct _ACTION_ADDBA_REQ_BODY_T { + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_REQ_BODY_T, *P_ACTION_ADDBA_REQ_BODY_T; + +/* 7.4.4.2 ADDBA Response frame format */ +typedef struct _ACTION_ADDBA_RSP_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_8 aucStatusCode[2]; + UINT_8 aucBAParameterSet[2]; /* BA policy, TID, buffer size */ + UINT_8 aucBATimeoutValue[2]; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_FRAME_T, *P_ACTION_ADDBA_RSP_FRAME_T; + +typedef struct _ACTION_ADDBA_RSP_BODY_T { + UINT_16 u2StatusCode; + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; +} __KAL_ATTRIB_PACKED__ ACTION_ADDBA_RSP_BODY_T, *P_ACTION_ADDBA_RSP_BODY_T; + +/* 7.4.4.3 DELBA frame format */ +typedef struct _ACTION_DELBA_FRAME_T { + /* Action MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2DurationID; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Action frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_16 u2DelBaParameterSet; /* Bit 11 Initiator, Bits 12-15 TID */ + UINT_16 u2ReasonCode; /* 7.3.1.7 */ +} __KAL_ATTRIB_PACKED__ ACTION_DELBA_FRAME_T, *P_ACTION_DELBA_FRAME_T; + +/* 7.4.6.1 Radio Measurement Request frame format */ +typedef struct _ACTION_RM_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Request frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_16 u2Repetitions; /* Number of repetitions */ + UINT_8 aucInfoElem[1]; /* Measurement Request elements, such as + channel load request, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REQ_FRAME, *P_ACTION_RM_REQ_FRAME; + +/* 7.4.6.2 Radio Measurement Report frame format */ +typedef struct _ACTION_RM_REPORT_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Radio Measurement Report frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 aucInfoElem[1]; /* Measurement Report elements, such as + channel load report, and etc. */ +} __KAL_ATTRIB_PACKED__ ACTION_RM_REPORT_FRAME, *P_ACTION_RM_REPORT_FRAME; + +/* 7.4.7.1a 20/40 BSS Coexistence Management frame format */ +typedef struct _ACTION_20_40_COEXIST_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + IE_20_40_COEXIST_T rBssCoexist; /* 20/40 BSS coexistence element */ + IE_INTOLERANT_CHNL_REPORT_T rChnlReport; /* Intolerant channel report */ + +} __KAL_ATTRIB_PACKED__ ACTION_20_40_COEXIST_FRAME, *P_ACTION_20_40_COEXIST_FRAME; + +#if CFG_SUPPORT_802_11W +/* 7.4.9 SA Query Management frame format */ +typedef struct _ACTION_SA_QUERY_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; /* Transaction id */ + +} __KAL_ATTRIB_PACKED__ ACTION_SA_QUERY_FRAME, *P_ACTION_SA_QUERY_FRAME; +#endif + +/* 7.4.10 Notify Channel Width Management frame format */ +typedef struct _ACTION_NOTIFY_CHNL_WIDTH_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* BSS Coexistence Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucChannelWidth; /* Channel Width */ +} __KAL_ATTRIB_PACKED__ ACTION_NOTIFY_CHNL_WIDTH_FRAME, *P_ACTION_NOTIFY_CHNL_WIDTH_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement Request */ +typedef struct _ACTION_WNM_TIMING_MEAS_REQ_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Request Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucTrigger; /* Trigger */ +} __KAL_ATTRIB_PACKED__ ACTION_WNM_TIMING_MEAS_REQ_FRAME, *P_ACTION_WNM_TIMING_MEAS_REQ_FRAME; + +/* 802.11v Wireless Network Management: Timing Measurement */ +typedef struct _ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* Timing Measurement Management frame body */ + UINT_8 ucCategory; /* Category */ + UINT_8 ucAction; /* Action Value */ + UINT_8 ucDialogToken; /* Dialog Token */ + UINT_8 ucFollowUpDialogToken; /* Follow Up Dialog Token */ + UINT_32 u4ToD; /* Timestamp of Departure [10ns] */ + UINT_32 u4ToA; /* Timestamp of Arrival [10ns] */ + UINT_8 ucMaxToDErr; /* Maximum of ToD Error [10ns] */ + UINT_8 ucMaxToAErr; /* Maximum of ToA Error [10ns] */ +} __KAL_ATTRIB_PACKED__ ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME, *P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME; + +/* 3 Information Elements from WFA. */ +typedef struct _IE_WFA_T { + UINT_8 ucId; + UINT_8 ucLength; + UINT_8 aucOui[3]; + UINT_8 ucOuiType; + UINT_8 aucOuiSubTypeVersion[2]; + /*!< Please be noted. WPA defines a 16 bit field version + instead of one subtype field and one version field */ +} __KAL_ATTRIB_PACKED__ IE_WFA_T, *P_IE_WFA_T; + +/* HS20 3.1 - HS 2.0 Indication Information Element */ +typedef struct _IE_HS20_INDICATION_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucType; /* Type */ + UINT_8 ucHotspotConfig; /* Hotspot Configuration */ +} __KAL_ATTRIB_PACKED__ IE_HS20_INDICATION_T, *P_IE_HS20_INDICATION_T; + +/* WAPI Information element format */ +typedef struct _WAPI_INFO_ELEM_T { + UCHAR ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_16 u2AuthKeyMgtSuiteCount; + UCHAR aucAuthKeyMgtSuite1[4]; +} __KAL_ATTRIB_PACKED__ WAPI_INFO_ELEM_T, *P_WAPI_INFO_ELEM_T; + +#if defined(WINDOWS_DDK) || defined(WINDOWS_CE) +#pragma pack() +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Convert the ECWmin(max) to CWmin(max) */ +#define ECW_TO_CW(_ECW) ((1 << (_ECW)) - 1) + +/* Convert the RCPI to dBm */ +#define RCPI_TO_dBm(_rcpi) \ + ((PARAM_RSSI)(((_rcpi) > RCPI_HIGH_BOUND ? RCPI_HIGH_BOUND : (_rcpi)) >> 1) - NDBM_LOW_BOUND_FOR_RCPI) + +/* Convert the dBm to RCPI */ +#define dBm_TO_RCPI(_dbm) \ + (RCPI)(((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) > RCPI_HIGH_BOUND) ? RCPI_HIGH_BOUND : \ + ((((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1) < RCPI_LOW_BOUND ? RCPI_LOW_BOUND : \ + (((PARAM_RSSI)(_dbm) + NDBM_LOW_BOUND_FOR_RCPI) << 1))) + +/* Convert an unsigned char pointer to an information element pointer */ +#define IE_ID(fp) (((P_IE_HDR_T) fp)->ucId) +#define IE_LEN(fp) (((P_IE_HDR_T) fp)->ucLength) +#define IE_SIZE(fp) (ELEM_HDR_LEN + IE_LEN(fp)) + +#define SSID_IE(fp) ((P_IE_SSID_T) fp) + +#define SUP_RATES_IE(fp) ((P_IE_SUPPORTED_RATE_T) fp) + +#define DS_PARAM_IE(fp) ((P_IE_DS_PARAM_SET_T) fp) + +#define TIM_IE(fp) ((P_IE_TIM_T) fp) + +#define IBSS_PARAM_IE(fp) ((P_IE_IBSS_PARAM_SET_T) fp) + +#define ERP_INFO_IE(fp) ((P_IE_ERP_T) fp) + +#define EXT_SUP_RATES_IE(fp) ((P_IE_EXT_SUPPORTED_RATE_T) fp) + +#define WFA_IE(fp) ((P_IE_WFA_T) fp) + +#if CFG_SUPPORT_802_11D +#define COUNTRY_IE(fp) ((P_IE_COUNTRY_T) fp) +#endif + +#define EXT_CAP_IE(fp) ((P_EXT_CAP_T) fp) + +#define HT_CAP_IE(fp) ((P_IE_HT_CAP_T) fp) + +#define HT_OP_IE(fp) ((P_IE_HT_OP_T) fp) + +#define OBSS_SCAN_PARAM_IE(fp) ((P_IE_OBSS_SCAN_PARAM_T) fp) + +#define BSS_20_40_COEXIST_IE(fp) ((P_IE_20_40_COEXIST_T) fp) + +#define SUP_OPERATING_CLASS_IE(fp) ((P_IE_SUP_OPERATING_CLASS_T) fp) + +#define QUIET_IE(fp) ((P_IE_QUIET_T) fp) + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +#define SUPPORTED_CHANNELS_IE(fp) ((P_IE_SUPPORTED_CHANNELS_T)fp) +#endif + +#define TIMEOUT_INTERVAL_IE(fp) ((IE_TIMEOUT_INTERVAL_T *)fp) + +/* The macro to check if the MAC address is B/MCAST Address */ +#define IS_BMCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) (((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to check if the MAC address is UCAST Address */ +#define IS_UCAST_MAC_ADDR(_pucDestAddr) \ + ((BOOLEAN) !(((PUINT_8)(_pucDestAddr))[0] & BIT(0))) + +/* The macro to copy the MAC address */ +#define COPY_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + kalMemCopy(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN) + +/* The macro to check if two MAC addresses are equal */ +#define EQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (!kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check if two MAC addresses are not equal */ +#define UNEQUAL_MAC_ADDR(_pucDestAddr, _pucSrcAddr) \ + (kalMemCmp(_pucDestAddr, _pucSrcAddr, MAC_ADDR_LEN)) + +/* The macro to check whether two SSIDs are equal */ +#define EQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 <= ELEM_MAX_LEN_SSID) && \ + (ucSsidLen2 <= ELEM_MAX_LEN_SSID) && \ + ((ucSsidLen1) == (ucSsidLen2)) && \ + !kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to check whether two SSIDs are equal */ +#define UNEQUAL_SSID(pucSsid1, ucSsidLen1, pucSsid2, ucSsidLen2) \ + ((ucSsidLen1 > ELEM_MAX_LEN_SSID) || \ + (ucSsidLen2 > ELEM_MAX_LEN_SSID) || \ + ((ucSsidLen1) != (ucSsidLen2)) || \ + kalMemCmp(pucSsid1, pucSsid2, ucSsidLen1)) + +/* The macro to copy the SSID, the length of pucDestSsid should have at least 32 bytes */ +#define COPY_SSID(pucDestSsid, ucDestSsidLen, pucSrcSsid, ucSrcSsidLen) \ + do { \ + ucDestSsidLen = ucSrcSsidLen; \ + if (ucSrcSsidLen) { \ + ASSERT(ucSrcSsidLen <= ELEM_MAX_LEN_SSID); \ + kalMemCopy(pucDestSsid, \ + pucSrcSsid, \ + ((ucSrcSsidLen > ELEM_MAX_LEN_SSID) ? ELEM_MAX_LEN_SSID : ucSrcSsidLen)); \ + } \ + } while (FALSE) + +/* The macro to copy the IE */ +#define COPY_IE(pucDestIE, pucSrcIE) \ + do { \ + kalMemCopy((PUINT_8)pucDestIE, \ + (PUINT_8)pucSrcIE,\ + IE_SIZE(pucSrcIE)); \ + } while (FALSE) + +#define IE_FOR_EACH(_pucIEsBuf, _u2IEsBufLen, _u2Offset) \ + for ((_u2Offset) = 0;\ + ((((_u2Offset) + 2) <= (_u2IEsBufLen)) && (((_u2Offset) + IE_SIZE(_pucIEsBuf)) <= (_u2IEsBufLen))); \ + (_u2Offset) += IE_SIZE(_pucIEsBuf), (_pucIEsBuf) += IE_SIZE(_pucIEsBuf)) + +#define SET_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + do { \ + if ((_ucBit) < ((_ucFieldLength) * 8)) { \ + PUINT_8 aucExtCap = (PUINT_8)(_aucField); \ + ((aucExtCap)[(_ucBit) / 8]) |= BIT((_ucBit) % 8); \ + } \ + } while (FALSE) + +#define TEST_EXT_CAP(_aucField, _ucFieldLength, _ucBit) \ + ((((_ucFieldLength) * 8) > (_ucBit)) && (((_aucField)[(_ucBit) / 8]) & BIT((_ucBit) % 8))) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MAC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h new file mode 100644 index 0000000000000..583923aed0100 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/mtreg.h @@ -0,0 +1,272 @@ +/* +** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/include/nic/mtreg.h#2 +*/ + +/*! \file "mtreg.h" + \brief The common register definition of mt5931 + + N/A +*/ + +/* +** Log: mtreg.h + * + * 01 28 2013 samp.lin + * [WCXRP00000851] [MT6582 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6582-specific definitions. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 07 13 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add initial version for MT6628 driver support. + * +*/ + +#ifndef _MTREG_H +#define _MTREG_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* 1 MT6628 MCR Definition */ + +/* 2 Host Interface */ + +/* 4 CHIP ID Register */ +#define MCR_WCIR 0x0000 + +/* 4 HIF Low Power Control Register */ +#define MCR_WHLPCR 0x0004 + +/* 4 Control Status Register */ +#define MCR_WSDIOCSR 0x0008 +#define MCR_WSPICSR 0x0008 + +/* 4 HIF Control Register */ +#define MCR_WHCR 0x000C + +/* 4 HIF Interrupt Status Register */ +#define MCR_WHISR 0x0010 + +/* 4 HIF Interrupt Enable Register */ +#define MCR_WHIER 0x0014 + +/* 4 Abnormal Status Register */ +#define MCR_WASR 0x0018 + +/* 4 WLAN Software Interrupt Control Register */ +#define MCR_WSICR 0x001C + +/* 4 WLAN TX Status Register */ +#define MCR_WTSR0 0x0020 + +/* 4 WLAN TX Status Register */ +#define MCR_WTSR1 0x0024 + +/* 4 WLAN TX Data Register 0 */ +#define MCR_WTDR0 0x0028 + +/* 4 WLAN TX Data Register 1 */ +#define MCR_WTDR1 0x002C + +/* 4 WLAN RX Data Register 0 */ +#define MCR_WRDR0 0x0030 + +/* 4 WLAN RX Data Register 1 */ +#define MCR_WRDR1 0x0034 + +/* 4 Host to Device Send Mailbox 0 Register */ +#define MCR_H2DSM0R 0x0038 + +/* 4 Host to Device Send Mailbox 1 Register */ +#define MCR_H2DSM1R 0x003c + +/* 4 Device to Host Receive Mailbox 0 Register */ +#define MCR_D2HRM0R 0x0040 + +/* 4 Device to Host Receive Mailbox 1 Register */ +#define MCR_D2HRM1R 0x0044 + +/* 4 Device to Host Receive Mailbox 2 Register */ +#define MCR_D2HRM2R 0x0048 + +/* 4 WLAN RX Packet Length Register */ +#define MCR_WRPLR 0x0050 + +/* 4 HSIF Transaction Count Register */ +#define MCR_HSTCR 0x0058 + +/* #if CFG_SDIO_INTR_ENHANCE */ +typedef struct _ENHANCE_MODE_DATA_STRUCT_T { + UINT_32 u4WHISR; + union { + struct { + UINT_8 ucTQ0Cnt; + UINT_8 ucTQ1Cnt; + UINT_8 ucTQ2Cnt; + UINT_8 ucTQ3Cnt; + UINT_8 ucTQ4Cnt; + UINT_8 ucTQ5Cnt; + UINT_16 u2Rsrv; + } u; + UINT_32 au4WTSR[2]; + } rTxInfo; + union { + struct { + UINT_16 u2NumValidRx0Len; + UINT_16 u2NumValidRx1Len; + UINT_16 au2Rx0Len[16]; + UINT_16 au2Rx1Len[16]; + } u; + UINT_32 au4RxStatusRaw[17]; + } rRxInfo; + UINT_32 u4RcvMailbox0; + UINT_32 u4RcvMailbox1; +} ENHANCE_MODE_DATA_STRUCT_T, *P_ENHANCE_MODE_DATA_STRUCT_T; +/* #endif */ /* ENHANCE_MODE_DATA_STRUCT_T */ + +/* 2 Definition in each register */ +/* 3 WCIR 0x0000 */ +#define WCIR_WLAN_READY BIT(21) +#define WCIR_POR_INDICATOR BIT(20) +#define WCIR_REVISION_ID BITS(16, 19) +#define WCIR_CHIP_ID BITS(0, 15) + +#define MTK_CHIP_REV_72 0x00006572 +#define MTK_CHIP_REV_82 0x00006582 +#define MTK_CHIP_REV_92 0x00006592 +#define MTK_CHIP_MP_REVERSION_ID 0x0 + +/* 3 WHLPCR 0x0004 */ +#define WHLPCR_FW_OWN_REQ_CLR BIT(9) +#define WHLPCR_FW_OWN_REQ_SET BIT(8) +#define WHLPCR_IS_DRIVER_OWN BIT(8) +#define WHLPCR_INT_EN_CLR BIT(1) +#define WHLPCR_INT_EN_SET BIT(0) + +/* 3 WSDIOCSR 0x0008 */ +#define WSDIOCSR_SDIO_RE_INIT_EN BIT(0) + +/* 3 WSPICSR 0x0008 */ +#define WCSR_SPI_MODE_SEL BITS(3, 4) +#define WCSR_SPI_ENDIAN_BIG BIT(2) +#define WCSR_SPI_INT_OUT_MODE BIT(1) +#define WCSR_SPI_DATA_OUT_MODE BIT(0) + +/* 3 WHCR 0x000C */ +#define WHCR_RX_ENHANCE_MODE_EN BIT(16) +#define WHCR_MAX_HIF_RX_LEN_NUM BITS(4, 7) +#define WHCR_W_MAILBOX_RD_CLR_EN BIT(2) +#define WHCR_W_INT_CLR_CTRL BIT(1) +#define WHCR_MCU_DBG_EN BIT(0) +#define WHCR_OFFSET_MAX_HIF_RX_LEN_NUM 4 + +/* 3 WHISR 0x0010 */ +#define WHISR_D2H_SW_INT BITS(8, 31) +#define WHISR_D2H_SW_ASSERT_INFO_INT BIT(31) +#define WHISR_FW_OWN_BACK_INT BIT(4) +#define WHISR_ABNORMAL_INT BIT(3) +#define WHISR_RX1_DONE_INT BIT(2) +#define WHISR_RX0_DONE_INT BIT(1) +#define WHISR_TX_DONE_INT BIT(0) + +/* 3 WHIER 0x0014 */ +#define WHIER_D2H_SW_INT BITS(8, 31) +#define WHIER_FW_OWN_BACK_INT_EN BIT(4) +#define WHIER_ABNORMAL_INT_EN BIT(3) +#define WHIER_RX1_DONE_INT_EN BIT(2) +#define WHIER_RX0_DONE_INT_EN BIT(1) +#define WHIER_TX_DONE_INT_EN BIT(0) +#define WHIER_DEFAULT (WHIER_RX0_DONE_INT_EN | \ + WHIER_RX1_DONE_INT_EN | \ + WHIER_TX_DONE_INT_EN | \ + WHIER_ABNORMAL_INT_EN | \ + WHIER_D2H_SW_INT \ + ) + +/* 3 WASR 0x0018 */ +#define WASR_FW_OWN_INVALID_ACCESS BIT(4) +#define WASR_RX1_UNDER_FLOW BIT(3) +#define WASR_RX0_UNDER_FLOW BIT(2) +#define WASR_TX1_OVER_FLOW BIT(1) +#define WASR_TX0_OVER_FLOW BIT(0) + +/* 3 WSICR 0x001C */ +#define WSICR_H2D_SW_INT_SET BITS(16, 31) + +/* 3 WRPLR 0x0050 */ +#define WRPLR_RX1_PACKET_LENGTH BITS(16, 31) +#define WRPLR_RX0_PACKET_LENGTH BITS(0, 15) + +/* 3 HSTCR 0x0058 */ +#define HSTCR_AFF_BURST_LEN BITS(24, 25) +#define HSTCR_AFF_BURST_LEN_OFFSET 24 +#define HSTCR_TRANS_TARGET BITS(20, 22) +#define HSTCR_TRANS_TARGET_OFFSET 20 +#define HSTCR_HSIF_TRANS_CNT BITS(2, 19) +#define HSTCR_HSIF_TRANS_CNT_OFFSET 2 + +/* HSTCR_TRANS_TARGET */ +typedef enum _eTransTarget { + TRANS_TARGET_TXD0 = 0, + TRANS_TARGET_TXD1, + TRANS_TARGET_RXD0, + TRANS_TARGET_RXD1, + TRANS_TARGET_WHISR, + NUM_TRANS_TARGET +} E_TRANS_TARGET_T; + +typedef enum _E_AFF_BURST_LEN { + BURST_1_DW = 0, + BURST_4_DW, + BURST_8_DW, + BURST_RSV, + NUM_AFF_BURST_LEN +} E_AFF_BURST_LEN; + +#endif /* _MTREG_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h new file mode 100644 index 0000000000000..c059b707aee84 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic.h @@ -0,0 +1,498 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic.h#1 +*/ + +/*! \file "nic.h" + \brief The declaration of nic functions + + Detail description. +*/ + +/* +** Log: nic.h + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS + * cannot do the 4-way handshake to connect to the AP.. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right + * after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] + * Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced + * by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test + * with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always process TX interrupt first then RX interrupt. + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-10-13 21:58:58 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-24 21:12:55 GMT mtk01104 +** Add function prototype nicRestoreSpiDefMode() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-19 18:32:54 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:32 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_H +#define _NIC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct _REG_ENTRY_T { + UINT_32 u4Offset; + UINT_32 u4Value; +}; + +struct _TABLE_ENTRY_T { + P_REG_ENTRY_T pu4TablePtr; + UINT_16 u2Size; +}; + +/*! INT status to event map */ +typedef struct _INT_EVENT_MAP_T { + UINT_32 u4Int; + UINT_32 u4Event; +} INT_EVENT_MAP_T, *P_INT_EVENT_MAP_T; + +enum ENUM_INT_EVENT_T { + INT_EVENT_ABNORMAL, + INT_EVENT_SW_INT, + INT_EVENT_TX, + INT_EVENT_RX, + INT_EVENT_NUM +}; + +typedef enum _ENUM_IE_UPD_METHOD_T { + IE_UPD_METHOD_UPDATE_RANDOM, + IE_UPD_METHOD_UPDATE_ALL, + IE_UPD_METHOD_DELETE_ALL, +} ENUM_IE_UPD_METHOD_T, *P_ENUM_IE_UPD_METHOD_T; + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern BOOLEAN fgIsResetting; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in nic.c */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter); + +VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter); + +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus); + +WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter); + +VOID nicMCRInit(IN P_ADAPTER_T prAdapter); + +BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter); + +#if CFG_SDIO_INTR_ENHANCE +VOID nicSDIOInit(IN P_ADAPTER_T prAdapter); + +VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus); +#endif + +BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter); + +VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt); + +BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter); + +BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter); + +#if defined(_HIF_SPI) +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter); +#endif + +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data); + +VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data); + +VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap); + +P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); + +P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum); + +P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx); + +VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter); + +UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter); + +/* Media State Change */ +WLAN_STATUS +nicMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +/* Utility function for channel number conversion */ +UINT_32 nicChannelNum2Freq(IN UINT_32 u4ChannelNum); + +UINT_32 nicFreq2ChannelNum(IN UINT_32 u4FreqInKHz); + +/* firmware command wrapper */ + /* NETWORK (WIFISYS) */ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* BSS-INFO */ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* BSS-INFO Indication (PM) */ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + + /* Beacon Template Update */ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen); + +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam); + +/*----------------------------------------------------------------------------*/ +/* Calibration Control */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam); + +WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset); + +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult); + +/*----------------------------------------------------------------------------*/ +/* PHY configuration */ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* MGMT and System Service Control */ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter); + +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent); + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent); +/*----------------------------------------------------------------------------*/ +/* Scan Result Processing */ +/*----------------------------------------------------------------------------*/ +VOID +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_32 u4Privacy, + IN PARAM_RSSI rRssi, + IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, + IN P_PARAM_802_11_CONFIG_T prConfiguration, + IN ENUM_PARAM_OP_MODE_T eOpMode, + IN PARAM_RATES_EX rSupportedRates, IN UINT_16 u2IELength, IN PUINT_8 pucIEBuf); + +VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx); + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +/*----------------------------------------------------------------------------*/ +/* Workaround Control */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicEnableClockGating(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicDisableClockGating(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* Fixed Rate Hacking */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams(IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 u2HtCapInfo); + +/*----------------------------------------------------------------------------*/ +/* Write registers */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value); + +/*----------------------------------------------------------------------------*/ +/* Update auto rate */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3); + +/*----------------------------------------------------------------------------*/ +/* Enable/Disable Roaming */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRoamingUpdateParams(IN P_ADAPTER_T prAdapter, IN UINT_32 u4EnableRoaming); + +VOID nicPrintFirmwareAssertInfo(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Link Quality Updating */ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN P_EVENT_LINK_QUALITY prEventLinkQuality); + +VOID +nicUpdateRSSI(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality); + +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN UINT_16 u2LinkSpeed); + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam); +#endif + +#endif /* _NIC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h new file mode 100644 index 0000000000000..86e2c84b07ffa --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_rx.h @@ -0,0 +1,420 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_rx.h#1 +*/ + +/*! \file "nic_rx.h" + \brief The declaration of the nic rx functions + +*/ + +/* +** Log: nic_rx.h + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode + * and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Change prototype of API of adding P2P device to scan result. + * Additional IE buffer is saved. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 05 2010 yuche.tsai + * NULL + * Modify data structure for P2P Scan result. + * + * 08 03 2010 cp.wu + * NULL + * newly added P2P API should be declared in header file. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * 2) firmware image length is now retrieved via NdisFileOpen + * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * 4) nicRxWaitResponse() revised + * * 5) another set of TQ counter default value is added for fw-download state + * * 6) Wi-Fi load address is now retrieved from registry too + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * and result is retrieved by get ATInfo instead + * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:49:09 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-12-09 14:02:37 GMT MTK02468 +** Added ucStaRecIdx in SW_RFB_T and HALF_SEQ_NO_COUNT definition (to replace HALF_SEQ_NO_CNOUT) +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-27 11:07:54 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-25 18:18:09 GMT mtk02752 +** modify nicRxAddScanResult() +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-24 22:42:22 GMT mtk02752 +** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-24 19:57:06 GMT mtk02752 +** adopt P_HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-16 21:43:04 GMT mtk02752 +** correct ENUM_RX_PKT_DESTINATION_T definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 15:28:25 GMT mtk02752 +** add ucQueuedPacketNum for indicating how many packet are queued by RX reordering buffer/forwarding path +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 15:05:01 GMT mtk02752 +** add eTC for SW_RFB_T and structure RX_MAILBOX +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-13 21:16:57 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-13 16:59:30 GMT mtk02752 +** add handler for event packet +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-13 13:45:50 GMT mtk02752 +** add port param for nicRxEnhanceReadBuffer() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-11 10:12:31 GMT mtk02752 +** nicSDIOReadIntStatus() always read sizeof(ENHANCE_MODE_DATA_STRUCT_T) for int response, +** thus the number should be set to 0(:=16) instead of 10 +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-10-29 19:53:32 GMT mtk01084 +** modify structure naming +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-23 16:08:23 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:01 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-20 12:23:33 GMT mtk01461 +** Add u4MaxEventBufferLen parameter to nicRxWaitResponse() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-05-18 21:00:48 GMT mtk01426 +** Update SDIO_MAXIMUM_RX_STATUS value +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-28 10:36:15 GMT mtk01461 +** Remove unused define - SDIO_MAXIMUM_TX_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:17 GMT mtk01461 +** Add function for HIF_LOOPBACK_PRE_TEST +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:56:19 GMT mtk01426 +** Add to support CFG_HIF_LOOPBACK and CFG_SDIO_RX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:19:56 GMT mtk01426 +** Add nicRxWaitResponse function proto type +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:35 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_RX_H +#define _NIC_RX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern P_SW_RFB_T g_arGscnResultsTempBuffer[]; +extern UINT_8 g_GscanResultsTempBufferIndex; +extern UINT_8 g_arGscanResultsIndicateNumber[]; +extern UINT_8 g_GetResultsBufferedCnt; +extern UINT_8 g_GetResultsCmdCnt; +extern void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define MAX_SEQ_NO 4095 +#define MAX_SEQ_NO_COUNT 4096 +#define HALF_SEQ_NO_CNOUT 2048 + +#define HALF_SEQ_NO_COUNT 2048 + +#define MT6620_FIXED_WIN_SIZE 64 +#define CFG_RX_MAX_BA_ENTRY 4 +#define CFG_RX_MAX_BA_TID_NUM 8 + +#define RX_STATUS_FLAG_MORE_PACKET BIT(30) +#define RX_STATUS_CHKSUM_MASK BITS(0, 10) + +#define RX_RFB_LEN_FIELD_LEN 4 +#define RX_HEADER_OFFSET 2 + +#define RX_RETURN_INDICATED_RFB_TIMEOUT_SEC 3 + +#if defined(_HIF_SDIO) && defined(WINDOWS_DDK) +/*! On XP, maximum Tx+Rx Statue <= 64-4(HISR)*/ +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#else +#define SDIO_MAXIMUM_RX_LEN_NUM 0 /*!< 0~15 (0: un-limited) */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_RX_STATISTIC_COUNTER_T { + RX_MPDU_TOTAL_COUNT = 0, + RX_SIZE_ERR_DROP_COUNT, + + RX_DATA_INDICATION_COUNT, + RX_DATA_RETURNED_COUNT, + RX_DATA_RETAINED_COUNT, + + RX_DROP_TOTAL_COUNT, + RX_TYPE_ERR_DROP_COUNT, + RX_CLASS_ERR_DROP_COUNT, + RX_DST_NULL_DROP_COUNT, + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + RX_CSUM_TCP_FAILED_COUNT, + RX_CSUM_UDP_FAILED_COUNT, + RX_CSUM_IP_FAILED_COUNT, + RX_CSUM_TCP_SUCCESS_COUNT, + RX_CSUM_UDP_SUCCESS_COUNT, + RX_CSUM_IP_SUCCESS_COUNT, + RX_CSUM_UNKNOWN_L4_PKT_COUNT, + RX_CSUM_UNKNOWN_L3_PKT_COUNT, + RX_IP_V6_PKT_CCOUNT, +#endif + RX_STATISTIC_COUNTER_NUM +} ENUM_RX_STATISTIC_COUNTER_T; + +typedef enum _ENUM_RX_PKT_DESTINATION_T { + RX_PKT_DESTINATION_HOST, /* to OS */ + RX_PKT_DESTINATION_FORWARD, /* to TX queue for forward, AP mode */ + RX_PKT_DESTINATION_HOST_WITH_FORWARD, /* to both TX and OS, AP mode broadcast packet */ + RX_PKT_DESTINATION_NULL, /* packet to be freed */ + RX_PKT_DESTINATION_NUM +} ENUM_RX_PKT_DESTINATION_T; + +struct _SW_RFB_T { + QUE_ENTRY_T rQueEntry; + PVOID pvPacket; /*!< ptr to rx Packet Descriptor */ + PUINT_8 pucRecvBuff; /*!< ptr to receive data buffer */ + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4HifRxHdrFlag; + PVOID pvHeader; + UINT_16 u2PacketLen; + UINT_16 u2HeaderLen; + UINT_16 u2SSN; + UINT_8 ucTid; + UINT_8 ucWlanIdx; + UINT_8 ucPacketType; + UINT_8 ucStaRecIdx; + + ENUM_CSUM_RESULT_T aeCSUM[CSUM_TYPE_NUM]; + ENUM_RX_PKT_DESTINATION_T eDst; + ENUM_TRAFFIC_CLASS_INDEX_T eTC; /* only valid when eDst == FORWARD */ + + UINT_64 rRxTime; +}; + +/*! RX configuration type structure */ +typedef struct _RX_CTRL_T { + UINT_32 u4RxCachedSize; + PUINT_8 pucRxCached; + QUE_T rFreeSwRfbList; + QUE_T rReceivedRfbList; + QUE_T rIndicatedRfbList; + +#if CFG_SDIO_RX_AGG + PUINT_8 pucRxCoalescingBufPtr; +#endif + + PVOID apvIndPacket[CFG_RX_MAX_PKT_NUM]; + PVOID apvRetainedPacket[CFG_RX_MAX_PKT_NUM]; + + UINT_8 ucNumIndPacket; + UINT_8 ucNumRetainedPacket; + UINT_64 au8Statistics[RX_STATISTIC_COUNTER_NUM]; /*!< RX Counters */ + +#if CFG_HIF_STATISTICS + UINT_32 u4TotalRxAccessNum; + UINT_32 u4TotalRxPacketNum; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + UINT_32 u4QueuedCnt; + UINT_32 u4DequeuedCnt; +#endif + +#if CFG_RX_PKTS_DUMP + UINT_32 u4RxPktsDumpTypeMask; +#endif + +} RX_CTRL_T, *P_RX_CTRL_T; + +typedef struct _RX_MAILBOX_T { + UINT_32 u4RxMailbox[2]; /* for Device-to-Host Mailbox */ +} RX_MAILBOX_T, *P_RX_MAILBOX_T; + +typedef WLAN_STATUS(*PROCESS_RX_MGT_FUNCTION) (P_ADAPTER_T, P_SW_RFB_T); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define RX_INC_CNT(prRxCtrl, eCounter) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]++; } + +#define RX_ADD_CNT(prRxCtrl, eCounter, u8Amount) \ + {((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter] += (UINT_64)u8Amount; } + +#define RX_GET_CNT(prRxCtrl, eCounter) \ + (((P_RX_CTRL_T)prRxCtrl)->au8Statistics[eCounter]) + +#define RX_RESET_ALL_CNTS(prRxCtrl) \ + {kalMemZero(&prRxCtrl->au8Statistics[0], sizeof(prRxCtrl->au8Statistics)); } + +#define RX_STATUS_TEST_MORE_FLAG(flag) \ + ((BOOLEAN)((flag & RX_STATUS_FLAG_MORE_PACKET) ? TRUE : FALSE)) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter); + +#if !CFG_SDIO_INTR_ENHANCE +VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#else +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS +nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); + +VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prRfb); + +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus); + +VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); + +VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter); + +VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count); + +WLAN_STATUS +nicRxWaitResponse(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length); + +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter); + +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +#endif /* _NIC_RX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h new file mode 100644 index 0000000000000..e516468fcb16a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/nic_tx.h @@ -0,0 +1,642 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/nic_tx.h#1 +*/ + +/*! \file nic_tx.h + \brief Functions that provide TX operation in NIC's point of view. + + This file provides TX functions which are responsible for both Hardware and + Software Resource Management and keep their Synchronization. + +*/ + +/* +** Log: nic_tx.h + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add log counter for tx + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add TX_DONE status detail information. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing + * frame dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 02 16 2011 cp.wu + * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking + * available count and modify behavior + * 1. add new API: nicTxGetFreeCmdCount() + * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 12 15 2010 yuche.tsai + * NULL + * Update SLT Descriptor number configure in driver. + * + * 11 16 2010 yarco.yang + * [WCXRP00000177] [MT5931 F/W] Performance tuning for 1st connection + * Update TX buffer count + * + * 11 03 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * 1) use 8 buffers for MT5931 which is equipped with less memory + * 2) modify MT5931 debug level to TRACE when download is successful + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 07 26 2010 cp.wu + * + * change TC4 initial value from 2 to 4. + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under + * concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add MGMT Packet type for HIF_TX_HEADER + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add flag on MSDU_INFO_T for indicating BIP frame and forceBasicRate + * 2) add packet type for indicating management frames + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add TX_PACKET_MGMT to indicate the frame is coming from management modules + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 02 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Redistributed the initial TC resources for normal operation + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * 4) nicRxWaitResponse() revised + * * * 5) another set of TQ counter default value is added for fw-download state + * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * 4. correct some HAL implementation + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * and result is retrieved by get ATInfo instead + * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:53:28 GMT mtk02752 +** remove unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-27 11:08:00 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-24 19:56:49 GMT mtk02752 +** remove redundant eTC +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-23 22:01:08 GMT mtk02468 +** Added MSDU_INFO fields for composing HIF TX header +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-17 22:40:51 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-11-17 17:35:05 GMT mtk02752 +** + nicTxMsduInfoList() for sending MsduInfoList +** + NIC_TX_BUFF_COUNT_TC[0~5] +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-11-17 11:07:00 GMT mtk02752 +** add nicTxAdjustTcq() API +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-11-16 22:28:30 GMT mtk02752 +** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-11-16 21:44:50 GMT mtk02752 +** + nicTxReturnMsduInfo() +** + nicTxFillMsduInfo() +** + rFreeMsduInfoList field in TX_CTRL +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-11-16 18:00:43 GMT mtk02752 +** use P_PACKET_INFO_T for prPacket to avoid inventing another new structure for packet +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-11-16 15:28:49 GMT mtk02752 +** add ucQueuedPacketNum for indicating how many packets are queued by per STA/AC queue +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-16 10:52:01 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-14 23:39:24 GMT mtk02752 +** interface structure redefine +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-13 21:17:03 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-10-29 19:53:10 GMT mtk01084 +** remove strange code by Frog +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:59:04 GMT mtk01084 +** update for new HW architecture design +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-10-02 13:53:03 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-28 10:36:50 GMT mtk01461 +** Add declaration of nicTxReleaseResource() +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-17 19:58:39 GMT mtk01461 +** Move CMD_INFO_T related define and function to cmd_buf.h +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:53:53 GMT mtk01461 +** Add function for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:33:27 GMT mtk01461 +** Define constants for TX PATH and add nicTxPollingResource +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:09:32 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:38 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _NIC_TX_H +#define _NIC_TX_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NIC_TX_RESOURCE_POLLING_TIMEOUT 256 +#define NIC_TX_RESOURCE_POLLING_DELAY_MSEC 50 + +/* Maximum buffer count for individual HIF TCQ */ + +#if defined(MT6620) +#if CFG_SLT_SUPPORT + /* 20101215 mtk01725 Redistributed the initial TC resources for SLT operation */ +#define NIC_TX_BUFF_COUNT_TC0 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 16 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 0 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 0 /* First connection: 0 */ +#else + /* 20100302 mtk02468 Redistributed the initial TC resources for normal operation */ +#define NIC_TX_BUFF_COUNT_TC0 6 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 8 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 8 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 8 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 2 /* First connection: 0 */ +#endif +#elif defined(MT6628) +#if (CFG_SRAM_SIZE_OPTION == 0) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 20 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#elif (CFG_SRAM_SIZE_OPTION == 1) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 36 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#elif (CFG_SRAM_SIZE_OPTION == 2) +#define NIC_TX_BUFF_COUNT_TC0 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC1 48 /* First connection: 32 */ +#define NIC_TX_BUFF_COUNT_TC2 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC3 1 /* First connection: 0 */ +#define NIC_TX_BUFF_COUNT_TC4 4 /* First connection: 2 */ +#define NIC_TX_BUFF_COUNT_TC5 1 /* First connection: 0 */ +#else +#error "> Set TX_BUFF_COUNT_TC error!" +#endif +#endif + +#define NIC_TX_BUFF_SUM (NIC_TX_BUFF_COUNT_TC0 + \ + NIC_TX_BUFF_COUNT_TC1 + \ + NIC_TX_BUFF_COUNT_TC2 + \ + NIC_TX_BUFF_COUNT_TC3 + \ + NIC_TX_BUFF_COUNT_TC4 + \ + NIC_TX_BUFF_COUNT_TC5) +#if CFG_ENABLE_FW_DOWNLOAD + +#define NIC_TX_INIT_BUFF_COUNT_TC0 8 +#define NIC_TX_INIT_BUFF_COUNT_TC1 0 +#define NIC_TX_INIT_BUFF_COUNT_TC2 0 +#define NIC_TX_INIT_BUFF_COUNT_TC3 0 +#define NIC_TX_INIT_BUFF_COUNT_TC4 0 +#define NIC_TX_INIT_BUFF_COUNT_TC5 0 + +#define NIC_TX_INIT_BUFF_SUM (NIC_TX_INIT_BUFF_COUNT_TC0 + \ + NIC_TX_INIT_BUFF_COUNT_TC1 + \ + NIC_TX_INIT_BUFF_COUNT_TC2 + \ + NIC_TX_INIT_BUFF_COUNT_TC3 + \ + NIC_TX_INIT_BUFF_COUNT_TC4 + \ + NIC_TX_INIT_BUFF_COUNT_TC5) + +#endif + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define NIC_TX_TIME_THRESHOLD 100 /* in unit of ms */ +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* 3 Session for TX QUEUES */ +/* The definition in this ENUM is used to categorize packet's Traffic Class according + * to the their TID(User Priority). + * In order to achieve QoS goal, a particular TC should not block the process of + * another packet with different TC. + * In current design we will have 5 categories(TCs) of SW resource. + */ +typedef enum _ENUM_TRAFFIC_CLASS_INDEX_T { + TC0_INDEX = 0, /* HIF TX0: AC0 packets */ + TC1_INDEX, /* HIF TX0: AC1 packets & non-QoS packets */ + TC2_INDEX, /* HIF TX0: AC2 packets */ + TC3_INDEX, /* HIF TX0: AC3 packets */ + TC4_INDEX, /* HIF TX1: Command packets or 802.1x packets */ + TC5_INDEX, /* HIF TX0: BMCAST packets */ + TC_NUM /* Maximum number of Traffic Classes. */ +} ENUM_TRAFFIC_CLASS_INDEX_T; + +typedef enum _ENUM_TX_STATISTIC_COUNTER_T { + TX_MPDU_TOTAL_COUNT = 0, + TX_INACTIVE_BSS_DROP, + TX_INACTIVE_STA_DROP, + TX_FORWARD_OVERFLOW_DROP, + TX_AP_BORADCAST_DROP, + TX_STATISTIC_COUNTER_NUM +} ENUM_TX_STATISTIC_COUNTER_T; + +typedef struct _TX_TCQ_STATUS_T { + UINT_8 aucFreeBufferCount[TC_NUM]; + UINT_8 aucMaxNumOfBuffer[TC_NUM]; +} TX_TCQ_STATUS_T, *P_TX_TCQ_STATUS_T; + +typedef struct _TX_TCQ_ADJUST_T { + INT_8 acVariation[TC_NUM]; +} TX_TCQ_ADJUST_T, *P_TX_TCQ_ADJUST_T; + +typedef struct _TX_CTRL_T { + UINT_32 u4TxCachedSize; + PUINT_8 pucTxCached; + +/* Elements below is classified according to TC (Traffic Class) value. */ + + TX_TCQ_STATUS_T rTc; + + PUINT_8 pucTxCoalescingBufPtr; + + QUE_T rFreeMsduInfoList; + + /* Management Frame Tracking */ + /* number of management frames to be sent */ + INT_32 i4TxMgmtPendingNum; + + /* to tracking management frames need TX done callback */ + QUE_T rTxMgmtTxingQueue; + +#if CFG_HIF_STATISTICS + UINT_32 u4TotalTxAccessNum; + UINT_32 u4TotalTxPacketNum; +#endif + UINT_32 au4Statistics[TX_STATISTIC_COUNTER_NUM]; + + /* Number to track forwarding frames */ + INT_32 i4PendingFwdFrameCount; + +} TX_CTRL_T, *P_TX_CTRL_T; + +typedef enum _ENUM_TX_PACKET_SRC_T { + TX_PACKET_OS, + TX_PACKET_OS_OID, + TX_PACKET_FORWARDING, + TX_PACKET_MGMT, + TX_PACKET_NUM +} ENUM_TX_PACKET_SRC_T; + +typedef enum _ENUM_HIF_TX_PACKET_TYPE_T { + HIF_TX_PACKET_TYPE_DATA = 0, + HIF_TX_PACKET_TYPE_COMMAND, + HIF_TX_PACKET_TYPE_HIF_LB, + HIF_TX_PACKET_TYPE_MGMT +} ENUM_HIF_TX_PACKET_TYPE_T, *P_ENUM_HIF_TX_PACKET_TYPE_T; + +typedef enum _ENUM_TX_RESULT_CODE_T { + TX_RESULT_SUCCESS = 0, + TX_RESULT_LIFE_TIMEOUT, + TX_RESULT_RTS_ERROR, + TX_RESULT_MPDU_ERROR, + TX_RESULT_AGING_TIMEOUT, + TX_RESULT_FLUSHED, + TX_RESULT_DROPPED_IN_DRIVER = 32, + TX_RESULT_NUM +} ENUM_TX_RESULT_CODE_T, *P_ENUM_TX_RESULT_CODE_T; + +struct _WLAN_CFG_ENTRY_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; + WLAN_CFG_SET_CB pfSetCb; + PVOID pPrivate; + UINT_32 u4Flags; +}; + +struct _WLAN_CFG_T { + UINT_32 u4WlanCfgEntryNumMax; + UINT_32 u4WlanCfgKeyLenMax; + UINT_32 u4WlanCfgValueLenMax; + WLAN_CFG_ENTRY_T arWlanCfgBuf[WLAN_CFG_ENTRY_NUM_MAX]; +}; + +/* TX Call Back Function */ +typedef WLAN_STATUS(*PFN_TX_DONE_HANDLER) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +typedef struct _PKT_PROFILE_T { + BOOLEAN fgIsValid; +#if CFG_PRINT_RTP_PROFILE + BOOLEAN fgIsPrinted; + UINT_16 u2IpSn; + UINT_16 u2RtpSn; + UINT_8 ucTcxFreeCount; +#endif + OS_SYSTIME rHardXmitArrivalTimestamp; + OS_SYSTIME rEnqueueTimestamp; + OS_SYSTIME rDequeueTimestamp; + OS_SYSTIME rHifTxDoneTimestamp; +} PKT_PROFILE_T, *P_PKT_PROFILE_T; +#endif + +/* TX transactions could be divided into 4 kinds: + * + * 1) 802.1X / Bluetooth-over-Wi-Fi Security Frames + * [CMD_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + * + * 2) MMPDU + * [CMD_INFO_T] - [prPacket] - [MSDU_INFO_T] - [prPacket] - direct buffer for frame body + * + * 3) Command Packets + * [CMD_INFO_T] - [pucInfoBuffer] - direct buffer for content of command packet + * + * 4) Normal data frame + * [MSDU_INFO_T] - [prPacket] - in skb or NDIS_PACKET form + */ + +/* PS_FORWARDING_TYPE_NON_PS means that the receiving STA is in Active Mode +* from the perspective of host driver (maybe not synchronized with FW --> SN is needed) +*/ + +struct _MSDU_INFO_T { + QUE_ENTRY_T rQueEntry; + P_NATIVE_PACKET prPacket; + + ENUM_TX_PACKET_SRC_T eSrc; /* specify OS/FORWARD packet */ + UINT_8 ucUserPriority; + + /* For composing HIF TX header */ + UINT_8 ucTC; /* Traffic Class: 0~4 (HIF TX0), 5 (HIF TX1) */ + UINT_8 ucPacketType; /* 0: Data, 1: Command, 2: HIF Loopback 3: Management Frame */ + UINT_8 ucStaRecIndex; + UINT_8 ucNetworkType; /* See ENUM_NETWORK_TYPE_T */ + UINT_8 ucFormatID; /* 0: MAUI, Linux, Windows NDIS 5.1 */ + BOOLEAN fgIs802_1x; /* TRUE: 802.1x frame */ + BOOLEAN fgIs802_11; /* TRUE: 802.11 header is present */ + UINT_16 u2PalLLH; /* PAL Logical Link Header (for BOW network) */ + UINT_16 u2AclSN; /* ACL Sequence Number (for BOW network) */ + UINT_8 ucPsForwardingType; /* See ENUM_PS_FORWARDING_TYPE_T */ + UINT_8 ucPsSessionID; /* PS Session ID specified by the FW for the STA */ + BOOLEAN fgIsBurstEnd; /* TRUE means this is the last packet of the burst for (STA, TID) */ + BOOLEAN fgIsBIP; /* Management Frame Protection */ + BOOLEAN fgIsBasicRate; /* Force Basic Rate Transmission */ + + /* flattened from PACKET_INFO_T */ + UINT_8 ucMacHeaderLength; + UINT_8 ucLlcLength; /* w/o EtherType */ + UINT_16 u2FrameLength; + UINT_8 aucEthDestAddr[MAC_ADDR_LEN]; /* Ethernet Destination Address */ + + /* for TX done tracking */ + UINT_8 ucTxSeqNum; + PFN_TX_DONE_HANDLER pfTxDoneHandler; + BOOLEAN fgNeedTxDoneStatus; + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + PKT_PROFILE_T rPktProfile; +#endif + COMMAND_TYPE eCmdType; + UINT_8 ucCID; + UINT_32 u4InqueTime; +}; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define TX_INC_CNT(prTxCtrl, eCounter) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]++; } + +#define TX_ADD_CNT(prTxCtrl, eCounter, u8Amount) \ + {((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter] += (UINT_32)u8Amount; } + +#define TX_GET_CNT(prTxCtrl, eCounter) \ + (((P_TX_CTRL_T)prTxCtrl)->au4Statistics[eCounter]) + +#define TX_RESET_ALL_CNTS(prTxCtrl) \ + {kalMemZero(&prTxCtrl->au4Statistics[0], sizeof(prTxCtrl->au4Statistics)); } + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#define PRINT_PKT_PROFILE(_pkt_profile, _note) \ +{ \ + if (!(_pkt_profile)->fgIsPrinted) { \ + DBGLOG(TX, TRACE, "X[%u] E[%u] D[%u] HD[%u] B[%d] RTP[%d] %s\n", \ + (UINT_32)((_pkt_profile)->rHardXmitArrivalTimestamp), \ + (UINT_32)((_pkt_profile)->rEnqueueTimestamp), \ + (UINT_32)((_pkt_profile)->rDequeueTimestamp), \ + (UINT_32)((_pkt_profile)->rHifTxDoneTimestamp), \ + (UINT_8)((_pkt_profile)->ucTcxFreeCount), \ + (UINT_16)((_pkt_profile)->u2RtpSn), \ + (_note)); \ + (_pkt_profile)->fgIsPrinted = TRUE; \ + } \ +} + +#define CHK_PROFILES_DELTA(_pkt1, _pkt2, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt1)->rHardXmitArrivalTimestamp, (_pkt2)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rEnqueueTimestamp, (_pkt2)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rDequeueTimestamp, (_pkt2)->rDequeueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt1)->rHifTxDoneTimestamp, (_pkt2)->rHifTxDoneTimestamp, (_delta))) + +#define CHK_PROFILE_DELTA(_pkt, _delta) \ + (CHECK_FOR_TIMEOUT((_pkt)->rEnqueueTimestamp, (_pkt)->rHardXmitArrivalTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rDequeueTimestamp, (_pkt)->rEnqueueTimestamp, (_delta)) || \ + CHECK_FOR_TIMEOUT((_pkt)->rHifTxDoneTimestamp, (_pkt)->rDequeueTimestamp, (_delta))) +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt); + +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN UINT_8 *aucTxRlsCnt); + +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter); + +UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC); + +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue); + +WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); + +VOID nicTxRelease(IN P_ADAPTER_T prAdapter); + +VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter); + +VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prNdisPacket); + +WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter); + +#if CFG_ENABLE_FW_DOWNLOAD +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC); + +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter); +#endif + +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_TX_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h new file mode 100644 index 0000000000000..d518aaf10eb56 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p.h @@ -0,0 +1,192 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p.h#3 +*/ + +/* +** Log: p2p.h + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * p2p interface revised to be sync. with HAL + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 18 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add parameter to control: + * 1) auto group owner + * 2) P2P-PS parameter (CTWindow, NoA descriptors) + * + * 05 18 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * correct WPS Device Password ID definition. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * +*/ + +#ifndef _P2P_H +#define _P2P_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* refer to 'Config Methods' in WPS */ +#define WPS_CONFIG_USBA 0x0001 +#define WPS_CONFIG_ETHERNET 0x0002 +#define WPS_CONFIG_LABEL 0x0004 +#define WPS_CONFIG_DISPLAY 0x0008 +#define WPS_CONFIG_EXT_NFC 0x0010 +#define WPS_CONFIG_INT_NFC 0x0020 +#define WPS_CONFIG_NFC 0x0040 +#define WPS_CONFIG_PBC 0x0080 +#define WPS_CONFIG_KEYPAD 0x0100 + +/* refer to 'Device Password ID' in WPS */ +#define WPS_DEV_PASSWORD_ID_PIN 0x0000 +#define WPS_DEV_PASSWORD_ID_USER 0x0001 +#define WPS_DEV_PASSWORD_ID_MACHINE 0x0002 +#define WPS_DEV_PASSWORD_ID_REKEY 0x0003 +#define WPS_DEV_PASSWORD_ID_PUSHBUTTON 0x0004 +#define WPS_DEV_PASSWORD_ID_REGISTRAR 0x0005 + +#define P2P_DEVICE_TYPE_NUM 2 +#define P2P_DEVICE_NAME_LENGTH 32 +#define P2P_NETWORK_NUM 8 +#define P2P_MEMBER_NUM 8 + +#define P2P_WILDCARD_SSID "DIRECT-" + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +struct _P2P_INFO_T { + UINT_32 u4DeviceNum; + EVENT_P2P_DEV_DISCOVER_RESULT_T arP2pDiscoverResult[CFG_MAX_NUM_BSS_LIST]; + PUINT_8 pucCurrIePtr; + UINT_8 aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]; /* A common pool for IE of all scan results. */ +}; + +typedef enum { + ENUM_P2P_PEER_GROUP, + ENUM_P2P_PEER_DEVICE, + ENUM_P2P_PEER_NUM +} ENUM_P2P_PEER_TYPE, *P_ENUM_P2P_PEER_TYPE; + +typedef struct _P2P_DEVICE_INFO { + UINT_8 aucDevAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 aucIfAddr[PARAM_MAC_ADDR_LEN]; + UINT_8 ucDevCapabilityBitmap; + INT_32 i4ConfigMethod; + UINT_8 aucPrimaryDeviceType[8]; + UINT_8 aucSecondaryDeviceType[8]; + UINT_8 aucDeviceName[P2P_DEVICE_NAME_LENGTH]; +} P2P_DEVICE_INFO, *P_P2P_DEVICE_INFO; + +typedef struct _P2P_GROUP_INFO { + PARAM_SSID_T rGroupID; + P2P_DEVICE_INFO rGroupOwnerInfo; + UINT_8 ucMemberNum; + P2P_DEVICE_INFO arMemberInfo[P2P_MEMBER_NUM]; +} P2P_GROUP_INFO, *P_P2P_GROUP_INFO; + +typedef struct _P2P_NETWORK_INFO { + ENUM_P2P_PEER_TYPE eNodeType; + + union { + P2P_GROUP_INFO rGroupInfo; + P2P_DEVICE_INFO rDeviceInfo; + } node; + +} P2P_NETWORK_INFO, *P_P2P_NETWORK_INFO; + +typedef struct _P2P_NETWORK_LIST { + UINT_8 ucNetworkNum; + P2P_NETWORK_INFO rP2PNetworkInfo[P2P_NETWORK_NUM]; +} P2P_NETWORK_LIST, *P_P2P_NETWORK_LIST; + +typedef struct _P2P_DISCONNECT_INFO { + UINT_8 ucRole; + UINT_8 ucRsv[3]; +} P2P_DISCONNECT_INFO, *P_P2P_DISCONNECT_INFO; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h new file mode 100644 index 0000000000000..7f7a92584c7ce --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_cmd_buf.h @@ -0,0 +1,83 @@ +/* +** Id: +*/ + +/*! \file "p2p_cmd_buf.h" + \brief In this file we define the structure for Command Packet. + + In this file we define the structure for Command Packet and the control unit + of MGMT Memory Pool. +*/ + +/* +** Log: p2p_cmd_buf.h + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface + * for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks +*/ + +#ifndef _P2P_CMD_BUF_H +#define _P2P_CMD_BUF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryP2PCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + BOOLEAN fgIsOid, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, + PUINT_8 pucInfoBuffer, OUT PVOID pvSetQueryBuffer, IN UINT_32 u4SetQueryBufferLen); + +#endif /* _P2P_CMD_BUF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h new file mode 100644 index 0000000000000..76115dabe1a1d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_mac.h @@ -0,0 +1,207 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_mac.h#2 +*/ + +/*! \file "p2p_mac.h" + \brief Brief description. + + Detail description. +*/ + +#ifndef _P2P_MAC_H +#define _P2P_MAC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define ACTION_PUBLIC_WIFI_DIRECT 9 +#define ACTION_GAS_INITIAL_REQUEST 10 +#define ACTION_GAS_INITIAL_RESPONSE 11 +#define ACTION_GAS_COMEBACK_REQUEST 12 +#define ACTION_GAS_COMEBACK_RESPONSE 13 + +/* P2P 4.2.8.1 - P2P Public Action Frame Type. */ +#define P2P_PUBLIC_ACTION_GO_NEGO_REQ 0 +#define P2P_PUBLIC_ACTION_GO_NEGO_RSP 1 +#define P2P_PUBLIC_ACTION_GO_NEGO_CFM 2 +#define P2P_PUBLIC_ACTION_INVITATION_REQ 3 +#define P2P_PUBLIC_ACTION_INVITATION_RSP 4 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_REQ 5 +#define P2P_PUBLIC_ACTION_DEV_DISCOVER_RSP 6 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_REQ 7 +#define P2P_PUBLIC_ACTION_PROV_DISCOVERY_RSP 8 + +/* P2P 4.2.9.1 - P2P Action Frame Type */ +#define P2P_ACTION_NOTICE_OF_ABSENCE 0 +#define P2P_ACTION_P2P_PRESENCE_REQ 1 +#define P2P_ACTION_P2P_PRESENCE_RSP 2 +#define P2P_ACTION_GO_DISCOVER_REQ 3 + +#define P2P_PUBLIC_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+8) +#define P2P_ACTION_FRAME_LEN (WLAN_MAC_MGMT_HEADER_LEN+7) + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/* P2P 4.2.8.2 P2P Public Action Frame Format */ +typedef struct _P2P_PUBLIC_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ + UINT_8 ucOuiType; /* 0x09 */ + UINT_8 ucOuiSubtype; /* GO Nego Req/Rsp/Cfm, P2P Invittion Req/Rsp, Device Discoverability Req/Rsp */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* P2P IE, WSC IE. */ +} __KAL_ATTRIB_PACKED__ P2P_PUBLIC_ACTION_FRAME_T, *P_P2P_PUBLIC_ACTION_FRAME_T; + +/* P2P 4.2.9.1 - General Action Frame Format. */ +typedef struct _P2P_ACTION_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Action Frame Body */ + UINT_8 ucCategory; /* 0x7F */ + UINT_8 aucOui[3]; /* 0x50, 0x6F, 0x9A */ + UINT_8 ucOuiType; /* 0x09 */ + UINT_8 ucOuiSubtype; /* */ + UINT_8 ucDialogToken; + UINT_8 aucInfoElem[1]; +} __KAL_ATTRIB_PACKED__ P2P_ACTION_FRAME_T, *P_P2P_ACTION_FRAME_T; + +/* P2P C.1 GAS Public Action Initial Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_REQUEST_FRAME_T; + +/* P2P C.2 GAS Public Action Initial Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Initial Response. */ + UINT_16 u2ComebackDelay; /* Initial Response. *//* In unit of TU. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_INITIAL_RESPONSE_FRAME_T; + +/* P2P C.3-1 GAS Public Action Comeback Request Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_REQUEST_FRAME_T; + +/* P2P C.3-2 GAS Public Action Comeback Response Frame Format */ +typedef struct _GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T { + /* MAC header */ + UINT_16 u2FrameCtrl; /* Frame Control */ + UINT_16 u2Duration; /* Duration */ + UINT_8 aucDestAddr[MAC_ADDR_LEN]; /* DA */ + UINT_8 aucSrcAddr[MAC_ADDR_LEN]; /* SA */ + UINT_8 aucBSSID[MAC_ADDR_LEN]; /* BSSID */ + UINT_16 u2SeqCtrl; /* Sequence Control */ + /* P2P Public Action Frame Body */ + UINT_8 ucCategory; /* Category, 0x04 */ + UINT_8 ucAction; /* Action Value, 0x09 */ + UINT_8 ucDialogToken; /* Dialog Token. */ + UINT_16 u2StatusCode; /* Comeback Response. */ + UINT_8 ucFragmentID; /*Comeback Response. */ + UINT_16 u2ComebackDelay; /* Comeback Response. */ + UINT_8 aucInfoElem[1]; /* Advertisement IE. */ +} __KAL_ATTRIB_PACKED__ GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T, *P_GAS_PUBLIC_ACTION_COMEBACK_RESPONSE_FRAME_T; + +typedef struct _P2P_SD_VENDER_SPECIFIC_CONTENT_T { + /* Service Discovery Vendor-specific Content. */ + UINT_8 ucOuiSubtype; /* 0x09 */ + UINT_16 u2ServiceUpdateIndicator; + UINT_8 aucServiceTLV[1]; +} __KAL_ATTRIB_PACKED__ P2P_SD_VENDER_SPECIFIC_CONTENT_T, *P_P2P_SD_VENDER_SPECIFIC_CONTENT_T; + +typedef struct _P2P_SERVICE_REQUEST_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 aucQueryData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_REQUEST_TLV_T, *P_P2P_SERVICE_REQUEST_TLV_T; + +typedef struct _P2P_SERVICE_RESPONSE_TLV_T { + UINT_16 u2Length; + UINT_8 ucServiceProtocolType; + UINT_8 ucServiceTransID; + UINT_8 ucStatusCode; + UINT_8 aucResponseData[1]; +} __KAL_ATTRIB_PACKED__ P2P_SERVICE_RESPONSE_TLV_T, *P_P2P_SERVICE_RESPONSE_TLV_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h new file mode 100644 index 0000000000000..0a87bd457a926 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic.h @@ -0,0 +1,62 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic.h#1 +*/ + +/*! \file "p2p_nic.h" + \brief The declaration of nic functions + + Detail description. +*/ + +#ifndef _P2P_NIC_H +#define _P2P_NIC_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +VOID +nicP2pMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus); + +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h new file mode 100644 index 0000000000000..cea77414ce357 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/p2p_nic_cmd_event.h @@ -0,0 +1,70 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/nic/p2p_nic_cmd_event.h#1 +*/ + +/*! \file p2p_nic_cmd_event.h + \brief +*/ + +#ifndef _P2P_NIC_CMD_EVENT_H +#define _P2P_NIC_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +typedef struct _EVENT_P2P_DEV_DISCOVER_RESULT_T { +/* UINT_8 aucCommunicateAddr[MAC_ADDR_LEN]; // Deprecated. */ + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[2]; + UINT_16 u2NameLength; + UINT_8 aucName[32]; + PUINT_8 pucIeBuf; + UINT_16 u2IELength; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + /* TODO: Service Information or PasswordID valid? */ +} EVENT_P2P_DEV_DISCOVER_RESULT_T, *P_EVENT_P2P_DEV_DISCOVER_RESULT_T; + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h new file mode 100644 index 0000000000000..dbfb90d94ee4c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/que_mgt.h @@ -0,0 +1,971 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/que_mgt.h#1 +*/ + +/*! \file "que_mgt.h" + \brief TX/RX queues management header file + + The main tasks of queue management include TC-based HIF TX flow control, + adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save + forwarding control, RX packet reordering, and RX BA agreement management. +*/ + +/* +** Log: que_mgt.h + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 07 26 2011 eddie.chen + * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter + * API for query the RX reorder queued packets counter. + * + * 06 14 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Change the parameter for WMM pass. + * + * 05 31 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Fix the QM quota in MT5931. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 28 2011 eddie.chen + * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW + * Fix wmm parameters in beacon for BOW. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Change GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * 1) Check Bss if support QoS before adding WMMIE + * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T + * and replaced by ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 07 22 2010 george.huang + * + * Update fgIsQoS information in BSS INFO by CMD + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 yarco.yang + * + * [WPD00003849] + * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 30 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled adaptive TC resource control + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 19 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * By default enabling dynamic STA_REC activation and decactivation + * + * 03 17 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) + * + * 03 11 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed buffer leak when processing BAR frames + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled multi-STA TX path with fairness + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled dynamically activating and deactivating STA_RECs + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for dynamic activating and deactivating STA_RECs. + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-12-09 14:04:53 GMT MTK02468 +** Added RX buffer reordering function prototypes +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-02 22:08:44 GMT MTK02468 +** Added macro QM_INIT_STA_REC for initialize a STA_REC +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 21:58:43 GMT mtk02468 +** Initial version +** +*/ + +#ifndef _QUE_MGT_H +#define _QUE_MGT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* Queue Manager Features */ +/* 1: Indicate the last TX packet to the FW for each burst */ +#define QM_BURST_END_INFO_ENABLED 1 +/* 1: To fairly share TX resource among active STAs */ +#define QM_FORWARDING_FAIRNESS 1 +/* 1: To adaptively adjust resource for each TC */ +#define QM_ADAPTIVE_TC_RESOURCE_CTRL 1 +/* 1: To print TC resource adjustment results */ +#define QM_PRINT_TC_RESOURCE_CTRL 0 +/* 1: If pkt with SSN is missing, auto advance the RX reordering window */ +#define QM_RX_WIN_SSN_AUTO_ADVANCING 1 +/* 1: Indicate the packets falling behind to OS before the frame with SSN is received */ +#define QM_RX_INIT_FALL_BEHIND_PASS 1 +/* 1: Count times of TC resource empty happened */ +#define QM_TC_RESOURCE_EMPTY_COUNTER 1 +/* Parameters */ + +/* + In TDLS or AP mode, peer maybe enter "sleep mode". + + If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, + we need to wait 60 * u4TimeToAdjustTcResource = 180 packets + u4TimeToAdjustTcResource = 3, + then we will adjust TC resouce for VI or VO. + + But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, + we will to wait about 12 seconds to collect 180 packets. + but the test time is only 20 seconds. +*/ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN 60 /* p: Update queue lengths when p TX packets are enqueued */ +#define QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN 5 + +#define QM_INIT_TIME_TO_ADJUST_TC_RSC 3 /* s: Adjust the TC resource every s updates of queue lengths */ +#define QM_QUE_LEN_MOVING_AVE_FACTOR 3 /* Factor for Que Len averaging */ + +#define QM_MIN_RESERVED_TC0_RESOURCE 1 +#define QM_MIN_RESERVED_TC1_RESOURCE 1 +#define QM_MIN_RESERVED_TC2_RESOURCE 1 +#define QM_MIN_RESERVED_TC3_RESOURCE 1 +#define QM_MIN_RESERVED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_MIN_RESERVED_TC5_RESOURCE 1 + +#if defined(MT6620) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 9 +#define QM_GUARANTEED_TC3_RESOURCE 11 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#elif defined(MT6628) + +#define QM_GUARANTEED_TC0_RESOURCE 4 +#define QM_GUARANTEED_TC1_RESOURCE 4 +#define QM_GUARANTEED_TC2_RESOURCE 6 +#define QM_GUARANTEED_TC3_RESOURCE 6 +#define QM_GUARANTEED_TC4_RESOURCE 2 /* Resource for TC4 is not adjustable */ +#define QM_GUARANTEED_TC5_RESOURCE 4 + +#else +#error +#endif + +#define QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY 0 + +#define QM_TOTAL_TC_RESOURCE (\ + NIC_TX_BUFF_COUNT_TC0 + NIC_TX_BUFF_COUNT_TC1 +\ + NIC_TX_BUFF_COUNT_TC2 + NIC_TX_BUFF_COUNT_TC3 +\ + NIC_TX_BUFF_COUNT_TC5) +#define QM_AVERAGE_TC_RESOURCE 6 + +/* Note: QM_INITIAL_RESIDUAL_TC_RESOURCE shall not be less than 0 */ +/* for 6628: QM_TOTAL_TC_RESOURCE = 28, RESIDUAL = 4 4 6 6 2 4 = 26 */ +#define QM_INITIAL_RESIDUAL_TC_RESOURCE (QM_TOTAL_TC_RESOURCE - \ + (QM_GUARANTEED_TC0_RESOURCE +\ + QM_GUARANTEED_TC1_RESOURCE +\ + QM_GUARANTEED_TC2_RESOURCE +\ + QM_GUARANTEED_TC3_RESOURCE +\ + QM_GUARANTEED_TC5_RESOURCE \ + )) + +/* Hard-coded network type for Phase 3: NETWORK_TYPE_AIS/P2P/BOW */ +#define QM_OPERATING_NETWORK_TYPE NETWORK_TYPE_AIS + +#define QM_TEST_MODE 0 +#define QM_TEST_TRIGGER_TX_COUNT 50 +#define QM_TEST_STA_REC_DETERMINATION 0 +#define QM_TEST_STA_REC_DEACTIVATION 0 +#define QM_TEST_FAIR_FORWARDING 0 + +#define QM_DEBUG_COUNTER 0 + +/* Per-STA Queues: [0] AC0, [1] AC1, [2] AC2, [3] AC3, [4] 802.1x */ +/* Per-Type Queues: [0] BMCAST */ +#define NUM_OF_PER_STA_TX_QUEUES 5 +#define NUM_OF_PER_TYPE_TX_QUEUES 1 + +/* These two constants are also used for FW to verify the STA_REC index */ +#define STA_REC_INDEX_BMCAST 0xFF +#define STA_REC_INDEX_NOT_FOUND 0xFE + +/* TX Queue Index */ +#define TX_QUEUE_INDEX_BMCAST 0 +#define TX_QUEUE_INDEX_NO_STA_REC 0 +#define TX_QUEUE_INDEX_AC0 0 +#define TX_QUEUE_INDEX_AC1 1 +#define TX_QUEUE_INDEX_AC2 2 +#define TX_QUEUE_INDEX_AC3 3 +#define TX_QUEUE_INDEX_802_1X 4 +#define TX_QUEUE_INDEX_NON_QOS 1 + +/* 1 WMM-related */ +/* WMM FLAGS */ +#define WMM_FLAG_SUPPORT_WMM BIT(0) +#define WMM_FLAG_SUPPORT_WMMSA BIT(1) +#define WMM_FLAG_AC_PARAM_PRESENT BIT(2) +#define WMM_FLAG_SUPPORT_UAPSD BIT(3) + +/* WMM Admission Control Mandatory FLAGS */ +#define ACM_FLAG_ADM_NOT_REQUIRED 0 +#define ACM_FLAG_ADM_GRANTED BIT(0) +#define ACM_FLAG_ADM_REQUIRED BIT(1) + +/* WMM Power Saving FLAGS */ +#define AC_FLAG_TRIGGER_ENABLED BIT(1) +#define AC_FLAG_DELIVERY_ENABLED BIT(2) + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/* WMM-2.2.2 WMM Parameter Element */ +#define ELEM_MAX_LEN_WMM_PARAM 24 + +/* WMM-2.2.1 WMM QoS Info field */ +#define WMM_QOS_INFO_PARAM_SET_CNT BITS(0, 3) /* Sent by AP */ +#define WMM_QOS_INFO_UAPSD BIT(7) + +#define WMM_QOS_INFO_VO_UAPSD BIT(0) /* Sent by non-AP STA */ +#define WMM_QOS_INFO_VI_UAPSD BIT(1) +#define WMM_QOS_INFO_BK_UAPSD BIT(2) +#define WMM_QOS_INFO_BE_UAPSD BIT(3) +#define WMM_QOS_INFO_MAX_SP_LEN_MASK BITS(5, 6) +#define WMM_QOS_INFO_MAX_SP_ALL 0 +#define WMM_QOS_INFO_MAX_SP_2 BIT(5) +#define WMM_QOS_INFO_MAX_SP_4 BIT(6) +#define WMM_QOS_INFO_MAX_SP_6 BITS(5, 6) + +/* -- definitions for Max SP length field */ +#define WMM_MAX_SP_LENGTH_ALL 0 +#define WMM_MAX_SP_LENGTH_2 2 +#define WMM_MAX_SP_LENGTH_4 4 +#define WMM_MAX_SP_LENGTH_6 6 + +/* WMM-2.2.2 WMM ACI/AIFSN field */ +/* -- subfields in the ACI/AIFSN field */ +#define WMM_ACIAIFSN_AIFSN BITS(0, 3) +#define WMM_ACIAIFSN_ACM BIT(4) +#define WMM_ACIAIFSN_ACI BITS(5, 6) +#define WMM_ACIAIFSN_ACI_OFFSET 5 + +/* -- definitions for ACI field */ +#define WMM_ACI_AC_BE 0 +#define WMM_ACI_AC_BK BIT(5) +#define WMM_ACI_AC_VI BIT(6) +#define WMM_ACI_AC_VO BITS(5, 6) + +#define WMM_ACI(_AC) (_AC << WMM_ACIAIFSN_ACI_OFFSET) + +/* -- definitions for ECWmin/ECWmax field */ +#define WMM_ECW_WMIN_MASK BITS(0, 3) +#define WMM_ECW_WMAX_MASK BITS(4, 7) +#define WMM_ECW_WMAX_OFFSET 4 + +#define TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME 0 /* Unit: 64 us */ + +#define QM_RX_BA_ENTRY_MISS_TIMEOUT_MS (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +enum { + QM_DBG_CNT_00 = 0, + QM_DBG_CNT_01, + QM_DBG_CNT_02, + QM_DBG_CNT_03, + QM_DBG_CNT_04, + QM_DBG_CNT_05, + QM_DBG_CNT_06, + QM_DBG_CNT_07, + QM_DBG_CNT_08, + QM_DBG_CNT_09, + QM_DBG_CNT_10, + QM_DBG_CNT_11, + QM_DBG_CNT_12, + QM_DBG_CNT_13, + QM_DBG_CNT_14, + QM_DBG_CNT_15, + QM_DBG_CNT_16, + QM_DBG_CNT_17, + QM_DBG_CNT_18, + QM_DBG_CNT_19, + QM_DBG_CNT_20, + QM_DBG_CNT_21, + QM_DBG_CNT_22, + QM_DBG_CNT_23, + QM_DBG_CNT_24, + QM_DBG_CNT_25, + QM_DBG_CNT_26, + QM_DBG_CNT_27, + QM_DBG_CNT_28, + QM_DBG_CNT_29, + QM_DBG_CNT_30, + QM_DBG_CNT_31, + QM_DBG_CNT_NUM +}; + +/* Used for MAC TX */ +typedef enum _ENUM_MAC_TX_QUEUE_INDEX_T { + MAC_TX_QUEUE_AC0_INDEX = 0, + MAC_TX_QUEUE_AC1_INDEX, + MAC_TX_QUEUE_AC2_INDEX, + MAC_TX_QUEUE_AC3_INDEX, + MAC_TX_QUEUE_AC4_INDEX, + MAC_TX_QUEUE_AC5_INDEX, + MAC_TX_QUEUE_AC6_INDEX, + MAC_TX_QUEUE_BCN_INDEX, + MAC_TX_QUEUE_BMC_INDEX, + MAC_TX_QUEUE_NUM +} ENUM_MAC_TX_QUEUE_INDEX_T; + +typedef struct _RX_BA_ENTRY_T { + BOOLEAN fgIsValid; + QUE_T rReOrderQue; + UINT_16 u2WinStart; + UINT_16 u2WinEnd; + UINT_16 u2WinSize; + + /* For identifying the RX BA agreement */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; + + BOOLEAN fgIsWaitingForPktWithSsn; + + /* UINT_8 ucTxBufferSize; */ + /* BOOL fgIsAcConstrain; */ + /* BOOL fgIsBaEnabled; */ +} RX_BA_ENTRY_T, *P_RX_BA_ENTRY_T; + +/* The mailbox message (could be used for Host-To-Device or Device-To-Host Mailbox) */ +typedef struct _MAILBOX_MSG_T { + UINT_32 u4Msg[2]; /* [0]: D2HRM0R or H2DRM0R, [1]: D2HRM1R or H2DRM1R */ +} MAILBOX_MSG_T, *P_MAILBOX_MSG_T; + +/* Used for adaptively adjusting TC resources */ +typedef struct _TC_RESOURCE_CTRL_T { + /* TC0, TC1, TC2, TC3, TC5 */ + UINT_32 au4AverageQueLen[TC_NUM - 1]; +} TC_RESOURCE_CTRL_T, *P_TC_RESOURCE_CTRL_T; + +typedef struct _QUE_MGT_T { /* Queue Management Control Info */ + + /* Per-Type Queues: [0] BMCAST or UNKNOWN-STA packets */ + QUE_T arTxQueue[NUM_OF_PER_TYPE_TX_QUEUES]; + +#if 0 + /* For TX Scheduling */ + UINT_8 arRemainingTxOppt[NUM_OF_PER_STA_TX_QUEUES]; + UINT_8 arCurrentTxStaIndex[NUM_OF_PER_STA_TX_QUEUES]; + +#endif + + /* Reordering Queue Parameters */ + RX_BA_ENTRY_T arRxBaTable[CFG_NUM_OF_RX_BA_AGREEMENTS]; + + /* Current number of activated RX BA agreements <= CFG_NUM_OF_RX_BA_AGREEMENTS */ + UINT_8 ucRxBaCount; + +#if QM_TEST_MODE + UINT_32 u4PktCount; + P_ADAPTER_T prAdapter; + +#if QM_TEST_FAIR_FORWARDING + UINT_32 u4CurrentStaRecIndexToEnqueue; +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + /* The current TX count for a STA with respect to a TC index */ + UINT_32 au4ForwardCount[NUM_OF_PER_STA_TX_QUEUES]; + + /* The current serving STA with respect to a TC index */ + UINT_32 au4HeadStaRecIndex[NUM_OF_PER_STA_TX_QUEUES]; +#endif + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 au4AverageQueLen[TC_NUM]; + UINT_32 au4CurrentTcResource[TC_NUM]; + UINT_32 au4MinReservedTcResource[TC_NUM]; /* The minimum amount of resource no matter busy or idle */ + UINT_32 au4GuaranteedTcResource[TC_NUM]; /* The minimum amount of resource when extremely busy */ + + UINT_32 u4TimeToAdjustTcResource; + UINT_32 u4TimeToUpdateQueLen; + UINT_32 u4TxNumOfVi, u4TxNumOfVo; /* number of VI/VO packets */ + + /* Set to TRUE if the last TC adjustment has not been completely applied (i.e., waiting more TX-Done events + to align the TC quotas to the TC resource assignment) */ + BOOLEAN fgTcResourcePostAnnealing; + +#endif + +#if QM_DEBUG_COUNTER + UINT_32 au4QmDebugCounters[QM_DBG_CNT_NUM]; +#endif +#if QM_TC_RESOURCE_EMPTY_COUNTER + UINT_32 au4QmTcResourceEmptyCounter[NET_TYPE_NUM][TC_NUM]; + UINT_32 au4QmTcResourceBackCounter[TC_NUM]; + UINT_32 au4DequeueNoTcResourceCounter[TC_NUM]; + + UINT_32 au4ResourceUsedCounter[TC_NUM]; + + UINT_32 au4ResourceWantedCounter[TC_NUM]; + + UINT_32 u4EnqeueuCounter; + UINT_32 u4DequeueCounter; +#endif +} QUE_MGT_T, *P_QUE_MGT_T; + +typedef struct _EVENT_RX_ADDBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + + /* Fields that are present in the received ADDBA_REQ */ + UINT_8 ucDialogToken; /* Dialog Token chosen by the sender */ + UINT_16 u2BAParameterSet; /* BA policy, TID, buffer size */ + UINT_16 u2BATimeoutValue; + UINT_16 u2BAStartSeqCtrl; /* SSN */ + +} EVENT_RX_ADDBA_T, *P_EVENT_RX_ADDBA_T; + +typedef struct _EVENT_RX_DELBA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Fields not present in the received ADDBA_REQ */ + UINT_8 ucStaRecIdx; + UINT_8 ucTid; +} EVENT_RX_DELBA_T, *P_EVENT_RX_DELBA_T; + +typedef struct _EVENT_BSS_ABSENCE_PRESENCE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucNetTypeIdx; + BOOLEAN fgIsAbsent; + UINT_8 ucBssFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_BSS_ABSENCE_PRESENCE_T, *P_EVENT_BSS_ABSENCE_PRESENCE_T; + +typedef struct _EVENT_STA_CHANGE_PS_MODE_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + BOOLEAN fgIsInPs; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; +} EVENT_STA_CHANGE_PS_MODE_T, *P_EVENT_STA_CHANGE_PS_MODE_T; + +/* The free quota is used by PS only now */ +/* The event may be used by per STA flow conttrol in general */ +typedef struct _EVENT_STA_UPDATE_FREE_QUOTA_T { + /* Event header */ + UINT_16 u2Length; + UINT_16 u2Reserved1; /* Must be filled with 0x0001 (EVENT Packet) */ + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + /* Event Body */ + UINT_8 ucStaRecIdx; + UINT_8 ucUpdateMode; + UINT_8 ucFreeQuota; + UINT_8 aucReserved[1]; +} EVENT_STA_UPDATE_FREE_QUOTA_T, *P_EVENT_STA_UPDATE_FREE_QUOTA_T; + +/* WMM-2.2.1 WMM Information Element */ +typedef struct _IE_WMM_INFO_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucDummy[3]; /* Dummy for pack */ +} IE_WMM_INFO_T, *P_IE_WMM_INFO_T; + +/* WMM-2.2.2 WMM Parameter Element */ +typedef struct _IE_WMM_PARAM_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + + /* IE Body */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + + /* WMM IE Body */ + UINT_8 ucQosInfo; /* QoS Info field */ + UINT_8 ucReserved; + + /* AC Parameters */ + UINT_8 ucAciAifsn_BE; + UINT_8 ucEcw_BE; + UINT_8 aucTxopLimit_BE[2]; + + UINT_8 ucAciAifsn_BG; + UINT_8 ucEcw_BG; + UINT_8 aucTxopLimit_BG[2]; + + UINT_8 ucAciAifsn_VI; + UINT_8 ucEcw_VI; + UINT_8 aucTxopLimit_VI[2]; + + UINT_8 ucAciAifsn_VO; + UINT_8 ucEcw_VO; + UINT_8 aucTxopLimit_VO[2]; + +} IE_WMM_PARAM_T, *P_IE_WMM_PARAM_T; + +typedef struct _IE_WMM_TSPEC_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + /* WMM TSPEC body */ + UINT_8 aucTsInfo[3]; /* TS Info */ + UINT_8 aucTspecBodyPart[1]; /* Note: Utilize PARAM_QOS_TSPEC to fill (memory copy) */ +} IE_WMM_TSPEC_T, *P_IE_WMM_TSPEC_T; + +typedef struct _IE_WMM_HDR_T { + UINT_8 ucId; /* Element ID */ + UINT_8 ucLength; /* Length */ + UINT_8 aucOui[3]; /* OUI */ + UINT_8 ucOuiType; /* OUI Type */ + UINT_8 ucOuiSubtype; /* OUI Subtype */ + UINT_8 ucVersion; /* Version */ + UINT_8 aucBody[1]; /* IE body */ +} IE_WMM_HDR_T, *P_IE_WMM_HDR_T; + +typedef struct _AC_QUE_PARMS_T { + UINT_16 u2CWmin; /*!< CWmin */ + UINT_16 u2CWmax; /*!< CWmax */ + UINT_16 u2TxopLimit; /*!< TXOP limit */ + UINT_16 u2Aifsn; /*!< AIFSN */ + UINT_8 ucGuradTime; /*!< GuardTime for STOP/FLUSH. */ + BOOLEAN fgIsACMSet; +} AC_QUE_PARMS_T, *P_AC_QUE_PARMS_T; + +/* WMM ACI (AC index) */ +typedef enum _ENUM_WMM_ACI_T { + WMM_AC_BE_INDEX = 0, + WMM_AC_BK_INDEX, + WMM_AC_VI_INDEX, + WMM_AC_VO_INDEX, + WMM_AC_INDEX_NUM +} ENUM_WMM_ACI_T, *P_ENUM_WMM_ACI_T; + +/* Used for CMD Queue Operation */ +typedef enum _ENUM_FRAME_ACTION_T { + FRAME_ACTION_DROP_PKT = 0, + FRAME_ACTION_QUEUE_PKT, + FRAME_ACTION_TX_PKT, + FRAME_ACTION_NUM +} ENUM_FRAME_ACTION_T; + +typedef enum _ENUM_FRAME_TYPE_IN_CMD_Q_T { + FRAME_TYPE_802_1X = 0, + FRAME_TYPE_MMPDU, + FRAME_TYPE_NUM +} ENUM_FRAME_TYPE_IN_CMD_Q_T; + +typedef enum _ENUM_FREE_QUOTA_MODET_T { + FREE_QUOTA_UPDATE_MODE_INIT = 0, + FREE_QUOTA_UPDATE_MODE_OVERWRITE, + FREE_QUOTA_UPDATE_MODE_INCREASE, + FREE_QUOTA_UPDATE_MODE_DECREASE +} ENUM_FREE_QUOTA_MODET_T, *P_ENUM_FREE_QUOTA_MODET_T; + +typedef struct _CMD_UPDATE_WMM_PARMS_T { + AC_QUE_PARMS_T arACQueParms[AC_NUM]; + UINT_8 ucNetTypeIndex; + UINT_8 fgIsQBSS; + UINT_8 aucReserved[2]; +} CMD_UPDATE_WMM_PARMS_T, *P_CMD_UPDATE_WMM_PARMS_T; + +typedef struct _CMD_TX_AMPDU_T { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_TX_AMPDU_T, *P_CMD_TX_AMPDU_T; + +typedef struct _CMD_ADDBA_REJECT { + BOOLEAN fgEnable; + UINT_8 aucReserved[3]; +} CMD_ADDBA_REJECT_T, *P_CMD_ADDBA_REJECT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#define QM_TX_SET_NEXT_MSDU_INFO(_prMsduInfoPreceding, _prMsduInfoNext) \ + ((((_prMsduInfoPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prMsduInfoNext)) + +#define QM_TX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) + +#define QM_TX_GET_NEXT_MSDU_INFO(_prMsduInfo) \ + ((P_MSDU_INFO_T)(((_prMsduInfo)->rQueEntry).prNext)) + +#define QM_RX_SET_NEXT_SW_RFB(_prSwRfbPreceding, _prSwRfbNext) \ + ((((_prSwRfbPreceding)->rQueEntry).prNext) = (P_QUE_ENTRY_T)(_prSwRfbNext)) + +#define QM_RX_GET_NEXT_SW_RFB(_prSwRfb) \ + ((P_SW_RFB_T)(((_prSwRfb)->rQueEntry).prNext)) + +#if 0 +#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ + ((((_ucIndex) != STA_REC_INDEX_BMCAST) && ((_ucIndex) != STA_REC_INDEX_NOT_FOUND)) ?\ + &(_prAdapter->arStaRec[_ucIndex]) : NULL) +#endif + +#define QM_GET_STA_REC_PTR_FROM_INDEX(_prAdapter, _ucIndex) \ + cnmGetStaRecByIndex(_prAdapter, _ucIndex) + +#define QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(\ + _prMsduInfo,\ + _ucTC,\ + _ucPacketType,\ + _ucFormatID,\ + _fgIs802_1x,\ + _fgIs802_11,\ + _u2PalLLH,\ + _u2AclSN,\ + _ucPsForwardingType,\ + _ucPsSessionID\ + ) \ +{\ + ASSERT(_prMsduInfo);\ + (_prMsduInfo)->ucTC = (_ucTC);\ + (_prMsduInfo)->ucPacketType = (_ucPacketType);\ + (_prMsduInfo)->ucFormatID = (_ucFormatID);\ + (_prMsduInfo)->fgIs802_1x = (_fgIs802_1x);\ + (_prMsduInfo)->fgIs802_11 = (_fgIs802_11);\ + (_prMsduInfo)->u2PalLLH = (_u2PalLLH);\ + (_prMsduInfo)->u2AclSN = (_u2AclSN);\ + (_prMsduInfo)->ucPsForwardingType = (_ucPsForwardingType);\ + (_prMsduInfo)->ucPsSessionID = (_ucPsSessionID);\ + (_prMsduInfo)->fgIsBurstEnd = (FALSE);\ +} + +#define QM_INIT_STA_REC(\ + _prStaRec,\ + _fgIsValid,\ + _fgIsQoS,\ + _pucMacAddr\ + )\ +{\ + ASSERT(_prStaRec);\ + (_prStaRec)->fgIsValid = (_fgIsValid);\ + (_prStaRec)->fgIsQoS = (_fgIsQoS);\ + (_prStaRec)->fgIsInPS = FALSE; \ + (_prStaRec)->ucPsSessionID = 0xFF;\ + COPY_MAC_ADDR((_prStaRec)->aucMacAddr, (_pucMacAddr));\ +} + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +#define QM_GET_TX_QUEUE_LEN(_prAdapter, _u4QueIdx) \ + ((_prAdapter->rQM.au4AverageQueLen[(_u4QueIdx)] >> QM_QUE_LEN_MOVING_AVE_FACTOR)) +#endif + +#define WMM_IE_OUI_TYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiType) +#define WMM_IE_OUI_SUBTYPE(fp) (((P_IE_WMM_HDR_T)(fp))->ucOuiSubtype) +#define WMM_IE_OUI(fp) (((P_IE_WMM_HDR_T)(fp))->aucOui) + +#if QM_DEBUG_COUNTER +#define QM_DBG_CNT_INC(_prQM, _index) { (_prQM)->au4QmDebugCounters[(_index)]++; } +#else +#define QM_DBG_CNT_INC(_prQM, _index) {} +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Queue Management and STA_REC Initialization */ +/*----------------------------------------------------------------------------*/ + +VOID qmInit(IN P_ADAPTER_T prAdapter); + +#if QM_TEST_MODE +VOID qmTestCases(IN P_ADAPTER_T prAdapter); +#endif + +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); + +/*----------------------------------------------------------------------------*/ +/* TX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter); + +P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx); + +P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus); + +VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter); + +VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ + +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter); + +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter); + +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); + +VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); + +VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue); + +VOID +qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +BOOLEAN +qmPopOutDueToFallWithin(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout); + +VOID qmPopOutDueToFallAhead(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue); + +VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg); + +BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater); + +VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid); + +BOOLEAN +qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize); + +VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost); + +VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +VOID +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride); + +VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams); + +VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec); + +/* Utility function: for deciding STA-REC index */ +UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +UINT_32 +mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, + UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf); + +VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode); + +VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType); + +VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength); + +VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent); + +VOID +qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone); + +VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter); + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); +VOID qmResetArpDetect(VOID); +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); +#endif +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUE_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h new file mode 100644 index 0000000000000..2804b0387f5f0 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic/wlan_def.h @@ -0,0 +1,1010 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic/wlan_def.h#1 +*/ + +/*! \file "wlan_def.h" + \brief This file includes the basic definition of WLAN + +*/ + +/* +** Log: wlan_def.h +** +** 09 02 2013 cp.wu +** add path to handle reassociation request + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 wh.su + * [WCXRP00000806] [MT6620 Wi-Fi][Driver] Move the WPA/RSN IE and WAPI IE structure to mac.h and let the sw + * structure not align at byte + * Move the WAPI/RSN IE to mac.h and SW structure not align to byte, + * Notice needed update P2P.ko. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 17 2011 yuche.tsai + * NULL + * Resize the Secondary Device Type array when WiFi Direct is enabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Add new station type MACRO. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 11 2010 kevin.huang + * [WCXRP00000068] [MT6620 Wi-Fi][Driver][FW] Fix STA RECORD sync issue and remove unused code + * Update ENUM_STA_ROLE_INDEX_T by using a fixed base value + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by + * ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 14 2010 chinghwa.yu + * NULL + * Update OP_MODE_BOW and include bow_fsm.h. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * Change P2P Descriptor List to a pointer and allocate it dynamically to avoid structure corrupt by BssDescriptor free. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Add a pointer in BSS Descriptor for P2P Descriptor. + * + * 08 11 2010 yuche.tsai + * NULL + * Add an Interface in BSS Descriptor. + * + * 08 05 2010 yuche.tsai + * NULL + * Modify data structure for P2P Scan result. + * + * 07 26 2010 yuche.tsai + * + * Add an operation mode for P2P device. + * + * 07 23 2010 cp.wu + * + * P2P/RSN/WAPI IEs need to be declared with compact structure. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, other request will be directly + * dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Add P2P present boolean flag in BSS & Pre-BSS descriptor. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * move bss related data types to wlan_def.h to avoid recursive dependency. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:16:40 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_DEF_H +#define _WLAN_DEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* disconnect reason */ +#define DISCONNECT_REASON_CODE_RESERVED 0 +#define DISCONNECT_REASON_CODE_RADIO_LOST 1 +#define DISCONNECT_REASON_CODE_DEAUTHENTICATED 2 +#define DISCONNECT_REASON_CODE_DISASSOCIATED 3 +#define DISCONNECT_REASON_CODE_NEW_CONNECTION 4 +#define DISCONNECT_REASON_CODE_REASSOCIATION 5 +#define DISCONNECT_REASON_CODE_ROAMING 6 + +/* The rate definitions */ +#define TX_MODE_CCK 0x00 +#define TX_MODE_OFDM 0x40 +#define TX_MODE_HT_MM 0x80 +#define TX_MODE_HT_GF 0xC0 + +#define RATE_CCK_SHORT_PREAMBLE 0x10 +#define RATE_OFDM 0x20 + +#define PHY_RATE_1M 0x0 +#define PHY_RATE_2M 0x1 +#define PHY_RATE_5_5M 0x2 +#define PHY_RATE_11M 0x3 +#define PHY_RATE_6M 0xB +#define PHY_RATE_9M 0xF +#define PHY_RATE_12M 0xA +#define PHY_RATE_18M 0xE +#define PHY_RATE_24M 0x9 +#define PHY_RATE_36M 0xD +#define PHY_RATE_48M 0x8 +#define PHY_RATE_54M 0xC +#define PHY_RATE_MCS0 0x0 +#define PHY_RATE_MCS1 0x1 +#define PHY_RATE_MCS2 0x2 +#define PHY_RATE_MCS3 0x3 +#define PHY_RATE_MCS4 0x4 +#define PHY_RATE_MCS5 0x5 +#define PHY_RATE_MCS6 0x6 +#define PHY_RATE_MCS7 0x7 +#define PHY_RATE_MCS32 0x20 + +#define RATE_CCK_1M_LONG (TX_MODE_CCK | PHY_RATE_1M) +#define RATE_CCK_2M_LONG (TX_MODE_CCK | PHY_RATE_2M) +#define RATE_CCK_5_5M_LONG (TX_MODE_CCK | PHY_RATE_5_5M) +#define RATE_CCK_11M_LONG (TX_MODE_CCK | PHY_RATE_11M) +#define RATE_CCK_2M_SHORT (TX_MODE_CCK | PHY_RATE_2M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_5_5M_SHORT (TX_MODE_CCK | PHY_RATE_5_5M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_CCK_11M_SHORT (TX_MODE_CCK | PHY_RATE_11M | RATE_CCK_SHORT_PREAMBLE) +#define RATE_OFDM_6M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_6M) +#define RATE_OFDM_9M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_9M) +#define RATE_OFDM_12M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_12M) +#define RATE_OFDM_18M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_18M) +#define RATE_OFDM_24M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_24M) +#define RATE_OFDM_36M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_36M) +#define RATE_OFDM_48M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_48M) +#define RATE_OFDM_54M (TX_MODE_OFDM | RATE_OFDM | PHY_RATE_54M) + +#define RATE_MM_MCS_0 (TX_MODE_HT_MM | PHY_RATE_MCS0) +#define RATE_MM_MCS_1 (TX_MODE_HT_MM | PHY_RATE_MCS1) +#define RATE_MM_MCS_2 (TX_MODE_HT_MM | PHY_RATE_MCS2) +#define RATE_MM_MCS_3 (TX_MODE_HT_MM | PHY_RATE_MCS3) +#define RATE_MM_MCS_4 (TX_MODE_HT_MM | PHY_RATE_MCS4) +#define RATE_MM_MCS_5 (TX_MODE_HT_MM | PHY_RATE_MCS5) +#define RATE_MM_MCS_6 (TX_MODE_HT_MM | PHY_RATE_MCS6) +#define RATE_MM_MCS_7 (TX_MODE_HT_MM | PHY_RATE_MCS7) +#define RATE_MM_MCS_32 (TX_MODE_HT_MM | PHY_RATE_MCS32) + +#define RATE_GF_MCS_0 (TX_MODE_HT_GF | PHY_RATE_MCS0) +#define RATE_GF_MCS_1 (TX_MODE_HT_GF | PHY_RATE_MCS1) +#define RATE_GF_MCS_2 (TX_MODE_HT_GF | PHY_RATE_MCS2) +#define RATE_GF_MCS_3 (TX_MODE_HT_GF | PHY_RATE_MCS3) +#define RATE_GF_MCS_4 (TX_MODE_HT_GF | PHY_RATE_MCS4) +#define RATE_GF_MCS_5 (TX_MODE_HT_GF | PHY_RATE_MCS5) +#define RATE_GF_MCS_6 (TX_MODE_HT_GF | PHY_RATE_MCS6) +#define RATE_GF_MCS_7 (TX_MODE_HT_GF | PHY_RATE_MCS7) +#define RATE_GF_MCS_32 (TX_MODE_HT_GF | PHY_RATE_MCS32) + +#define RATE_TX_MODE_MASK BITS(6, 7) +#define RATE_TX_MODE_OFFSET 6 +#define RATE_CODE_GET_TX_MODE(_ucRateCode) ((_ucRateCode & RATE_TX_MODE_MASK) >> RATE_TX_MODE_OFFSET) +#define RATE_PHY_RATE_MASK BITS(0, 5) +#define RATE_PHY_RATE_OFFSET 0 +#define RATE_CODE_GET_PHY_RATE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_MASK) >> RATE_PHY_RATE_OFFSET) +#define RATE_PHY_RATE_SHORT_PREAMBLE BIT(4) +#define RATE_CODE_IS_SHORT_PREAMBLE(_ucRateCode) ((_ucRateCode & RATE_PHY_RATE_SHORT_PREAMBLE)?TRUE:FALSE) + +#define CHNL_LIST_SZ_2G 14 +#define CHNL_LIST_SZ_5G 14 + +/*! CNM(STA_RECORD_T) related definition */ +#define CFG_STA_REC_NUM 20 + +/* PHY TYPE bit definitions */ +#define PHY_TYPE_BIT_HR_DSSS BIT(PHY_TYPE_HR_DSSS_INDEX) /* HR/DSSS PHY (clause 18) */ +#define PHY_TYPE_BIT_ERP BIT(PHY_TYPE_ERP_INDEX) /* ERP PHY (clause 19) */ +#define PHY_TYPE_BIT_OFDM BIT(PHY_TYPE_OFDM_INDEX) /* OFDM 5 GHz PHY (clause 17) */ +#define PHY_TYPE_BIT_HT BIT(PHY_TYPE_HT_INDEX) /* HT PHY (clause 20) */ + +/* PHY TYPE set definitions */ +#define PHY_TYPE_SET_802_11ABGN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11BGN (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11GN (PHY_TYPE_BIT_ERP | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11AN (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HT) + +#define PHY_TYPE_SET_802_11ABG (PHY_TYPE_BIT_OFDM | \ + PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11BG (PHY_TYPE_BIT_HR_DSSS | \ + PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11A (PHY_TYPE_BIT_OFDM) + +#define PHY_TYPE_SET_802_11G (PHY_TYPE_BIT_ERP) + +#define PHY_TYPE_SET_802_11B (PHY_TYPE_BIT_HR_DSSS) + +#define PHY_TYPE_SET_802_11N (PHY_TYPE_BIT_HT) + +/* Rate set bit definitions */ +#define RATE_SET_BIT_1M BIT(RATE_1M_INDEX) /* Bit 0: 1M */ +#define RATE_SET_BIT_2M BIT(RATE_2M_INDEX) /* Bit 1: 2M */ +#define RATE_SET_BIT_5_5M BIT(RATE_5_5M_INDEX) /* Bit 2: 5.5M */ +#define RATE_SET_BIT_11M BIT(RATE_11M_INDEX) /* Bit 3: 11M */ +#define RATE_SET_BIT_22M BIT(RATE_22M_INDEX) /* Bit 4: 22M */ +#define RATE_SET_BIT_33M BIT(RATE_33M_INDEX) /* Bit 5: 33M */ +#define RATE_SET_BIT_6M BIT(RATE_6M_INDEX) /* Bit 6: 6M */ +#define RATE_SET_BIT_9M BIT(RATE_9M_INDEX) /* Bit 7: 9M */ +#define RATE_SET_BIT_12M BIT(RATE_12M_INDEX) /* Bit 8: 12M */ +#define RATE_SET_BIT_18M BIT(RATE_18M_INDEX) /* Bit 9: 18M */ +#define RATE_SET_BIT_24M BIT(RATE_24M_INDEX) /* Bit 10: 24M */ +#define RATE_SET_BIT_36M BIT(RATE_36M_INDEX) /* Bit 11: 36M */ +#define RATE_SET_BIT_48M BIT(RATE_48M_INDEX) /* Bit 12: 48M */ +#define RATE_SET_BIT_54M BIT(RATE_54M_INDEX) /* Bit 13: 54M */ +#define RATE_SET_BIT_HT_PHY BIT(RATE_HT_PHY_INDEX) /* Bit 14: BSS Selector */ + +/* Rate set definitions */ +#define RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_18M | \ + RATE_SET_BIT_24M | \ + RATE_SET_BIT_36M | \ + RATE_SET_BIT_48M | \ + RATE_SET_BIT_54M) + +#define RATE_SET_HT (RATE_SET_ERP) +/* #define RATE_SET_HT (RATE_SET_ERP | RATE_SET_BIT_HT_PHY) *//* NOTE(Kevin): TBD */ + +#define RATE_SET_ALL_ABG RATE_SET_ERP + +#define BASIC_RATE_SET_HR_DSSS (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M) + +#define BASIC_RATE_SET_HR_DSSS_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M) + +#define BASIC_RATE_SET_ERP (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_OFDM (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define BASIC_RATE_SET_ERP_P2P (RATE_SET_BIT_6M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_100 RATE_SET_ALL_ABG + +#define INITIAL_RATE_SET_RCPI_80 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M | \ + RATE_SET_BIT_9M | \ + RATE_SET_BIT_12M | \ + RATE_SET_BIT_24M) + +#define INITIAL_RATE_SET_RCPI_60 (RATE_SET_BIT_1M | \ + RATE_SET_BIT_2M | \ + RATE_SET_BIT_5_5M | \ + RATE_SET_BIT_11M | \ + RATE_SET_BIT_6M) + +#define INITIAL_RATE_SET(_rcpi) (INITIAL_RATE_SET_ ## _rcpi) + +#define RCPI_100 100 /* -60 dBm */ +#define RCPI_80 80 /* -70 dBm */ +#define RCPI_60 60 /* -80 dBm */ + +/* The number of RCPI records used to calculate their average value */ +#define MAX_NUM_RCPI_RECORDS 10 + +/* The number of RCPI records used to calculate their average value */ +#define NO_RCPI_RECORDS -128 +#define MAX_RCPI_DBM 0 +#define MIN_RCPI_DBM -100 + +#define MAC_TX_RESERVED_FIELD 0 /* NOTE(Kevin): Should defined in tx.h */ + +#define MAX_ASSOC_ID (CFG_STA_REC_NUM) /* Available AID: 1 ~ 20(STA_REC_NUM) */ + +#define MAX_DEAUTH_INFO_COUNT 4 /* NOTE(Kevin): Used in auth.c */ +#define MIN_DEAUTH_INTERVAL_MSEC 500 /* The minimum interval if continuously send Deauth Frame */ + +/* Authentication Type */ +#define AUTH_TYPE_OPEN_SYSTEM BIT(AUTH_ALGORITHM_NUM_OPEN_SYSTEM) +#define AUTH_TYPE_SHARED_KEY BIT(AUTH_ALGORITHM_NUM_SHARED_KEY) +#define AUTH_TYPE_FAST_BSS_TRANSITION BIT(AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION) + +/* Authentication Retry Limit */ +#define TX_AUTH_ASSOCI_RETRY_LIMIT 2 +#define TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING 1 + +/* WMM-2.2.1 WMM Information Element */ +#define ELEM_MAX_LEN_WMM_INFO 7 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_16 PHY_TYPE, *P_PHY_TYPE; +typedef UINT_8 RCPI, *P_RCPI; +typedef UINT_8 ALC_VAL, *P_ALC_VAL; + +typedef enum _ENUM_HW_BSSID_T { + BSSID_0 = 0, + BSSID_1, + BSSID_NUM +} ENUM_HW_BSSID_T; + +typedef enum _ENUM_HW_MAC_ADDR_T { + MAC_ADDR_0 = 0, + MAC_ADDR_1, + MAC_ADDR_NUM +} ENUM_HW_MAC_ADDR_T; + +typedef enum _ENUM_HW_OP_MODE_T { + HW_OP_MODE_STA = 0, + HW_OP_MODE_AP, + HW_OP_MODE_ADHOC, + HW_OP_MODE_NUM +} ENUM_HW_OP_MODE_T; + +typedef enum _ENUM_TSF_T { + ENUM_LOCAL_TSF_0, + ENUM_LOCAL_TSF_1, + ENUM_LOCAL_TSF_NUM +} ENUM_LOCAL_TSF_T, *P_ENUM_LOCAL_TSF_T; + +typedef enum _HAL_TS_HW_UPDATE_MODE { + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME, + HAL_TSF_HW_UPDATE_BY_TICK_ONLY, + HAL_TSF_HW_UPDATE_BY_RECEIVED_FRAME_ONLY, + HAL_TSF_HW_UPDATE_BY_TICK_AND_RECEIVED_FRAME_AD_HOC +} HAL_TSF_HW_UPDATE_MODE; + +typedef enum _ENUM_AC_T { + AC0 = 0, + AC1, + AC2, + AC3, + AC_NUM +} ENUM_AC_T, *P_ENUM_AC_T; + +/* The Type of Network been activated */ +typedef enum _ENUM_NETWORK_TYPE_INDEX_T { + NETWORK_TYPE_AIS_INDEX = 0, + NETWORK_TYPE_P2P_INDEX, + NETWORK_TYPE_BOW_INDEX, + NETWORK_TYPE_INDEX_NUM +} ENUM_NETWORK_TYPE_INDEX_T; + +/* The Type of STA Type. */ +typedef enum _ENUM_STA_TYPE_INDEX_T { + STA_TYPE_LEGACY_INDEX = 0, + STA_TYPE_P2P_INDEX, + STA_TYPE_BOW_INDEX, + STA_TYPE_INDEX_NUM +} ENUM_STA_TYPE_INDEX_T; + +#define STA_ROLE_BASE_INDEX 4 + +typedef enum _ENUM_STA_ROLE_INDEX_T { + STA_ROLE_ADHOC_INDEX = STA_ROLE_BASE_INDEX, /* 4 */ + STA_ROLE_CLIENT_INDEX, + STA_ROLE_AP_INDEX, + STA_ROLE_TDLS_INDEX, + STA_ROLE_DLS_INDEX /* Note: need to extend P_CMD_UPDATE_STA_RECORD_T */ +} ENUM_STA_ROLE_INDEX_T; + +/* The Power State of a specific Network */ +typedef enum _ENUM_PWR_STATE_T { + PWR_STATE_IDLE = 0, + PWR_STATE_ACTIVE, + PWR_STATE_PS, + PWR_STATE_NUM +} ENUM_PWR_STATE_T; + +typedef enum _ENUM_PHY_TYPE_INDEX_T { + /* PHY_TYPE_DSSS_INDEX, *//* DSSS PHY (clause 15) -- Not used anymore */ + PHY_TYPE_HR_DSSS_INDEX = 0, /* HR/DSSS PHY (clause 18) */ + PHY_TYPE_ERP_INDEX, /* ERP PHY (clause 19) */ + PHY_TYPE_ERP_P2P_INDEX, /* ERP PHY (clause 19) w/o HR/DSSS */ + PHY_TYPE_OFDM_INDEX, /* OFDM 5 GHz PHY (clause 17) */ + PHY_TYPE_HT_INDEX, /* HT PHY (clause 20) */ + PHY_TYPE_INDEX_NUM /* 5 */ +} ENUM_PHY_TYPE_INDEX_T, *P_ENUM_PHY_TYPE_INDEX_T; + +typedef enum _ENUM_ACPI_STATE_T { + ACPI_STATE_D0 = 0, + ACPI_STATE_D1, + ACPI_STATE_D2, + ACPI_STATE_D3 +} ENUM_ACPI_STATE_T; + +/* The operation mode of a specific Network */ +typedef enum _ENUM_OP_MODE_T { + OP_MODE_INFRASTRUCTURE = 0, /* Infrastructure/GC */ + OP_MODE_IBSS, /* AdHoc */ + OP_MODE_ACCESS_POINT, /* For GO */ + OP_MODE_P2P_DEVICE, /* P2P Device */ + OP_MODE_BOW, + OP_MODE_NUM +} ENUM_OP_MODE_T, *P_ENUM_OP_MODE_T; + +typedef enum _ENUM_CHNL_EXT_T { + CHNL_EXT_SCN = 0, + CHNL_EXT_SCA = 1, + CHNL_EXT_RES = 2, + CHNL_EXT_SCB = 3 +} ENUM_CHNL_EXT_T, *P_ENUM_CHNL_EXT_T; + +/* This starting freq of the band is unit of kHz */ +typedef enum _ENUM_BAND_T { + BAND_NULL, + BAND_2G4, + BAND_5G, + BAND_NUM +} ENUM_BAND_T, *P_ENUM_BAND_T; + +/* Provide supported channel list to other components in array format */ +typedef struct _RF_CHANNEL_INFO_T { + ENUM_BAND_T eBand; + UINT_8 ucChannelNum; +} RF_CHANNEL_INFO_T, *P_RF_CHANNEL_INFO_T; + +typedef enum _ENUM_RATE_INDEX_T { + RATE_1M_INDEX = 0, /* 1M */ + RATE_2M_INDEX, /* 2M */ + RATE_5_5M_INDEX, /* 5.5M */ + RATE_11M_INDEX, /* 11M */ + RATE_22M_INDEX, /* 22M */ + RATE_33M_INDEX, /* 33M */ + RATE_6M_INDEX, /* 6M */ + RATE_9M_INDEX, /* 9M */ + RATE_12M_INDEX, /* 12M */ + RATE_18M_INDEX, /* 18M */ + RATE_24M_INDEX, /* 24M */ + RATE_36M_INDEX, /* 36M */ + RATE_48M_INDEX, /* 48M */ + RATE_54M_INDEX, /* 54M */ + RATE_HT_PHY_INDEX, /* BSS Selector - HT PHY */ + RATE_NUM /* 15 */ +} ENUM_RATE_INDEX_T, *P_ENUM_RATE_INDEX_T; + +typedef enum _ENUM_HT_RATE_INDEX_T { + HT_RATE_MCS0_INDEX = 0, + HT_RATE_MCS1_INDEX, + HT_RATE_MCS2_INDEX, + HT_RATE_MCS3_INDEX, + HT_RATE_MCS4_INDEX, + HT_RATE_MCS5_INDEX, + HT_RATE_MCS6_INDEX, + HT_RATE_MCS7_INDEX, + HT_RATE_MCS32_INDEX, + HT_RATE_NUM /* 9 */ +} ENUM_HT_RATE_INDEX_T, *P_ENUM_HT_RATE_INDEX_T; + +typedef enum _ENUM_PREMABLE_OPTION_T { + PREAMBLE_DEFAULT_LONG_NONE = 0, /* LONG for PHY_TYPE_HR_DSSS, NONE for PHY_TYPE_OFDM */ + PREAMBLE_OPTION_SHORT, /* SHORT mandatory for PHY_TYPE_ERP, SHORT option for PHY_TYPE_HR_DSSS */ + PREAMBLE_HT_MIXED_MODE, + PREAMBLE_HT_GREEN_FIELD, + PREAMBLE_OPTION_NUM +} ENUM_PREMABLE_OPTION_T, *P_ENUM_PREMABLE_OPTION_T; + +typedef enum _ENUM_CHANNEL_WIDTH_T { + CW_20_40MHZ = 0, + CW_80MHZ = 1, + CW_160MHZ = 2, + CW_80P80MHZ = 3 +} ENUM_CHANNEL_WIDTH_T, *P_ENUM_CHANNEL_WIDTH_P; + +typedef enum _ENUM_MODULATION_SYSTEM_T { + MODULATION_SYSTEM_CCK = 0, + MODULATION_SYSTEM_OFDM, + MODULATION_SYSTEM_HT20, + MODULATION_SYSTEM_HT40, + MODULATION_SYSTEM_NUM +} ENUM_MODULATION_SYSTEM_T, *P_ENUM_MODULATION_SYSTEM_T; + +typedef enum _ENUM_MODULATION_TYPE_T { + MODULATION_TYPE_CCK_BPSK = 0, + MODULATION_TYPE_QPSK, + MODULATION_TYPE_16QAM, + MODULATION_TYPE_64QAM, + MODULATION_TYPE_NUM +} ENUM_MODULATION_TYPE_T, *P_ENUM_MODULATION_TYPE_T; + +typedef enum _ENUM_PS_FORWARDING_TYPE_T { + PS_FORWARDING_TYPE_NON_PS = 0, + PS_FORWARDING_TYPE_DELIVERY_ENABLED, + PS_FORWARDING_TYPE_NON_DELIVERY_ENABLED, + PS_FORWARDING_MORE_DATA_ENABLED, + PS_FORWARDING_TYPE_NUM +} ENUM_PS_FORWARDING_TYPE_T, *P_ENUM_PS_FORWARDING_TYPE_T; + +typedef struct _DEAUTH_INFO_T { + UINT_8 aucRxAddr[MAC_ADDR_LEN]; + OS_SYSTIME rLastSendTime; +} DEAUTH_INFO_T, *P_DEAUTH_INFO_T; + +/*----------------------------------------------------------------------------*/ +/* Information Element (IE) handlers */ +/*----------------------------------------------------------------------------*/ +typedef VOID(*PFN_APPEND_IE_FUNC) (P_ADAPTER_T, P_MSDU_INFO_T); +typedef VOID(*PFN_HANDLE_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T); +typedef VOID(*PFN_VERIFY_IE_FUNC) (P_ADAPTER_T, P_SW_RFB_T, P_IE_HDR_T, PUINT_16); +typedef UINT_32(*PFN_CALCULATE_VAR_IE_LEN_FUNC) (P_ADAPTER_T, ENUM_NETWORK_TYPE_INDEX_T, P_STA_RECORD_T); + +typedef struct _APPEND_IE_ENTRY_T { + UINT_16 u2EstimatedIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_IE_ENTRY_T, *P_APPEND_IE_ENTRY_T; + +typedef struct _APPEND_VAR_IE_ENTRY_T { + UINT_16 u2EstimatedFixedIELen; /* For Fixed Length */ + PFN_CALCULATE_VAR_IE_LEN_FUNC pfnCalculateVariableIELen; + PFN_APPEND_IE_FUNC pfnAppendIE; +} APPEND_VAR_IE_ENTRY_T, *P_APPEND_VAR_IE_ENTRY_T; + +typedef struct _HANDLE_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_HANDLE_IE_FUNC pfnHandleIE; +} HANDLE_IE_ENTRY_T, *P_HANDLE_IE_ENTRY_T; + +typedef struct _VERIFY_IE_ENTRY_T { + UINT_8 ucElemID; + PFN_VERIFY_IE_FUNC pfnVarifyIE; +} VERIFY_IE_ENTRY_T, *P_VERIFY_IE_ENTRY_T; + +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration */ +/*----------------------------------------------------------------------------*/ +typedef enum _ENUM_PARAM_CONNECTION_POLICY_T { + CONNECT_BY_SSID_BEST_RSSI = 0, + CONNECT_BY_SSID_GOOD_RSSI_MIN_CH_LOAD, + CONNECT_BY_SSID_ANY, /* NOTE(Kevin): Needed by WHQL */ + CONNECT_BY_BSSID, + CONNECT_BY_CUSTOMIZED_RULE /* NOTE(Kevin): TBD */ +} ENUM_PARAM_CONNECTION_POLICY_T, *P_ENUM_PARAM_CONNECTION_POLICY_T; + +typedef enum _ENUM_PARAM_PREAMBLE_TYPE_T { + PREAMBLE_TYPE_LONG = 0, + PREAMBLE_TYPE_SHORT, + PREAMBLE_TYPE_AUTO /*!< Try preamble short first, if fail tray preamble long. */ +} ENUM_PARAM_PREAMBLE_TYPE_T, *P_ENUM_PARAM_PREAMBLE_TYPE_T; + +/* This is enum defined for user to select a phy config listed in combo box */ +typedef enum _ENUM_PARAM_PHY_CONFIG_T { + /*!< Can associated with 802.11abg AP but without n capability, Scan dual band. */ + PHY_CONFIG_802_11ABG = 0, + PHY_CONFIG_802_11BG, /*!< Can associated with 802_11bg AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11G, /*!< Can associated with 802_11g only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11A, /*!< Can associated with 802_11a only AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11B, /*!< Can associated with 802_11b only AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11ABGN, /*!< Can associated with 802.11abgn AP, Scan dual band. */ + PHY_CONFIG_802_11BGN, /*!< Can associated with 802_11bgn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_802_11AN, /*!< Can associated with 802_11an AP, Scan single band and not report 2.4G BSSs. */ + PHY_CONFIG_802_11GN, /*!< Can associated with 802_11gn AP, Scan single band and not report 5G BSSs. */ + PHY_CONFIG_NUM /* 9 */ +} ENUM_PARAM_PHY_CONFIG_T, *P_ENUM_PARAM_PHY_CONFIG_T; + +/* This is enum defined for user to select an AP Mode */ +typedef enum _ENUM_PARAM_AP_MODE_T { + AP_MODE_11B = 0, /*!< Create 11b BSS if we support 802.11abg/802.11bg. */ + AP_MODE_MIXED_11BG, /*!< Create 11bg mixed BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G, /*!< Create 11g only BSS if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11G_P2P, /*!< Create 11g only BSS for P2P if we support 802.11abg/802.11bg/802.11g. */ + AP_MODE_11A, /*!< Create 11a only BSS if we support 802.11abg. */ + AP_MODE_NUM /* 4 */ +} ENUM_PARAM_AP_MODE_T, *P_ENUM_PARAM_AP_MODE_T; + +/* Masks for determining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define NETWORK_TYPE_AIS_MASK BIT(NETWORK_TYPE_AIS_INDEX) +#define NETWORK_TYPE_P2P_MASK BIT(NETWORK_TYPE_P2P_INDEX) +#define NETWORK_TYPE_BOW_MASK BIT(NETWORK_TYPE_BOW_INDEX) +#define STA_TYPE_LEGACY_MASK BIT(STA_TYPE_LEGACY_INDEX) +#define STA_TYPE_P2P_MASK BIT(STA_TYPE_P2P_INDEX) +#define STA_TYPE_BOW_MASK BIT(STA_TYPE_BOW_INDEX) +#define STA_TYPE_ADHOC_MASK BIT(STA_ROLE_ADHOC_INDEX) +#define STA_TYPE_CLIENT_MASK BIT(STA_ROLE_CLIENT_INDEX) +#define STA_TYPE_AP_MASK BIT(STA_ROLE_AP_INDEX) +#define STA_TYPE_DLS_MASK BIT(STA_ROLE_DLS_INDEX) +#define STA_TYPE_TDLS_MASK BIT(STA_ROLE_TDLS_INDEX) + +/* Macros for obtaining the Network Type or the Station Role, given the ENUM_STA_TYPE_T */ +#define IS_STA_IN_AIS(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) +#define IS_STA_IN_P2P(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) +#define IS_STA_IN_BOW(_prStaRec) ((_prStaRec)->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) +#define IS_STA_LEGACY_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_LEGACY_MASK) +#define IS_STA_P2P_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_P2P_MASK) +#define IS_STA_BOW_TYPE(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_BOW_MASK) +#define IS_ADHOC_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_ADHOC_MASK) +#define IS_CLIENT_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_CLIENT_MASK) +#define IS_AP_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_AP_MASK) +#define IS_DLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_DLS_MASK) +#define IS_TDLS_STA(_prStaRec) ((_prStaRec->eStaType) & STA_TYPE_TDLS_MASK) + +/* The ENUM_STA_TYPE_T accounts for ENUM_NETWORK_TYPE_T and ENUM_STA_ROLE_INDEX_T. + * * It is a merged version of Network Type and STA Role. + * */ +typedef enum _ENUM_STA_TYPE_T { + STA_TYPE_LEGACY_AP = (STA_TYPE_LEGACY_MASK | STA_TYPE_AP_MASK), + STA_TYPE_LEGACY_CLIENT = (STA_TYPE_LEGACY_MASK | STA_TYPE_CLIENT_MASK), + STA_TYPE_ADHOC_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_ADHOC_MASK), +#if CFG_ENABLE_WIFI_DIRECT + STA_TYPE_P2P_GO = (STA_TYPE_P2P_MASK | STA_TYPE_AP_MASK), + STA_TYPE_P2P_GC = (STA_TYPE_P2P_MASK | STA_TYPE_CLIENT_MASK), +#endif +#if CFG_ENABLE_BT_OVER_WIFI + STA_TYPE_BOW_AP = (STA_TYPE_BOW_MASK | STA_TYPE_AP_MASK), + STA_TYPE_BOW_CLIENT = (STA_TYPE_BOW_MASK | STA_TYPE_CLIENT_MASK), +#endif + STA_TYPE_DLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_DLS_MASK), + STA_TYPE_TDLS_PEER = (STA_TYPE_LEGACY_MASK | STA_TYPE_TDLS_MASK) +} ENUM_STA_TYPE_T, *P_ENUM_STA_TYPE_T; + +/* The type of BSS we discovered */ +typedef enum _ENUM_BSS_TYPE_T { + BSS_TYPE_INFRASTRUCTURE = 1, + BSS_TYPE_IBSS, + BSS_TYPE_P2P_DEVICE, + BSS_TYPE_BOW_DEVICE, + BSS_TYPE_NUM +} ENUM_BSS_TYPE_T, *P_ENUM_BSS_TYPE_T; + +/*----------------------------------------------------------------------------*/ +/* RSN structures */ +/*----------------------------------------------------------------------------*/ +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack(1) */ +/* #endif */ + +#define MAX_NUM_SUPPORTED_CIPHER_SUITES 8 /* max number of supported cipher suites */ +#if CFG_SUPPORT_802_11W +#define MAX_NUM_SUPPORTED_AKM_SUITES 8 /* max number of supported AKM suites */ +#else +#define MAX_NUM_SUPPORTED_AKM_SUITES 6 /* max number of supported AKM suites */ +#endif + +/* Structure of RSN Information */ +typedef struct _RSN_INFO_T { + UINT_8 ucElemId; + UINT_16 u2Version; + UINT_32 u4GroupKeyCipherSuite; + UINT_32 u4PairwiseKeyCipherSuiteCount; + UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_CIPHER_SUITES]; + UINT_32 u4AuthKeyMgtSuiteCount; + UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_AKM_SUITES]; + UINT_16 u2RsnCap; + BOOLEAN fgRsnCapPresent; +} /*__KAL_ATTRIB_PACKED__*/ RSN_INFO_T, *P_RSN_INFO_T; + +#define MAX_NUM_SUPPORTED_WAPI_AKM_SUITES 1 /* max number of supported AKM suites */ +#define MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES 1 /* max number of supported cipher suites */ + +/* Structure of WAPI Information */ +typedef struct _WAPI_INFO_T { + UINT_8 ucElemId; + UCHAR ucLength; + UINT_16 u2Version; + UINT_32 u4AuthKeyMgtSuiteCount; + UINT_32 au4AuthKeyMgtSuite[MAX_NUM_SUPPORTED_WAPI_AKM_SUITES]; + UINT_32 u4PairwiseKeyCipherSuiteCount; + UINT_32 au4PairwiseKeyCipherSuite[MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES]; + UINT_32 u4GroupKeyCipherSuite; + UINT_16 u2WapiCap; + UINT_16 u2Bkid; + UINT_8 aucBkid[1][16]; +} /* __KAL_ATTRIB_PACKED__ */ WAPI_INFO_T, *P_WAPI_INFO_T; + +/* #if defined(WINDOWS_DDK) || defined(WINDOWS_CE) */ +/* #pragma pack() */ +/* #endif */ + +#if CFG_ENABLE_WIFI_DIRECT + +typedef struct _P2P_DEVICE_TYPE_T { + UINT_16 u2CategoryID; + UINT_16 u2SubCategoryID; +} P2P_DEVICE_TYPE_T, *P_P2P_DEVICE_TYPE_T; + +typedef struct _P2P_DEVICE_DESC_T { + LINK_ENTRY_T rLinkEntry; + BOOLEAN fgDevInfoValid; + UINT_8 aucDeviceAddr[MAC_ADDR_LEN]; /* Device Address. */ + UINT_8 aucInterfaceAddr[MAC_ADDR_LEN]; /* Interface Address. */ + UINT_8 ucDeviceCapabilityBitmap; + UINT_8 ucGroupCapabilityBitmap; + UINT_16 u2ConfigMethod; /* Configure Method support. */ + P2P_DEVICE_TYPE_T rPriDevType; + UINT_8 ucSecDevTypeNum; + P2P_DEVICE_TYPE_T arSecDevType[8]; /* Reference to P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT */ + UINT_16 u2NameLength; + UINT_8 aucName[32]; /* Reference to WPS_ATTRI_MAX_LEN_DEVICE_NAME */ + /* TODO: Service Information or PasswordID valid? */ +} P2P_DEVICE_DESC_T, *P_P2P_DEVICE_DESC_T; + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static const UINT_8 aucRateIndex2RateCode[PREAMBLE_OPTION_NUM][RATE_NUM] = { + { /* Long Preamble */ + RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ + RATE_CCK_2M_LONG, /* RATE_2M_INDEX */ + RATE_CCK_5_5M_LONG, /* RATE_5_5M_INDEX */ + RATE_CCK_11M_LONG, /* RATE_11M_INDEX */ + RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ + RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ + RATE_OFDM_6M, /* RATE_6M_INDEX */ + RATE_OFDM_9M, /* RATE_9M_INDEX */ + RATE_OFDM_12M, /* RATE_12M_INDEX */ + RATE_OFDM_18M, /* RATE_18M_INDEX */ + RATE_OFDM_24M, /* RATE_24M_INDEX */ + RATE_OFDM_36M, /* RATE_36M_INDEX */ + RATE_OFDM_48M, /* RATE_48M_INDEX */ + RATE_OFDM_54M, /* RATE_54M_INDEX */ + }, + { /* Short Preamble */ + RATE_CCK_1M_LONG, /* RATE_1M_INDEX = 0 */ + RATE_CCK_2M_SHORT, /* RATE_2M_INDEX */ + RATE_CCK_5_5M_SHORT, /* RATE_5_5M_INDEX */ + RATE_CCK_11M_SHORT, /* RATE_11M_INDEX */ + RATE_CCK_1M_LONG, /* RATE_22M_INDEX - Not supported */ + RATE_CCK_1M_LONG, /* RATE_33M_INDEX - Not supported */ + RATE_OFDM_6M, /* RATE_6M_INDEX */ + RATE_OFDM_9M, /* RATE_9M_INDEX */ + RATE_OFDM_12M, /* RATE_12M_INDEX */ + RATE_OFDM_18M, /* RATE_18M_INDEX */ + RATE_OFDM_24M, /* RATE_24M_INDEX */ + RATE_OFDM_36M, /* RATE_36M_INDEX */ + RATE_OFDM_48M, /* RATE_48M_INDEX */ + RATE_OFDM_54M, /* RATE_54M_INDEX */ + }, + { /* Mixed Mode(Option) */ + RATE_MM_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_MM_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_MM_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_MM_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_MM_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_MM_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_MM_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_MM_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_MM_MCS_32 /* RATE_MCS32_INDEX, */ + }, + { /* Green Field(Option) */ + RATE_GF_MCS_0, /* RATE_MCS0_INDEX, */ + RATE_GF_MCS_1, /* RATE_MCS1_INDEX, */ + RATE_GF_MCS_2, /* RATE_MCS2_INDEX, */ + RATE_GF_MCS_3, /* RATE_MCS3_INDEX, */ + RATE_GF_MCS_4, /* RATE_MCS4_INDEX, */ + RATE_GF_MCS_5, /* RATE_MCS5_INDEX, */ + RATE_GF_MCS_6, /* RATE_MCS6_INDEX, */ + RATE_GF_MCS_7, /* RATE_MCS7_INDEX, */ + RATE_GF_MCS_32 /* RATE_MCS32_INDEX, */ + } +}; + +static const UINT_8 aucRateTableSize[PREAMBLE_OPTION_NUM] = { + RATE_HT_PHY_INDEX, + RATE_HT_PHY_INDEX, + HT_RATE_NUM, + HT_RATE_NUM +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Macros to get and set the wireless LAN frame fields those are 16/32 bits in + length. */ +#define WLAN_GET_FIELD_16(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_16)(_value_p) = ((UINT_16) __cp[0]) | ((UINT_16) __cp[1] << 8); \ + } + +#define WLAN_GET_FIELD_BE16(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_16)(_value_p) = ((UINT_16) __cp[0] << 8) | ((UINT_16) __cp[1]); \ + } + +#define WLAN_GET_FIELD_32(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_32)(_value_p) = ((UINT_32) __cp[0]) | ((UINT_32) __cp[1] << 8) | \ + ((UINT_32) __cp[2] << 16) | ((UINT_32) __cp[3] << 24); \ + } + +#define WLAN_GET_FIELD_64(_memAddr_p, _value_p) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + *(PUINT_64)(_value_p) = \ + ((UINT_64) __cp[0]) | ((UINT_64) __cp[1] << 8) | \ + ((UINT_64) __cp[2] << 16) | ((UINT_64) __cp[3] << 24) | \ + ((UINT_64) __cp[4] << 32) | ((UINT_64) __cp[5] << 40) | \ + ((UINT_64) __cp[6] << 48) | ((UINT_64) __cp[7] << 56); \ + } + +#define WLAN_SET_FIELD_16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + } + +#define WLAN_SET_FIELD_BE16(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) ((_value) >> 8); \ + __cp[1] = (UINT_8) (_value); \ + } + +#define WLAN_SET_FIELD_32(_memAddr_p, _value) \ + { \ + PUINT_8 __cp = (PUINT_8) (_memAddr_p); \ + __cp[0] = (UINT_8) (_value); \ + __cp[1] = (UINT_8) ((_value) >> 8); \ + __cp[2] = (UINT_8) ((_value) >> 16); \ + __cp[3] = (UINT_8) ((_value) >> 24); \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _WLAN_DEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h new file mode 100644 index 0000000000000..aba2e040c1949 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_cmd_event.h @@ -0,0 +1,2290 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_cmd_event.h#1 +*/ + +/*! \file "nic_cmd_event.h" + \brief This file contains the declairation file of the WLAN OID processing routines + of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: nic_cmd_event.h + * + * 03 29 2012 eason.tsai + * [WCXRP00001216] [MT6628 Wi-Fi][Driver]add conditional define + * add conditional define. + * + * 03 04 2012 eason.tsai + * NULL + * modify the cal fail report code. + * + * 01 06 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * redefine the CMD_ID_SET_TXPWR_CTRL value. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 11 30 2011 cm.chang + * [WCXRP00001128] [MT5931 Wi-Fi][FW] Update BB/RF setting based on RF doc v0.7 for LGE spec + * 1. Add a new CMD for driver to set device mode + * 2. Update calibration parameters + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add TX_DONE status detail information. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * check if CFG_SUPPORT_SWCR is defined to aoid compiler error. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 10 26 2011 cp.wu + * [WCXRP00001065] [MT6620 Wi-Fi][MT5931][FW][DRV] Adding parameter for controlling + * minimum channel dwell time for scanning + * add interface for control minimum channel dwell time for scanning. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * New CMD definition about RLM parameters + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 09 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * add CCK-DSSS TX-PWR control field in NVRAM and CMD definition for MT5931-MP + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * add osc stable time command structure + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search for more than + * one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID + * support as well as uProbeDelay in NDIS 6.x driver model + * + * 06 23 2011 cp.wu + * [WCXRP00000812] [MT6620 Wi-Fi][Driver] not show NVRAM when there is no valid MAC address in NVRAM content + * check with firmware for valid MAC address. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 31 2011 chinglan.wang + * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. + * . + * + * 03 18 2011 cm.chang + * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command + * As CR title + * + * 03 17 2011 yarco.yang + * [WCXRP00000569] [MT6620 Wi-Fi][F/W][Driver] Set multicast address support current network usage + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 02 16 2011 cm.chang + * [WCXRP00000447] [MT6620 Wi-Fi][FW] Support new NVRAM update mechanism + * . + * + * 02 10 2011 cp.wu + * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers + * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Update cmd format of BSS INFO, always sync OwnMac to FW no matter P2P is enabled or not.. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 15 2011 puff.wen + * NULL + * Add Stress test + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Sync HT operation element information from host to FW + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * report EEPROM used flag via NIC_CAPABILITY + * + * 12 28 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * integrate with 'EEPROM used' flag for reporting correct capability to Engineer Mode/META and other tools + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC for + * initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 cp.wu + * [WCXRP00000133] [MT6620 Wi-Fi] [FW][Driver] Change TX power offset band definition + * follow-up for CMD_5G_PWR_OFFSET_T definition change + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 15 2010 cm.chang + * NULL + * Add new CMD for TX power, 5G power offset and power parameters + * + * 09 07 2010 yuche.tsai + * NULL + * Add a pointer in P2P SCAN RESULT structure. This pointer + * is pointed to a IE buffer for this P2p device. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 16 2010 george.huang + * NULL + * add new CMD ID definition + * + * 08 16 2010 yuche.tsai + * NULL + * Add a field in BSS INFO cmd to change interface address for P2P. (switching between Device Addr & Interface Addr) + * + * 08 12 2010 yuche.tsai + * NULL + * Add interface address indication when indicate connection status. + * It is requested by supplicant to do 4 way handshake. + * + * 08 07 2010 wh.su + * NULL + * adding the privacy related code for P2P network + * + * 08 05 2010 yuche.tsai + * NULL + * Change data structure for P2P Device scan result, all channel time for scan command. + * + * 08 04 2010 george.huang + * NULL + * handle change PS mode OID/ CMD + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 28 2010 cp.wu + * NULL + * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. + * + * 07 26 2010 yuche.tsai + * + * Add P2P Device Found Event. + * Channel extension option in scan abort command. + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 yuche.tsai + * + * Add for P2P Scan Result Parsing & Saving. + * + * 07 20 2010 george.huang + * + * DWORD align for the CMD data structure + * + * 07 20 2010 cp.wu + * + * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 09 2010 cp.wu + * + * reorder members of CMD_SET_BSS_INFO. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * update prStaRecOfAP with BSS-INFO. + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 28 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add BSS/STA_REC commands for integration. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add TX Done Event handle entry + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sync statistics data structure definition with firmware implementation + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * the frequency is used for adhoc connection only + * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00003824][MT6620 Wi-Fi][New Feature] Add support of large scan list + * Implement feature needed by CR: WPD00003824: refining association command by pasting scanning result + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 15 2010 kevin.huang + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Add event for activate STA_RECORD_T + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c + * 'cause it involves OS dependent data structure handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * send CMD_ID_INFRASTRUCTURE when handling OID_802_11_INFRASTRUCTURE_MODE set. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * 4. correct some HAL implementation + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * OID_802_11_RSSI, + * * * OID_802_11_RSSI_TRIGGER, + * * * OID_802_11_STATISTICS, + * * * OID_802_11_DISASSOCIATE, + * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * and result is retrieved by get ATInfo instead + * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-12-11 18:35:07 GMT mtk02752 +** add CMD added in CMD/EVEN document v0.8 +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-12-10 16:39:37 GMT mtk02752 +** eliminate unused definitions +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-12-10 09:55:11 GMT mtk02752 +** command ID/event ID revised +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-12-09 13:57:37 GMT MTK02468 +** Added event ids (EVENT_ID_RX_ADDBA and EVENT_ID_RX_DELBA) +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-12-08 17:35:39 GMT mtk02752 +** + add event ID for EVENT_ID_TEST_STATUS (rf test) +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-12-07 23:01:09 GMT mtk02752 +** add data structure for RF_TEST +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-12-03 16:22:56 GMT mtk01461 +** Modify the element - i4RSSI in EVENT of SCAN RESULT +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-11-30 10:54:44 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T, while 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-11-26 10:16:58 GMT mtk02752 +** resync EVENT_CONNECTION_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-11-25 21:34:01 GMT mtk02752 +** sync. EVENT_SCAN_RESULT_T with firmware +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-11-25 21:03:48 GMT mtk02752 +** refine MGMT_FRAME +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-11-25 18:17:47 GMT mtk02752 +** refine GL_WLAN_INFO_T for buffering scan result and presume max. ie length = 600 bytes +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-24 22:41:20 GMT mtk02752 +** add EVENT_SCAN_RESULT_T definition +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-11-23 20:29:16 GMT mtk02752 +** fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-11-23 14:46:01 GMT mtk02752 +** add new command/event structure upon CM@SD1's documentation +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-13 15:13:40 GMT mtk02752 +** add command definition for CMD_BUILD_CONNECTION and EVENT_CONNECTION_STATUS +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-20 12:22:22 GMT mtk01461 +** Add SeqNum field to Event Header +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:11 GMT mtk01461 +** Update structure of HIF_EVENT_HEADER_T and EVENT_HDR_SIZE +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 12:10:36 GMT mtk01461 +** Add Common Set CMD Callback for MCR Write and other Set OID +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:17 GMT mtk01461 +** Command Done Handler +*/ +#ifndef _NIC_CMD_EVENT_H +#define _NIC_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define CMD_STATUS_SUCCESS 0 +#define CMD_STATUS_REJECTED 1 +#define CMD_STATUS_UNKNOWN 2 + +#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) + +#define MAX_IE_LENGTH (600) +#define MAX_WSC_IE_LENGTH (400) + +/* Action field in structure CMD_CH_PRIVILEGE_T */ +#define CMD_CH_ACTION_REQ 0 +#define CMD_CH_ACTION_ABORT 1 + +/* Status field in structure EVENT_CH_PRIVILEGE_T */ +#define EVENT_CH_STATUS_GRANT 0 + +#define SCN_PSCAN_SWC_RSSI_WIN_MAX 75 +#define SCN_PSCAN_SWC_MAX_NUM 8 +#define SCN_PSCAN_HOTLIST_REPORT_MAX_NUM 8 + +typedef enum _ENUM_CMD_ID_T { + CMD_ID_TEST_MODE = 1, /* 0x01 (Set) */ + CMD_ID_RESET_REQUEST, /* 0x02 (Set) */ + CMD_ID_BUILD_CONNECTION, /* 0x03 (Set) */ + CMD_ID_SCAN_REQ_V2, /* 0x04 (Set) */ + CMD_ID_NIC_POWER_CTRL, /* 0x05 (Set) */ + CMD_ID_POWER_SAVE_MODE, /* 0x06 (Set) */ + CMD_ID_LINK_ATTRIB, /* 0x07 (Set) */ + CMD_ID_ADD_REMOVE_KEY, /* 0x08 (Set) */ + CMD_ID_DEFAULT_KEY_ID, /* 0x09 (Set) */ + CMD_ID_INFRASTRUCTURE, /* 0x0a (Set) */ + CMD_ID_SET_RX_FILTER, /* 0x0b (Set) */ + CMD_ID_DOWNLOAD_BUF, /* 0x0c (Set) */ + CMD_ID_WIFI_START, /* 0x0d (Set) */ + CMD_ID_CMD_BT_OVER_WIFI, /* 0x0e (Set) */ + CMD_ID_SET_MEDIA_CHANGE_DELAY_TIME, /* 0x0f (Set) */ + CMD_ID_SEND_ADDBA_RSP, /* 0x10 (Set) */ + CMD_ID_WAPI_MODE, /* 0x11 (Set) (obsolete) */ + CMD_ID_WAPI_ASSOC_INFO, /* 0x12 (Set) (obsolete) */ + CMD_ID_SET_DOMAIN_INFO, /* 0x13 (Set) */ + CMD_ID_SET_IP_ADDRESS, /* 0x14 (Set) */ + CMD_ID_BSS_ACTIVATE_CTRL, /* 0x15 (Set) */ + CMD_ID_SET_BSS_INFO, /* 0x16 (Set) */ + CMD_ID_UPDATE_STA_RECORD, /* 0x17 (Set) */ + CMD_ID_REMOVE_STA_RECORD, /* 0x18 (Set) */ + CMD_ID_INDICATE_PM_BSS_CREATED, /* 0x19 (Set) */ + CMD_ID_INDICATE_PM_BSS_CONNECTED, /* 0x1a (Set) */ + CMD_ID_INDICATE_PM_BSS_ABORT, /* 0x1b (Set) */ + CMD_ID_UPDATE_BEACON_CONTENT, /* 0x1c (Set) */ + CMD_ID_SET_BSS_RLM_PARAM, /* 0x1d (Set) */ + CMD_ID_SCAN_REQ, /* 0x1e (Set) */ + CMD_ID_SCAN_CANCEL, /* 0x1f (Set) */ + CMD_ID_CH_PRIVILEGE, /* 0x20 (Set) */ + CMD_ID_UPDATE_WMM_PARMS, /* 0x21 (Set) */ + CMD_ID_SET_WMM_PS_TEST_PARMS, /* 0x22 (Set) */ + CMD_ID_TX_AMPDU, /* 0x23 (Set) */ + CMD_ID_ADDBA_REJECT, /* 0x24 (Set) */ + CMD_ID_SET_PS_PROFILE_ADV, /* 0x25 (Set) */ + CMD_ID_SET_RAW_PATTERN, /* 0x26 (Set) */ + CMD_ID_CONFIG_PATTERN_FUNC, /* 0x27 (Set) */ + CMD_ID_SET_TX_PWR, /* 0x28 (Set) */ + CMD_ID_SET_5G_PWR_OFFSET, /* 0x29 (Set) */ + CMD_ID_SET_PWR_PARAM, /* 0x2A (Set) */ + CMD_ID_P2P_ABORT, /* 0x2B (Set) */ +#if CFG_STRESS_TEST_SUPPORT + CMD_ID_RANDOM_RX_RESET_EN = 0x2C, /* 0x2C (Set ) */ + CMD_ID_RANDOM_RX_RESET_DE = 0x2D, /* 0x2D (Set ) */ + CMD_ID_SAPP_EN = 0x2E, /* 0x2E (Set ) */ + CMD_ID_SAPP_DE = 0x2F, /* 0x2F (Set ) */ +#endif + CMD_ID_ROAMING_TRANSIT = 0x30, /* 0x30 (Set) */ + CMD_ID_SET_PHY_PARAM, /* 0x31 (Set) */ + CMD_ID_SET_NOA_PARAM, /* 0x32 (Set) */ + CMD_ID_SET_OPPPS_PARAM, /* 0x33 (Set) */ + CMD_ID_SET_UAPSD_PARAM, /* 0x34 (Set) */ + CMD_ID_SET_SIGMA_STA_SLEEP, /* 0x35 (Set) */ + CMD_ID_SET_EDGE_TXPWR_LIMIT, /* 0x36 (Set) */ + CMD_ID_SET_DEVICE_MODE, /* 0x37 (Set) */ + CMD_ID_SET_TXPWR_CTRL, /* 0x38 (Set) */ + CMD_ID_SET_AUTOPWR_CTRL, /* 0x39 (Set) */ + CMD_ID_SET_WFD_CTRL, /* 0x3A (Set) */ + CMD_ID_SET_5G_EDGE_TXPWR_LIMIT, /* 0x3B (Set) */ + CMD_ID_SET_RSSI_COMPENSATE, /* 0x3C (Set) */ + CMD_ID_SET_BAND_SUPPORT = 0x3D, /* 0x3D (Set) */ + CMD_ID_SET_NLO_REQ, /* 0x3E (Set) */ + CMD_ID_SET_NLO_CANCEL, /* 0x3F (Set) */ + CMD_ID_SET_BATCH_REQ, /* 0x40 (Set) */ + CMD_ID_SET_WOWLAN, /* 0x41 (Set) */ /*CFG_SUPPORT_WOWLAN */ + CMD_ID_GET_PSCAN_CAPABILITY = 0x42, /* 0x42 (Set) */ + CMD_ID_SET_PSCN_ENABLE = 0x43, /* 0x43 (Set) */ + CMD_ID_SET_PSCAN_PARAM = 0x44, /* 0x44 (Set) */ + CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID = 0x45, /* 0x45 (Set) */ + CMD_ID_SET_PSCN_ADD_SW_BSSID = 0x46, /* 0x46 (Set) */ + CMD_ID_SET_PSCN_MAC_ADDR = 0x47, /* 0x47 (Set) */ + CMD_ID_GET_GSCN_SCN_RESULT = 0x48, /* 0x48 (Get) */ + CMD_ID_SET_COUNTRY_POWER_LIMIT = 0x4A, /* 0x4A (Set) */ + CMD_ID_SET_SYSTEM_SUSPEND = 0x60, /* 0x60 (Set) */ + CMD_ID_GET_NIC_CAPABILITY = 0x80, /* 0x80 (Query) */ + CMD_ID_GET_LINK_QUALITY, /* 0x81 (Query) */ + CMD_ID_GET_STATISTICS, /* 0x82 (Query) */ + CMD_ID_GET_CONNECTION_STATUS, /* 0x83 (Query) */ + CMD_ID_GET_ASSOC_INFO, /* 0x84 (Query) (obsolete) */ + CMD_ID_GET_STA_STATISTICS = 0x85, /* 0x85 (Query) */ + CMD_ID_GET_DEBUG_CODE = 0x86, /* 0x86 (Query) */ + CMD_ID_GET_LTE_CHN = 0x87, /* 0x87 (Query) */ + CMD_ID_GET_CHN_LOADING = 0x88, /* 0x88 (Query) */ + CMD_ID_GET_STATISTICS_PL = 0x89, /* 0x87 (Query) */ + CMD_ID_BASIC_CONFIG = 0xc1, /* 0xc1 (Set / Query) */ + CMD_ID_ACCESS_REG, /* 0xc2 (Set / Query) */ + CMD_ID_MAC_MCAST_ADDR, /* 0xc3 (Set / Query) */ + CMD_ID_802_11_PMKID, /* 0xc4 (Set / Query) */ + CMD_ID_ACCESS_EEPROM, /* 0xc5 (Set / Query) */ + CMD_ID_SW_DBG_CTRL, /* 0xc6 (Set / Query) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + CMD_ID_SEC_CHECK, /* 0xc7 (Set / Query) */ +#endif + CMD_ID_DUMP_MEM, /* 0xc8 (Query) */ + + CMD_ID_CHIP_CONFIG = 0xCA, /* 0xca (Set / Query) */ + +#if CFG_SUPPORT_RDD_TEST_MODE + CMD_ID_SET_RDD_CH = 0xE1, +#endif + + CMD_ID_SET_BWCS = 0xF1, + CMD_ID_SET_ROAMING_INFO = 0xF3, + +#if CFG_SUPPORT_BUILD_DATE_CODE + CMD_ID_GET_BUILD_DATE_CODE = 0xF8, +#endif + CMD_ID_GET_BSS_INFO = 0xF9, +#if 1 /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ + CMD_ID_SET_HOTSPOT_OPTIMIZATION = 0xFA, /* 0xFA (Set) */ +#endif + + CMD_ID_TDLS_CORE = 0xFC, + CMD_ID_STATS = 0xFD, + CMD_ID_TX_AR_ERR_CONFIG = 0xFF +} ENUM_CMD_ID_T, *P_ENUM_CMD_ID_T; + +typedef enum _ENUM_EVENT_ID_T { + EVENT_ID_CMD_RESULT = 1, /* 0x01 (Query) */ + EVENT_ID_NIC_CAPABILITY, /* 0x02 (Query) */ + EVENT_ID_CONNECTION_STATUS, /* 0x03 (Query / Unsolicited) (obsolete) */ + EVENT_ID_SCAN_RESULT, /* 0x04 (Query / Unsolicited) (obselete) */ + EVENT_ID_LINK_QUALITY, /* 0x05 (Query / Unsolicited) */ + EVENT_ID_STATISTICS, /* 0x06 (Query) */ + EVENT_ID_MIC_ERR_INFO, /* 0x07 (Unsolicited) */ + EVENT_ID_ASSOC_INFO, /* 0x08 (Query - CMD_ID_GET_ASSOC_INFO) */ + EVENT_ID_BASIC_CONFIG, /* 0x09 (Query - CMD_ID_BASIC_CONFIG) */ + EVENT_ID_ACCESS_REG, /* 0x0a (Query - CMD_ID_ACCESS_REG) */ + EVENT_ID_MAC_MCAST_ADDR, /* 0x0b (Query - CMD_ID_MAC_MCAST_ADDR) */ + EVENT_ID_802_11_PMKID, /* 0x0c (Query - CMD_ID_802_11_PMKID) */ + EVENT_ID_ACCESS_EEPROM, /* 0x0d (Query - CMD_ID_ACCESS_EEPROM) */ + EVENT_ID_SLEEPY_NOTIFY, /* 0x0e (Query) */ + EVENT_ID_BT_OVER_WIFI, /* 0x0f (Unsolicited) */ + EVENT_ID_TEST_STATUS, /* 0x10 (Query - CMD_ID_TEST_MODE) */ + EVENT_ID_RX_ADDBA, /* 0x11 (Unsolicited) (obsolete) */ + EVENT_ID_RX_DELBA, /* 0x12 (Unsolicited) (obsolete) */ + EVENT_ID_ACTIVATE_STA_REC_T, /* 0x13 (Unsolicited) */ + EVENT_ID_DEACTIVATE_STA_REC_T, /* 0x14 (Unsolicited) */ + EVENT_ID_SCAN_DONE, /* 0x15 (Unsoiicited) */ + EVENT_ID_RX_FLUSH, /* 0x16 (Unsolicited) */ + EVENT_ID_TX_DONE, /* 0x17 (Unsolicited) */ + EVENT_ID_CH_PRIVILEGE, /* 0x18 (Unsolicited) */ + EVENT_ID_BSS_ABSENCE_PRESENCE = 0x19, /* 0x19 (Unsolicited) */ + EVENT_ID_STA_CHANGE_PS_MODE, /* 0x1A (Unsolicited) */ + EVENT_ID_BSS_BEACON_TIMEOUT, /* 0x1B (Unsolicited) */ + EVENT_ID_UPDATE_NOA_PARAMS, /* 0x1C (Unsolicited) */ + EVENT_ID_AP_OBSS_STATUS, /* 0x1D (Unsolicited) */ + EVENT_ID_STA_UPDATE_FREE_QUOTA, /* 0x1E (Unsolicited) */ + EVENT_ID_SW_DBG_CTRL, /* 0x1F (Query - CMD_ID_SW_DBG_CTRL) */ + EVENT_ID_ROAMING_STATUS, /* 0x20 (Unsolicited) */ + EVENT_ID_STA_AGING_TIMEOUT, /* 0x21 (Unsolicited) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + EVENT_ID_SEC_CHECK_RSP, /* 0x22 (Unsolicited) */ +#endif + EVENT_ID_SEND_DEAUTH, /* 0x23 (Unsolicited) */ + +#if CFG_SUPPORT_RDD_TEST_MODE + EVENT_ID_UPDATE_RDD_STATUS, /* 0x24 (Unsolicited) */ +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + EVENT_ID_UPDATE_BWCS_STATUS = 0x25, /* 0x25 (Unsolicited) */ + EVENT_ID_UPDATE_BCM_DEBUG, /* 0x26 (Unsolicited) */ +#endif + EVENT_ID_RX_ERR, + EVENT_ID_DUMP_MEM, + EVENT_ID_STA_STATISTICS = 0x29, /* 0x29 (Query ) */ + EVENT_ID_STA_STATISTICS_UPDATE, /* 0x2A (Unsolicited) */ + EVENT_ID_NLO_DONE = 0x2b, + + EVENT_ID_GSCAN_CAPABILITY = 0x30, + EVENT_ID_GSCAN_SCAN_COMPLETE = 0x31, + EVENT_ID_GSCAN_FULL_RESULT = 0x32, + EVENT_ID_GSCAN_SIGNIFICANT_CHANGE = 0x33, + EVENT_ID_GSCAN_GEOFENCE_FOUND = 0x34, + EVENT_ID_GSCAN_SCAN_AVAILABLE = 0x35, + EVENT_ID_GSCAN_RESULT = 0x36, + EVENT_ID_BATCH_RESULT = 0x37, + + EVENT_ID_TDLS = 0x80, + EVENT_ID_STATS_ENV = 0x81, + +#if CFG_SUPPORT_BUILD_DATE_CODE + EVENT_ID_BUILD_DATE_CODE = 0xF8, +#endif + EVENT_ID_GET_AIS_BSS_INFO = 0xF9, + EVENT_ID_DEBUG_CODE = 0xFB, + EVENT_ID_RFTEST_READY = 0xFC, /* 0xFC */ + EVENT_ID_TX_DONE_STATUS = 0xFD, + EVENT_ID_FW_LOG_ENV = 0xFE, /* 0xFE, FW real time debug log */ +} ENUM_EVENT_ID_T, *P_ENUM_EVENT_ID_T; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#ifndef LINUX +typedef UINT_8 CMD_STATUS; +#endif + +typedef struct _EVENT_TX_DONE_STATUS_T { + UINT_8 ucPacketSeq; + UINT_8 ucStatus; + UINT_16 u2SequenceNumber; + UINT_32 au4Reserved1; + UINT_32 au4Reserved2; + UINT_32 au4Reserved3; + UINT_32 u4PktBufInfo; + UINT_8 aucPktBuf[200]; +} EVENT_TX_DONE_STATUS_T, *P_EVENT_TX_DONE_STATUS_T; + +/* for Event Packet (via HIF-RX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_CMD_T { + UINT_16 u2TxByteCount_UserPriority; + UINT_8 ucEtherTypeOffset; + UINT_8 ucResource_PktType_CSflags; + UINT_8 ucCID; + UINT_8 ucSetQuery; + UINT_8 ucSeqNum; + UINT_8 aucReserved2; + + UINT_8 aucBuffer[0]; +} WIFI_CMD_T, *P_WIFI_CMD_T; + +/* for Command Packet (via HIF-TX) */ + /* following CM's documentation v0.7 */ +typedef struct _WIFI_EVENT_T { + UINT_16 u2PacketLen; + UINT_16 u2PacketType; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucReserved2[2]; + + UINT_8 aucBuffer[0]; +} WIFI_EVENT_T, *P_WIFI_EVENT_T; + +/* CMD_ID_TEST_MODE */ +typedef struct _CMD_TEST_CTRL_T { + UINT_8 ucAction; + UINT_8 aucReserved[3]; + union { + UINT_32 u4OpMode; + UINT_32 u4ChannelFreq; + PARAM_MTK_WIFI_TEST_STRUCT_T rRfATInfo; + } u; +} CMD_TEST_CTRL_T, *P_CMD_TEST_CTRL_T; + +/* EVENT_TEST_STATUS */ +typedef struct _PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T { + UINT_32 u4PktSentStatus; + UINT_32 u4PktSentCount; + UINT_16 u2AvgAlc; + UINT_8 ucCckGainControl; + UINT_8 ucOfdmGainControl; +} PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T; + +typedef struct _PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T { + UINT_32 u4IntRxOk; /*!< number of packets that Rx ok from interrupt */ + UINT_32 u4IntCrcErr; /*!< number of packets that CRC error from interrupt */ + UINT_32 u4IntShort; /*!< number of packets that is short preamble from interrupt */ + UINT_32 u4IntLong; /*!< number of packets that is long preamble from interrupt */ + UINT_32 u4PauRxPktCount; /*!< number of packets that Rx ok from PAU */ + UINT_32 u4PauCrcErrCount; /*!< number of packets that CRC error from PAU */ + UINT_32 u4PauRxFifoFullCount; /*!< number of packets that is short preamble from PAU */ + UINT_32 u4PauCCACount; /*!< CCA rising edge count */ +} PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T, *P_PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T; + +typedef union _EVENT_TEST_STATUS { + PARAM_MTK_WIFI_TEST_STRUCT_T rATInfo; +/* PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T rTxStatus; */ +/* PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T rRxStatus; */ +} EVENT_TEST_STATUS, *P_EVENT_TEST_STATUS; + +/* CMD_BUILD_CONNECTION */ +typedef struct _CMD_BUILD_CONNECTION { + UINT_8 ucInfraMode; + UINT_8 ucAuthMode; + UINT_8 ucEncryptStatus; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + + /* Ad-hoc mode */ + UINT_16 u2BeaconPeriod; + UINT_16 u2ATIMWindow; + UINT_8 ucJoinOnly; + UINT_8 ucReserved; + UINT_32 u4FreqInKHz; + + /* for faster connection */ + UINT_8 aucScanResult[0]; +} CMD_BUILD_CONNECTION, *P_CMD_BUILD_CONNECTION; + +/* CMD_ADD_REMOVE_KEY */ +typedef struct _CMD_802_11_KEY { + UINT_8 ucAddRemove; + UINT_8 ucTxKey; + UINT_8 ucKeyType; + UINT_8 ucIsAuthenticator; + UINT_8 aucPeerAddr[6]; + UINT_8 ucNetType; + UINT_8 ucAlgorithmId; + UINT_8 ucKeyId; + UINT_8 ucKeyLen; + UINT_8 aucReverved[2]; + UINT_8 aucKeyMaterial[32]; + UINT_8 aucKeyRsc[16]; +} CMD_802_11_KEY, *P_CMD_802_11_KEY; + +/* WPA2 PMKID cache structure */ +typedef struct _PMKID_ENTRY_T { + PARAM_BSSID_INFO_T rBssidInfo; + BOOLEAN fgPmkidExist; +} PMKID_ENTRY_T, *P_PMKID_ENTRY_T; + +typedef struct _CMD_802_11_PMKID { + ULONG u4BSSIDInfoCount; + P_PMKID_ENTRY_T arPMKIDInfo[1]; +} CMD_802_11_PMKID, *P_CMD_802_11_PMKID; + +/* CMD_BASIC_CONFIG */ +typedef struct _CMD_CSUM_OFFLOAD { + UINT_16 u2RxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ + UINT_16 u2TxChecksum; /* bit0: IP, bit1: UDP, bit2: TCP */ +} CMD_CSUM_OFFLOAD, *P_CMD_CSUM_OFFLOAD; + +typedef struct _CMD_BASIC_CONFIG { + PARAM_MAC_ADDRESS rMyMacAddr; + UINT_8 ucNative80211; + UINT_8 aucReserved[1]; + + CMD_CSUM_OFFLOAD rCsumOffload; +} CMD_BASIC_CONFIG, *P_CMD_BASIC_CONFIG, EVENT_BASIC_CONFIG, *P_EVENT_BASIC_CONFIG; + +/* CMD_MAC_MCAST_ADDR */ +typedef struct _CMD_MAC_MCAST_ADDR { + UINT_32 u4NumOfGroupAddr; + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; + PARAM_MAC_ADDRESS arAddress[MAX_NUM_GROUP_ADDR]; +} CMD_MAC_MCAST_ADDR, *P_CMD_MAC_MCAST_ADDR, EVENT_MAC_MCAST_ADDR, *P_EVENT_MAC_MCAST_ADDR; + +/* CMD_ACCESS_EEPROM */ +typedef struct _CMD_ACCESS_EEPROM { + UINT_16 u2Offset; + UINT_16 u2Data; +} CMD_ACCESS_EEPROM, *P_CMD_ACCESS_EEPROM, EVENT_ACCESS_EEPROM, *P_EVENT_ACCESS_EEPROM; + +typedef struct _CMD_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} CMD_CUSTOM_NOA_PARAM_STRUCT_T, *P_CMD_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; +} CMD_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_CMD_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _CMD_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} CMD_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_CMD_CUSTOM_UAPSD_PARAM_STRUCT_T; + +/* EVENT_CONNECTION_STATUS */ +typedef struct _EVENT_CONNECTION_STATUS { + UINT_8 ucMediaStatus; + UINT_8 ucReasonOfDisconnect; + + UINT_8 ucInfraMode; + UINT_8 ucSsidLen; + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_8 aucBssid[PARAM_MAC_ADDR_LEN]; + UINT_8 ucAuthenMode; + UINT_8 ucEncryptStatus; + UINT_16 u2BeaconPeriod; + UINT_16 u2AID; + UINT_16 u2ATIMWindow; + UINT_8 ucNetworkType; + UINT_8 aucReserved[1]; + UINT_32 u4FreqInKHz; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucInterfaceAddr[PARAM_MAC_ADDR_LEN]; +#endif + +} EVENT_CONNECTION_STATUS, *P_EVENT_CONNECTION_STATUS; + +/* EVENT_NIC_CAPABILITY */ +typedef struct _EVENT_NIC_CAPABILITY { + UINT_16 u2ProductID; + UINT_16 u2FwVersion; + UINT_16 u2DriverVersion; + UINT_8 ucHw5GBandDisabled; + UINT_8 ucEepromUsed; + UINT_8 ucEfuseValid; + UINT_8 ucMacAddrValid; +#if CFG_REPORT_RFBB_VERSION + UINT_8 ucRfVersion; + UINT_8 ucPhyVersion; +#endif +#if CFG_ENABLE_CAL_LOG + UINT_8 ucRfCalFail; + UINT_8 ucBbCalFail; +#endif + +#define FEATURE_SET_OFFSET_TDLS 0 +#define FEATURE_SET_OFFSET_5G_SUPPORT 1 + UINT_8 ucFeatureSet; /* bit0: TDLS */ + + UINT_8 aucReserved[1]; +#if CFG_EMBED_FIRMWARE_BUILD_DATE_CODE + UINT_8 aucDateCode[16]; +#endif +} EVENT_NIC_CAPABILITY, *P_EVENT_NIC_CAPABILITY; + +/* modified version of WLAN_BEACON_FRAME_BODY_T for simplier buffering */ +typedef struct _WLAN_BEACON_FRAME_BODY_T_LOCAL { + /* Beacon frame body */ + UINT_32 au4Timestamp[2]; /* Timestamp */ + UINT_16 u2BeaconInterval; /* Beacon Interval */ + UINT_16 u2CapInfo; /* Capability */ + UINT_8 aucInfoElem[MAX_IE_LENGTH]; /* Various IEs, start from SSID */ + UINT_16 u2IELength; /* This field is *NOT* carried by F/W but caculated by nic_rx */ +} WLAN_BEACON_FRAME_BODY_T_LOCAL, *P_WLAN_BEACON_FRAME_BODY_T_LOCAL; + +/* EVENT_SCAN_RESULT */ +typedef struct _EVENT_SCAN_RESULT_T { + INT_32 i4RSSI; + UINT_32 u4LinkQuality; + UINT_32 u4DSConfig; /* Center frequency */ + UINT_32 u4DomainInfo; /* Require CM opinion */ + UINT_32 u4Reserved; + UINT_8 ucNetworkType; + UINT_8 ucOpMode; + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + WLAN_BEACON_FRAME_BODY_T_LOCAL rBeaconFrameBody; +} EVENT_SCAN_RESULT_T, *P_EVENT_SCAN_RESULT_T; + +/* event of tkip mic error */ +typedef struct _EVENT_MIC_ERR_INFO { + UINT_32 u4Flags; +} EVENT_MIC_ERR_INFO, *P_EVENT_MIC_ERR_INFO; + +typedef struct _EVENT_PMKID_CANDIDATE_LIST_T { + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} EVENT_PMKID_CANDIDATE_LIST_T, *P_EVENT_PMKID_CANDIDATE_LIST_T; + +typedef struct _EVENT_CMD_RESULT { + UINT_8 ucCmdID; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_CMD_RESULT, *P_EVENT_CMD_RESULT; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +typedef struct _CMD_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} CMD_ACCESS_REG, *P_CMD_ACCESS_REG; + +/* CMD_ID_ACCESS_REG & EVENT_ID_ACCESS_REG */ +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + +typedef struct _CMD_ACCESS_CHN_LOAD { + UINT_32 u4Address; + UINT_32 u4Data; + UINT_16 u2Channel; + UINT_8 aucReserved[2]; +} CMD_ACCESS_CHN_LOAD, *P_ACCESS_CHN_LOAD; + +#endif +/* CMD_DUMP_MEMORY */ +typedef struct _CMD_DUMP_MEM { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} CMD_DUMP_MEM, *P_CMD_DUMP_MEM; + +typedef struct _EVENT_DUMP_MEM_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; + UINT_8 aucBuffer[1]; +} EVENT_DUMP_MEM_T, *P_EVENT_DUMP_MEM_T; + +typedef struct _CMD_SW_DBG_CTRL_T { + UINT_32 u4Id; + UINT_32 u4Data; + /* Debug Support */ + UINT_32 u4DebugCnt[64]; +} CMD_SW_DBG_CTRL_T, *P_CMD_SW_DBG_CTRL_T; + +/* CMD_ID_LINK_ATTRIB */ +typedef struct _CMD_LINK_ATTRIB { + INT_8 cRssiTrigger; + UINT_8 ucDesiredRateLen; + UINT_16 u2DesiredRate[32]; + UINT_8 ucMediaStreamMode; + UINT_8 aucReserved[1]; +} CMD_LINK_ATTRIB, *P_CMD_LINK_ATTRIB; + +/* CMD_ID_NIC_POWER_CTRL */ +typedef struct _CMD_NIC_POWER_CTRL { + UINT_8 ucPowerMode; + UINT_8 aucReserved[3]; +} CMD_NIC_POWER_CTRL, *P_CMD_NIC_POWER_CTRL; + +/* CMD_ID_POWER_SAVE_MODE */ +typedef struct _CMD_PS_PROFILE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucPsProfile; + UINT_8 aucReserved[2]; +} CMD_PS_PROFILE_T, *P_CMD_PS_PROFILE_T; + +/* EVENT_LINK_QUALITY */ +typedef struct _EVENT_LINK_QUALITY { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; +} EVENT_LINK_QUALITY, *P_EVENT_LINK_QUALITY; + +#if CFG_SUPPORT_P2P_RSSI_QUERY +/* EVENT_LINK_QUALITY */ +typedef struct _EVENT_LINK_QUALITY_EX { + INT_8 cRssi; + INT_8 cLinkQuality; + UINT_16 u2LinkSpeed; + UINT_8 ucMediumBusyPercentage; + UINT_8 ucIsLQ0Rdy; + INT_8 cRssiP2P; /* For P2P Network. */ + INT_8 cLinkQualityP2P; + UINT_16 u2LinkSpeedP2P; + UINT_8 ucMediumBusyPercentageP2P; + UINT_8 ucIsLQ1Rdy; +} EVENT_LINK_QUALITY_EX, *P_EVENT_LINK_QUALITY_EX; +#endif + +/* EVENT_ID_STATISTICS */ +typedef struct _EVENT_STATISTICS { + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; +} EVENT_STATISTICS, *P_EVENT_STATISTICS; + +/* EVENT_ID_FW_SLEEPY_NOTIFY */ +typedef struct _EVENT_SLEEPY_NOTIFY { + UINT_8 ucSleepyState; + UINT_8 aucReserved[3]; +} EVENT_SLEEPY_NOTIFY, *P_EVENT_SLEEPY_NOTIFY; + +typedef struct _EVENT_ACTIVATE_STA_REC_T { + UINT_8 aucMacAddr[6]; + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + BOOLEAN fgIsQoS; + BOOLEAN fgIsAP; + UINT_8 aucReserved[2]; +} EVENT_ACTIVATE_STA_REC_T, *P_EVENT_ACTIVATE_STA_REC_T; + +typedef struct _EVENT_DEACTIVATE_STA_REC_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_DEACTIVATE_STA_REC_T, *P_EVENT_DEACTIVATE_STA_REC_T; + +/* CMD_BT_OVER_WIFI */ +typedef struct _CMD_BT_OVER_WIFI { + UINT_8 ucAction; /* 0: query, 1: setup, 2: destroy */ + UINT_8 ucChannelNum; + PARAM_MAC_ADDRESS rPeerAddr; + UINT_16 u2BeaconInterval; + UINT_8 ucTimeoutDiscovery; + UINT_8 ucTimeoutInactivity; + UINT_8 ucRole; + UINT_8 PAL_Capabilities; + UINT_8 cMaxTxPower; + UINT_8 ucChannelBand; + UINT_8 ucReserved[1]; +} CMD_BT_OVER_WIFI, *P_CMD_BT_OVER_WIFI; + +/* EVENT_BT_OVER_WIFI */ +typedef struct _EVENT_BT_OVER_WIFI { + UINT_8 ucLinkStatus; + UINT_8 ucSelectedChannel; + INT_8 cRSSI; + UINT_8 ucReserved[1]; +} EVENT_BT_OVER_WIFI, *P_EVENT_BT_OVER_WIFI; + +/* Same with DOMAIN_SUBBAND_INFO */ +typedef struct _CMD_SUBBAND_INFO { + UINT_8 ucRegClass; + UINT_8 ucBand; + UINT_8 ucChannelSpan; + UINT_8 ucFirstChannelNum; + UINT_8 ucNumChannels; + UINT_8 aucReserved[3]; +} CMD_SUBBAND_INFO, *P_CMD_SUBBAND_INFO; + +/* CMD_SET_DOMAIN_INFO */ +typedef struct _CMD_SET_DOMAIN_INFO_T { + UINT_16 u2CountryCode; + UINT_16 u2IsSetPassiveScan; /* 0: set channel domain; 1: set passive scan channel domain */ + CMD_SUBBAND_INFO rSubBand[6]; + + UINT_8 uc2G4Bandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 uc5GBandwidth; /* CONFIG_BW_20_40M or CONFIG_BW_20M */ + UINT_8 aucReserved[2]; +} CMD_SET_DOMAIN_INFO_T, *P_CMD_SET_DOMAIN_INFO_T; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/* CMD_SET_PWR_LIMIT_TABLE */ +typedef struct _CMD_CHANNEL_POWER_LIMIT { + UINT_8 ucCentralCh; + INT_8 cPwrLimitCCK; + INT_8 cPwrLimit20; + INT_8 cPwrLimit40; + INT_8 cPwrLimit80; + INT_8 cPwrLimit160; + UINT_8 ucFlag; + UINT_8 aucReserved[1]; +} CMD_CHANNEL_POWER_LIMIT, *P_CMD_CHANNEL_POWER_LIMIT; + +typedef struct _CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T { + UINT_16 u2CountryCode; + UINT_8 ucCountryFlag; + UINT_8 ucNum; + UINT_8 aucReserved[4]; + CMD_CHANNEL_POWER_LIMIT rChannelPowerLimit[1]; +} CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T, *P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T; + +#endif + +/* CMD_SET_IP_ADDRESS */ +typedef struct _IPV4_NETWORK_ADDRESS { + UINT_8 aucIpAddr[4]; +} IPV4_NETWORK_ADDRESS, *P_IPV4_NETWORK_ADDRESS; + +typedef struct _CMD_SET_NETWORK_ADDRESS_LIST { + UINT_8 ucNetTypeIndex; + UINT_8 ucAddressCount; + UINT_8 ucReserved[2]; + IPV4_NETWORK_ADDRESS arNetAddress[1]; +} CMD_SET_NETWORK_ADDRESS_LIST, *P_CMD_SET_NETWORK_ADDRESS_LIST; + +typedef struct _PATTERN_DESCRIPTION { + UINT_8 fgCheckBcA1; + UINT_8 fgCheckMcA1; + UINT_8 ePatternHeader; + UINT_8 fgAndOp; + UINT_8 fgNotOp; + UINT_8 ucPatternMask; + UINT_16 ucPatternOffset; + UINT_8 aucPattern[8]; +} PATTERN_DESCRIPTION, *P_PATTERN_DESCRIPTION; + +typedef struct _CMD_RAW_PATTERN_CONFIGURATION_T { + PATTERN_DESCRIPTION arPatternDesc[4]; +} CMD_RAW_PATTERN_CONFIGURATION_T, *P_CMD_RAW_PATTERN_CONFIGURATION_T; + +typedef struct _CMD_PATTERN_FUNC_CONFIG { + BOOLEAN fgBcA1En; + BOOLEAN fgMcA1En; + BOOLEAN fgBcA1MatchDrop; + BOOLEAN fgMcA1MatchDrop; +} CMD_PATTERN_FUNC_CONFIG, *P_CMD_PATTERN_FUNC_CONFIG; + +typedef struct _EVENT_TX_DONE_T { + UINT_8 ucPacketSeq; + UINT_8 ucStatus; + UINT_16 u2SequenceNumber; + UINT_32 au4Reserved1; + UINT_32 au4Reserved2; + UINT_32 au4Reserved3; +} EVENT_TX_DONE_T, *P_EVENT_TX_DONE_T; + +typedef struct _CMD_BSS_ACTIVATE_CTRL { + UINT_8 ucNetTypeIndex; + UINT_8 ucActive; + UINT_8 aucReserved[2]; +} CMD_BSS_ACTIVATE_CTRL, *P_CMD_BSS_ACTIVATE_CTRL; + +typedef struct _CMD_SET_BSS_RLM_PARAM_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucRfBand; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucErpProtectMode; + UINT_8 ucHtProtectMode; + UINT_8 ucGfOperationMode; + UINT_8 ucTxRifsMode; + UINT_16 u2HtOpInfo3; + UINT_16 u2HtOpInfo2; + UINT_8 ucHtOpInfo1; + UINT_8 ucUseShortPreamble; + UINT_8 ucUseShortSlotTime; + UINT_8 ucCheckId; /* Fixed value: 0x72 */ +} CMD_SET_BSS_RLM_PARAM_T, *P_CMD_SET_BSS_RLM_PARAM_T; + +typedef struct _CMD_SET_BSS_INFO { + UINT_8 ucNetTypeIndex; + UINT_8 ucConnectionState; + UINT_8 ucCurrentOPMode; + UINT_8 ucSSIDLen; + UINT_8 aucSSID[32]; + UINT_8 aucBSSID[6]; + UINT_8 ucIsQBSS; + UINT_8 ucReserved1; + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucStaRecIdxOfAP; + UINT_8 ucReserved2; + UINT_8 ucReserved3; + UINT_8 ucNonHTBasicPhyType; /* For Slot Time and CWmin */ + UINT_8 ucAuthMode; + UINT_8 ucEncStatus; + UINT_8 ucPhyTypeSet; + UINT_8 aucOwnMac[6]; + UINT_8 fgWapiMode; + UINT_8 fgIsApMode; + UINT_8 fgHiddenSsidMode; + CMD_SET_BSS_RLM_PARAM_T rBssRlmParam; +} CMD_SET_BSS_INFO, *P_CMD_SET_BSS_INFO; + +typedef struct _CMD_UPDATE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucStaType; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_16 u2AssocId; + UINT_16 u2ListenInterval; + UINT_8 ucNetTypeIndex; + UINT_8 ucDesiredPhyTypeSet; + UINT_16 u2DesiredNonHTRateSet; + UINT_16 u2BSSBasicRateSet; + UINT_8 ucIsQoS; + UINT_8 ucIsUapsdSupported; + UINT_8 ucStaState; + UINT_8 ucMcsSet; + UINT_8 ucSupMcs32; + UINT_8 ucAmpduParam; + UINT_16 u2HtCapInfo; + UINT_16 u2HtExtendedCap; + UINT_32 u4TxBeamformingCap; + UINT_8 ucAselCap; + UINT_8 ucRCPI; + UINT_8 ucNeedResp; + UINT_8 ucUapsdAc; /* b0~3: Trigger enabled, b4~7: Delivery enabled */ + UINT_8 ucUapsdSp; /* 0: all, 1: max 2, 2: max 4, 3: max 6 */ + UINT_8 aucReserved[3]; + /* TBD */ +} CMD_UPDATE_STA_RECORD_T, *P_CMD_UPDATE_STA_RECORD_T; + +typedef struct _CMD_REMOVE_STA_RECORD_T { + UINT_8 ucIndex; + UINT_8 ucReserved; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} CMD_REMOVE_STA_RECORD_T, *P_CMD_REMOVE_STA_RECORD_T; + +typedef struct _CMD_INDICATE_PM_BSS_CREATED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 aucReserved[2]; +} CMD_INDICATE_PM_BSS_CREATED, *P_CMD_INDICATE_PM_BSS_CREATED; + +typedef struct _CMD_INDICATE_PM_BSS_CONNECTED_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucDtimPeriod; + UINT_16 u2AssocId; + UINT_16 u2BeaconInterval; + UINT_16 u2AtimWindow; + UINT_8 fgIsUapsdConnection; + UINT_8 ucBmpDeliveryAC; + UINT_8 ucBmpTriggerAC; + UINT_8 aucReserved[1]; +} CMD_INDICATE_PM_BSS_CONNECTED, *P_CMD_INDICATE_PM_BSS_CONNECTED; + +typedef struct _CMD_INDICATE_PM_BSS_ABORT { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[3]; +} CMD_INDICATE_PM_BSS_ABORT, *P_CMD_INDICATE_PM_BSS_ABORT; + +typedef struct _CMD_BEACON_TEMPLATE_UPDATE { + UINT_8 ucUpdateMethod; /* 0: update randomly, + * 1: update all, + * 2: delete all (1 and 2 will update directly without search) + */ + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_16 u2Capability; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_BEACON_TEMPLATE_UPDATE, *P_CMD_BEACON_TEMPLATE_UPDATE; + +typedef struct _CMD_SET_WMM_PS_TEST_STRUCT_T { + UINT_8 ucNetTypeIndex; + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ +} CMD_SET_WMM_PS_TEST_STRUCT_T, *P_CMD_SET_WMM_PS_TEST_STRUCT_T; + +/* Definition for CHANNEL_INFO.ucBand: + * 0: Reserved + * 1: BAND_2G4 + * 2: BAND_5G + * Others: Reserved + */ +typedef struct _CHANNEL_INFO_T { + UINT_8 ucBand; + UINT_8 ucChannelNum; +} CHANNEL_INFO_T, *P_CHANNEL_INFO_T; + +typedef struct _CMD_SCAN_REQ_EXT_CH_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucReserved[1]; + UINT_16 u2ChannelMinDwellTime; + UINT_8 aucSSID[32]; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_EXT_CH, *P_CMD_SCAN_REQ_EXT_CH; + +typedef struct _CMD_SCAN_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; /* BIT(0) wildcard / BIT(1) P2P-wildcard / BIT(2) specific */ + UINT_8 ucSSIDLength; + UINT_8 aucReserved[1]; + UINT_16 u2ChannelMinDwellTime; + UINT_8 aucSSID[32]; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ, *P_CMD_SCAN_REQ; + +typedef struct _CMD_SCAN_REQ_V2_EXT_CH_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[4]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[MAXIMUM_OPERATION_CHANNEL_LIST]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2_EXT_CH, *P_CMD_SCAN_REQ_V2_EXT_CH; + +typedef struct _CMD_SCAN_REQ_V2_T { + UINT_8 ucSeqNum; + UINT_8 ucNetworkType; + UINT_8 ucScanType; + UINT_8 ucSSIDType; + PARAM_SSID_T arSSID[4]; + UINT_16 u2ProbeDelayTime; + UINT_16 u2ChannelDwellTime; /* For P2P */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + CHANNEL_INFO_T arChannelList[32]; + UINT_16 u2IELen; + UINT_8 aucIE[MAX_IE_LENGTH]; +} CMD_SCAN_REQ_V2, *P_CMD_SCAN_REQ_V2; + +typedef struct _CMD_SCAN_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 ucIsExtChannel; /* For P2P channel extension. */ + UINT_8 aucReserved[2]; +} CMD_SCAN_CANCEL, *P_CMD_SCAN_CANCEL; + +typedef struct _EVENT_SCAN_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucSparseChannelValid; + CHANNEL_INFO_T rSparseChannel; +} EVENT_SCAN_DONE, *P_EVENT_SCAN_DONE; + +#if CFG_SUPPORT_GET_CH_ENV +typedef struct _CH_ENV_T { + UINT_8 ucChNum; + UINT_8 ucApNum; +} CH_ENV_T, *P_CH_ENV_T; +#endif + +#if 0 /* CFG_SUPPORT_BATCH_SCAN */ +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* an integer number of highest-strength AP for which we'd + like approximate distance reported */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucAction; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4MaxInterval; /* In unit of ms */ + UINT_8 aucBSSID[6]; + UINT_8 aucReserved[2]; +} CMD_CH_PRIVILEGE_T, *P_CMD_CH_PRIVILEGE_T; + +typedef struct _CMD_TX_PWR_T { + INT_8 cTxPwr2G4Cck; /* signed, in unit of 0.5dBm */ +#if defined(MT6620) + INT_8 acReserved[3]; +#elif defined(MT6628) + INT_8 cTxPwr2G4Dsss; /* signed, in unit of 0.5dBm */ + INT_8 acReserved[2]; +#else +#error "No valid definition!" +#endif + + INT_8 cTxPwr2G4OFDM_BPSK; + INT_8 cTxPwr2G4OFDM_QPSK; + INT_8 cTxPwr2G4OFDM_16QAM; + INT_8 cTxPwr2G4OFDM_Reserved; + INT_8 cTxPwr2G4OFDM_48Mbps; + INT_8 cTxPwr2G4OFDM_54Mbps; + + INT_8 cTxPwr2G4HT20_BPSK; + INT_8 cTxPwr2G4HT20_QPSK; + INT_8 cTxPwr2G4HT20_16QAM; + INT_8 cTxPwr2G4HT20_MCS5; + INT_8 cTxPwr2G4HT20_MCS6; + INT_8 cTxPwr2G4HT20_MCS7; + + INT_8 cTxPwr2G4HT40_BPSK; + INT_8 cTxPwr2G4HT40_QPSK; + INT_8 cTxPwr2G4HT40_16QAM; + INT_8 cTxPwr2G4HT40_MCS5; + INT_8 cTxPwr2G4HT40_MCS6; + INT_8 cTxPwr2G4HT40_MCS7; + + INT_8 cTxPwr5GOFDM_BPSK; + INT_8 cTxPwr5GOFDM_QPSK; + INT_8 cTxPwr5GOFDM_16QAM; + INT_8 cTxPwr5GOFDM_Reserved; + INT_8 cTxPwr5GOFDM_48Mbps; + INT_8 cTxPwr5GOFDM_54Mbps; + + INT_8 cTxPwr5GHT20_BPSK; + INT_8 cTxPwr5GHT20_QPSK; + INT_8 cTxPwr5GHT20_16QAM; + INT_8 cTxPwr5GHT20_MCS5; + INT_8 cTxPwr5GHT20_MCS6; + INT_8 cTxPwr5GHT20_MCS7; + + INT_8 cTxPwr5GHT40_BPSK; + INT_8 cTxPwr5GHT40_QPSK; + INT_8 cTxPwr5GHT40_16QAM; + INT_8 cTxPwr5GHT40_MCS5; + INT_8 cTxPwr5GHT40_MCS6; + INT_8 cTxPwr5GHT40_MCS7; +} CMD_TX_PWR_T, *P_CMD_TX_PWR_T; + +typedef struct _CMD_5G_PWR_OFFSET_T { + INT_8 cOffsetBand0; /* 4.915-4.980G */ + INT_8 cOffsetBand1; /* 5.000-5.080G */ + INT_8 cOffsetBand2; /* 5.160-5.180G */ + INT_8 cOffsetBand3; /* 5.200-5.280G */ + INT_8 cOffsetBand4; /* 5.300-5.340G */ + INT_8 cOffsetBand5; /* 5.500-5.580G */ + INT_8 cOffsetBand6; /* 5.600-5.680G */ + INT_8 cOffsetBand7; /* 5.700-5.825G */ +} CMD_5G_PWR_OFFSET_T, *P_CMD_5G_PWR_OFFSET_T; + +typedef struct _CMD_PWR_PARAM_T { + UINT_32 au4Data[28]; + UINT_32 u4RefValue1; + UINT_32 u4RefValue2; +} CMD_PWR_PARAM_T, *P_CMD_PWR_PARAM_T; + +typedef struct _CMD_PHY_PARAM_T { + UINT_8 aucData[144]; /* eFuse content */ +} CMD_PHY_PARAM_T, *P_CMD_PHY_PARAM_T; + +typedef struct _CMD_AUTO_POWER_PARAM_T { + UINT_8 ucType; /* 0: Disable 1: Enalbe 0x10: Change parameters */ + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 aucLevelRcpiTh[3]; + UINT_8 aucReserved2[1]; + INT_8 aicLevelPowerOffset[3]; /* signed, in unit of 0.5dBm */ + UINT_8 aucReserved3[1]; + UINT_8 aucReserved4[8]; +} CMD_AUTO_POWER_PARAM_T, *P_CMD_AUTO_POWER_PARAM_T; + +typedef struct _EVENT_CH_PRIVILEGE_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucTokenID; + UINT_8 ucStatus; + UINT_8 ucPrimaryChannel; + UINT_8 ucRfSco; + UINT_8 ucRfBand; + UINT_8 ucReqType; + UINT_8 ucReserved; + UINT_32 u4GrantInterval; /* In unit of ms */ +} EVENT_CH_PRIVILEGE_T, *P_EVENT_CH_PRIVILEGE_T; + +typedef enum _ENUM_BEACON_TIMEOUT_TYPE_T { + BEACON_TIMEOUT_LOST_BEACON = 0, + BEACON_TIMEOUT_AGE, + BEACON_TIMEOUT_CONNECT, + BEACON_TIMEOUT_BEACON_INTERVAL, + BEACON_TIMEOUT_ABORT, + BEACON_TIMEOUT_TX_ERROR, + BEACON_TIMEOUT_TYPE_NUM +} ENUM_BEACON_TIMEOUT_TYPE_T, *P_ENUM_BEACON_TIMEOUT_TYPE_T; + +typedef struct _EVENT_BSS_BEACON_TIMEOUT_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucReason; /* ENUM_BEACON_TIMEOUT_TYPE_T */ + UINT_8 aucReserved[2]; +} EVENT_BSS_BEACON_TIMEOUT_T, *P_EVENT_BSS_BEACON_TIMEOUT_T; + +typedef struct _EVENT_STA_AGING_TIMEOUT_T { + UINT_8 ucStaRecIdx; + UINT_8 aucReserved[3]; +} EVENT_STA_AGING_TIMEOUT_T, *P_EVENT_STA_AGING_TIMEOUT_T; + +typedef struct _EVENT_NOA_TIMING_T { + UINT_8 fgIsInUse; /* Indicate if this entry is in use or not */ + UINT_8 ucCount; /* Count */ + UINT_8 aucReserved[2]; + + UINT_32 u4Duration; /* Duration */ + UINT_32 u4Interval; /* Interval */ + UINT_32 u4StartTime; /* Start Time */ +} EVENT_NOA_TIMING_T, *P_EVENT_NOA_TIMING_T; + +typedef struct _EVENT_UPDATE_NOA_PARAMS_T { + UINT_8 ucNetTypeIndex; + UINT_8 aucReserved[2]; + UINT_8 fgEnableOppPS; + UINT_16 u2CTWindow; + + UINT_8 ucNoAIndex; + UINT_8 ucNoATimingCount; /* Number of NoA Timing */ + EVENT_NOA_TIMING_T arEventNoaTiming[8 /*P2P_MAXIMUM_NOA_COUNT */]; +} EVENT_UPDATE_NOA_PARAMS_T, *P_EVENT_UPDATE_NOA_PARAMS_T; + +typedef struct _EVENT_AP_OBSS_STATUS_T { + UINT_8 ucNetTypeIndex; + UINT_8 ucObssErpProtectMode; + UINT_8 ucObssHtProtectMode; + UINT_8 ucObssGfOperationMode; + UINT_8 ucObssRifsOperationMode; + UINT_8 ucObssBeaconForcedTo20M; + UINT_8 aucReserved[2]; +} EVENT_AP_OBSS_STATUS_T, *P_EVENT_AP_OBSS_STATUS_T; + +typedef struct _CMD_EDGE_TXPWR_LIMIT_T { + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + INT_8 cReserved; +} CMD_EDGE_TXPWR_LIMIT_T, *P_CMD_EDGE_TXPWR_LIMIT_T; + +typedef struct _CMD_RSSI_COMPENSATE_T { + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 ucRssiCompensationValidbit; + UINT_8 cReserved; +} CMD_RSSI_COMPENSATE_T, *P_CMD_RSSI_COMPENSATE_T; + +typedef struct _CMD_BAND_SUPPORT_T { + UINT_8 uc5GBandSupport; + UINT_8 cReserved[3]; +} CMD_BAND_SUPPORT_T, *P_CMD_BAND_SUPPORT_T; + +typedef struct _CMD_TX_PWR_CE_T { + INT_8 cTxPwrCckLmt; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwrOfdmLmt; /* signed, in unit of 0.5dBm */ + INT_8 cTxPwrHt20Lmt; + INT_8 cTxPwrHt40Lmt; +} CMD_TX_PWR_CE_T, *P_CMD_TX_PWR_CE_T; + +typedef struct _CMD_SET_DEVICE_MODE_T { + UINT_16 u2ChipID; + UINT_16 u2Mode; +} CMD_SET_DEVICE_MODE_T, *P_CMD_SET_DEVICE_MODE_T; + +#if CFG_SUPPORT_RDD_TEST_MODE +typedef struct _CMD_RDD_CH_T { + UINT_8 ucRddTestMode; + UINT_8 ucRddShutCh; + UINT_8 ucRddStartCh; + UINT_8 ucRddStopCh; + UINT_8 ucRddDfs; + UINT_8 ucReserved; + UINT_8 ucReserved1; + UINT_8 ucReserved2; +} CMD_RDD_CH_T, *P_CMD_RDD_CH_T; + +typedef struct _EVENT_RDD_STATUS_T { + UINT_8 ucRddStatus; + UINT_8 aucReserved[3]; +} EVENT_RDD_STATUS_T, *P_EVENT_RDD_STATUS_T; +#endif + +typedef struct _EVENT_AIS_BSS_INFO_T { + ENUM_PARAM_MEDIA_STATE_T eConnectionState; /* Connected Flag used in AIS_NORMAL_TR */ + ENUM_OP_MODE_T eCurrentOPMode; /* Current Operation Mode - Infra/IBSS */ + BOOLEAN fgIsNetActive; /* TRUE if this network has been actived */ + UINT_8 ucReserved[3]; +} EVENT_AIS_BSS_INFO_T, *P_EVENT_AIS_BSS_INFO_T; + +typedef struct _CMD_SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence + in the same channel + 0: Highest power has priority + 1: Lowest power has priority */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} CMD_SET_TXPWR_CTRL_T, *P_CMD_SET_TXPWR_CTRL_T; + +#if CFG_SUPPORT_BUILD_DATE_CODE +typedef struct _CMD_GET_BUILD_DATE_CODE { + UINT_8 aucReserved[4]; +} CMD_GET_BUILD_DATE_CODE, *P_CMD_GET_BUILD_DATE_CODE; + +typedef struct _EVENT_BUILD_DATE_CODE { + UINT_8 aucDateCode[16]; +} EVENT_BUILD_DATE_CODE, *P_EVENT_BUILD_DATE_CODE; +#endif + +typedef struct _CMD_GET_STA_STATISTICS_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 ucReadClear; + UINT_8 aucReserved0[1]; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_8 aucReserved1[2]; + UINT_8 aucReserved2[16]; +} CMD_GET_STA_STATISTICS_T, *P_CMD_GET_STA_STATISTICS_T; + +/* CFG_SUPPORT_WFD */ +typedef struct _EVENT_STA_STATISTICS_T { + /* Event header */ + /* UINT_16 u2Length; */ + /* UINT_16 u2Reserved1; *//* Must be filled with 0x0001 (EVENT Packet) */ + /* UINT_8 ucEID; */ + /* UINT_8 ucSeqNum; */ + /* UINT_8 aucReserved2[2]; */ + + /* Event Body */ + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + UINT_8 ucStaRecIdx; + UINT_8 ucNetworkTypeIndex; + UINT_8 ucWTEntry; + UINT_8 aucReserved4[1]; + + UINT_8 ucMacAddr[MAC_ADDR_LEN]; + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + + UINT_32 u4PhyMode; /* SGI BW */ + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + UINT_8 ucLinkQuality; + UINT_8 ucLinkReserved; + + UINT_32 u4TxCount; + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxDoneAirTime; + + UINT_8 aucReserved[64]; +} EVENT_STA_STATISTICS_T, *P_EVENT_STA_STATISTICS_T; + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION +typedef struct _CMD_HOTSPOT_OPTIMIZATION_CONFIG { + UINT_32 fgHotspotOptimizationEn; + UINT_32 u4Level; +} CMD_HOTSPOT_OPTIMIZATION_CONFIG, *P_HOTSPOT_OPTIMIZATION_CONFIG; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + +/* 4 Auto Channel Selection */ + +typedef struct _CMD_GET_CHN_LOAD_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 ucReadClear; + UINT_8 aucReserved0[1]; + + UINT_8 ucChannel; + UINT_16 u2ChannelLoad; + UINT_8 aucReserved1[1]; + UINT_8 aucReserved2[16]; +} CMD_GET_CHN_LOAD_T, *P_CMD_GET_CHN_LOAD_T; +/* 4 Auto Channel Selection */ + +typedef struct _EVENT_CHN_LOAD_T { + /* Event Body */ + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + UINT_8 ucChannel; + UINT_16 u2ChannelLoad; + UINT_8 aucReserved4[1]; + + UINT_8 aucReserved[64]; + +} EVENT_CHN_LOAD_T, *P_EVENT_CHN_LOAD_T; +typedef struct _CMD_GET_LTE_SAFE_CHN_T { + UINT_8 ucIndex; + UINT_8 ucFlags; + UINT_8 aucReserved0[2]; + + UINT_8 aucReserved2[16]; +} CMD_GET_LTE_SAFE_CHN_T, *P_CMD_GET_LTE_SAFE_CHN_T; + +typedef struct _EVENT_LTE_MODE_T { + /* Event Body */ + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + LTE_SAFE_CH_INFO_T rLteSafeChn; + UINT_8 aucReserved4[3]; + + UINT_8 aucReserved[4]; + +} EVENT_LTE_MODE_T, *P_EVENT_LTE_MODE_T; +#endif +typedef struct _CMD_ROAMING_INFO_T { + UINT_32 fgIsFastRoamingApplied; + UINT_32 Reserved[9]; +} CMD_ROAMING_INFO_T; + +typedef struct _CMD_WFD_DEBUG_MODE_INFO_T { + UINT_8 ucDebugMode; + UINT_16 u2PeriodInteval; + UINT_8 Reserved; +} CMD_WFD_DEBUG_MODE_INFO_T, *P_CMD_WFD_DEBUG_MODE_INFO_T; + +typedef struct _EVENT_FW_LOG_T { + UINT_8 fileName[64]; + UINT_32 lineNo; + UINT_32 WifiUpTime; + UINT_8 log[896]; /* total size is aucBuffer in WIFI_EVENT_T */ +} EVENT_FW_LOG_T, *P_EVENT_FW_LOG_T; + +typedef enum _ENUM_NLO_CIPHER_ALGORITHM { + NLO_CIPHER_ALGO_NONE = 0x00, + NLO_CIPHER_ALGO_WEP40 = 0x01, + NLO_CIPHER_ALGO_TKIP = 0x02, + NLO_CIPHER_ALGO_CCMP = 0x04, + NLO_CIPHER_ALGO_WEP104 = 0x05, + NLO_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + NLO_CIPHER_ALGO_WEP = 0x101, +} ENUM_NLO_CIPHER_ALGORITHM, *P_ENUM_NLO_CIPHER_ALGORITHM; + +typedef enum _ENUM_NLO_AUTH_ALGORITHM { + NLO_AUTH_ALGO_80211_OPEN = 1, + NLO_AUTH_ALGO_80211_SHARED_KEY = 2, + NLO_AUTH_ALGO_WPA = 3, + NLO_AUTH_ALGO_WPA_PSK = 4, + NLO_AUTH_ALGO_WPA_NONE = 5, + NLO_AUTH_ALGO_RSNA = 6, + NLO_AUTH_ALGO_RSNA_PSK = 7, +} ENUM_NLO_AUTH_ALGORITHM, *P_ENUM_NLO_AUTH_ALGORITHM; + +typedef struct _NLO_NETWORK { + UINT_8 ucNumChannelHint[4]; + UINT_8 ucSSIDLength; + UINT_8 ucCipherAlgo; + UINT_16 u2AuthAlgo; + UINT_8 aucSSID[32]; +} NLO_NETWORK, *P_NLO_NETWORK; + +typedef struct _CMD_NLO_REQ { + UINT_8 ucSeqNum; + UINT_8 ucBssIndex; + UINT_8 ucNetworkType; + UINT_8 fgStopAfterIndication; + UINT_8 ucFastScanIteration; + UINT_16 u2FastScanPeriod; + UINT_16 u2SlowScanPeriod; + UINT_8 ucEntryNum; + UINT_8 ucReserved; + UINT_16 u2IELen; + NLO_NETWORK arNetworkList[16]; + UINT_8 aucIE[0]; + UINT_8 ucScanType; +} CMD_NLO_REQ, *P_CMD_NLO_REQ; + +typedef struct _CMD_NLO_CANCEL_T { + UINT_8 ucSeqNum; + UINT_8 aucReserved[3]; +} CMD_NLO_CANCEL, *P_CMD_NLO_CANCEL; + +typedef struct _EVENT_NLO_DONE_T { + UINT_8 ucSeqNum; + UINT_8 ucStatus; + UINT_8 aucReserved[2]; +} EVENT_NLO_DONE_T, *P_EVENT_NLO_DONE_T; + +typedef struct _EVENT_GSCAN_CAPABILITY_T { + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4MaxScanCacheSize; + UINT_32 u4MaxScanBuckets; + UINT_32 u4MaxApCachePerScan; + UINT_32 u4MaxRssiSampleSize; + UINT_32 u4MaxScanReportingThreshold; + UINT_32 u4MaxHotlistAps; + UINT_32 u4MaxSignificantWifiChangeAps; + UINT_32 au4Reserved[4]; +} EVENT_GSCAN_CAPABILITY_T, *P_EVENT_GSCAN_CAPABILITY_T; + +typedef struct _EVENT_GSCAN_SCAN_AVAILABLE_T { + UINT_16 u2Num; + UINT_8 aucReserved[2]; +} EVENT_GSCAN_SCAN_AVAILABLE_T, *P_EVENT_GSCAN_SCAN_AVAILABLE_T; + +typedef struct _EVENT_GSCAN_SCAN_COMPLETE_T { + UINT_8 ucScanState; + UINT_8 aucReserved[3]; +} EVENT_GSCAN_SCAN_COMPLETE_T, *P_EVENT_GSCAN_SCAN_COMPLETE_T; + +typedef struct WIFI_GSCAN_RESULT { + UINT_64 u8Ts; /* Time of discovery */ + UINT_8 arSsid[ELEM_MAX_LEN_SSID + 1]; /* null terminated */ + UINT_8 arMacAddr[6]; /* BSSID */ + UINT_32 u4Channel; /* channel frequency in MHz */ + INT_32 i4Rssi; /* in db */ + UINT_64 u8Rtt; /* in nanoseconds */ + UINT_64 u8RttSd; /* standard deviation in rtt */ + UINT_16 u2BeaconPeriod; /* units are Kusec */ + UINT_16 u2Capability; /* Capability information */ + UINT_32 u4IeLength; /* byte length of Information Elements */ + UINT_8 ucIeData[1]; /* IE data to follow */ +} WIFI_GSCAN_RESULT_T, *P_WIFI_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_RESULT_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + UINT_16 u2ScanId; + UINT_16 u2ScanFlags; + UINT_16 u2NumOfResults; + WIFI_GSCAN_RESULT_T rResult[1]; +} EVENT_GSCAN_RESULT_T, *P_EVENT_GSCAN_RESULT_T; + +typedef struct _EVENT_GSCAN_FULL_RESULT_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + WIFI_GSCAN_RESULT_T rResult; +} EVENT_GSCAN_FULL_RESULT_T, *P_EVENT_GSCAN_FULL_RESULT_T; + +typedef struct GSCAN_SWC_NET { + UINT_16 u2Flags; + UINT_16 u2Channel; + UINT_8 arBssid[6]; + INT_8 aicRssi[SCN_PSCAN_SWC_RSSI_WIN_MAX]; +} GSCAN_SWC_NET_T, P_GSCAN_SWC_NET_T; + +typedef struct _EVENT_GSCAN_SIGNIFICANT_CHANGE_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + GSCAN_SWC_NET_T arNet[SCN_PSCAN_SWC_MAX_NUM]; +} EVENT_GSCAN_SIGNIFICANT_CHANGE_T, *P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T; + +typedef struct _EVENT_GSCAN_GEOFENCE_FOUND_T { + UINT_8 ucVersion; + UINT_8 aucReserved[3]; + WIFI_GSCAN_RESULT_T rResult[SCN_PSCAN_HOTLIST_REPORT_MAX_NUM]; +} EVENT_GSCAN_GEOFENCE_FOUND_T, *P_EVENT_GSCAN_GEOFENCE_FOUND_T; + +#if CFG_SUPPORT_BATCH_SCAN + +#if 0 /* !CFG_SUPPORT_GSCN */ +typedef struct _CMD_BATCH_REQ_T { + UINT_8 ucSeqNum; + UINT_8 ucNetTypeIndex; + UINT_8 ucCmd; /* Start/ Stop */ + UINT_8 ucMScan; /* an integer number of scans per batch */ + UINT_8 ucBestn; /* an integer number of the max AP to remember per scan */ + UINT_8 ucRtt; /* an integer number of highest-strength AP for which + we'd like approximate distance reported */ + UINT_8 ucChannel; /* channels */ + UINT_8 ucChannelType; + UINT_8 ucChannelListNum; + UINT_8 aucReserved[3]; + UINT_32 u4Scanfreq; /* an integer number of seconds between scans */ + CHANNEL_INFO_T arChannelList[32]; /* channels */ +} CMD_BATCH_REQ_T, *P_CMD_BATCH_REQ_T; + +#endif + +typedef struct _EVENT_BATCH_RESULT_ENTRY_T { + UINT_8 aucBssid[MAC_ADDR_LEN]; + UINT_8 aucSSID[ELEM_MAX_LEN_SSID]; + UINT_8 ucSSIDLen; + INT_8 cRssi; + UINT_32 ucFreq; + UINT_32 u4Age; + UINT_32 u4Dist; + UINT_32 u4Distsd; +} EVENT_BATCH_RESULT_ENTRY_T, *P_EVENT_BATCH_RESULT_ENTRY_T; + +typedef struct _EVENT_BATCH_RESULT_T { + UINT_8 ucScanCount; + UINT_8 aucReserved[3]; + EVENT_BATCH_RESULT_ENTRY_T arBatchResult[12]; /* Must be the same with SCN_BATCH_STORE_MAX_NUM */ +} EVENT_BATCH_RESULT_T, *P_EVENT_BATCH_RESULT_T; +#endif + +typedef struct _CMD_RLM_INFO_T { + UINT_32 u4Version; + UINT_32 fgIsErrRatioEnhanceApplied; + UINT_8 ucErrRatio2LimitMinRate; + /* + 0:1M, 1:2M, 2:5.5M, 3:11M, 6:6M, 7:9M, 8:12M, 9:18M, 10:24M, 11:36M, 12:48M, 13:54M + */ + UINT_8 ucMinLegacyRateIdx; + INT_8 cMinRssiThreshold; + BOOLEAN fgIsRtsApplied; + UINT_8 ucRecoverTime; + + UINT_32 u4Reserved[0]; +} CMD_RLM_INFO_T; + +typedef struct _WIFI_SYSTEM_SUSPEND_CMD_T { + BOOLEAN fgIsSystemSuspend; + UINT_8 reserved[3]; +} WIFI_SYSTEM_SUSPEND_CMD_T, *P_WIFI_SYSTEM_SUSPEND_CMD_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* Statistics responder */ +VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/* for timeout check */ +VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +#if CFG_SUPPORT_BUILD_DATE_CODE +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +/* 4 Auto Channel Selection */ +VOID nicCmdEventQueryChannelLoad(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID nicCmdEventQueryLTESafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); +#endif + +VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h new file mode 100644 index 0000000000000..994c589190dee --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/nic_init_cmd_event.h @@ -0,0 +1,177 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/nic_init_cmd_event.h#1 +*/ + +/*! \file "nic_init_cmd_event.h" + \brief This file contains the declairation file of the WLAN initialization routines + for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: nic_init_cmd_event.h + * + * 09 26 2011 cp.wu + * [WCXRP00001011] [MT6628 Wi-Fi] Firmware Download Agent: make CRC validation as an optional feature + * add definition for disabling CRC32 validation (for MT6628 only) + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 03 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add command/event definitions for initial states + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * +*/ +#ifndef _NIC_INIT_CMD_EVENT_H +#define _NIC_INIT_CMD_EVENT_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define INIT_CMD_STATUS_SUCCESS 0 +#define INIT_CMD_STATUS_REJECTED_INVALID_PARAMS 1 +#define INIT_CMD_STATUS_REJECTED_CRC_ERROR 2 +#define INIT_CMD_STATUS_REJECTED_DECRYPT_FAIL 3 +#define INIT_CMD_STATUS_UNKNOWN 4 + +#define EVENT_HDR_SIZE OFFSET_OF(WIFI_EVENT_T, aucBuffer[0]) + +typedef enum _ENUM_INIT_CMD_ID { + INIT_CMD_ID_DOWNLOAD_BUF = 1, + INIT_CMD_ID_WIFI_START, + INIT_CMD_ID_ACCESS_REG, + INIT_CMD_ID_QUERY_PENDING_ERROR +} ENUM_INIT_CMD_ID, *P_ENUM_INIT_CMD_ID; + +typedef enum _ENUM_INIT_EVENT_ID { + INIT_EVENT_ID_CMD_RESULT = 1, + INIT_EVENT_ID_ACCESS_REG, + INIT_EVENT_ID_PENDING_ERROR +} ENUM_INIT_EVENT_ID, *P_ENUM_INIT_EVENT_ID; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_8 CMD_STATUS; + +/* commands */ +typedef struct _INIT_WIFI_CMD_T { + UINT_8 ucCID; + UINT_8 ucSeqNum; + UINT_16 u2Reserved; + UINT_8 aucBuffer[0]; +} INIT_WIFI_CMD_T, *P_INIT_WIFI_CMD_T; + +typedef struct _INIT_HIF_TX_HEADER_T { + UINT_16 u2TxByteCount; + UINT_8 ucEtherTypeOffset; + UINT_8 ucCSflags; + INIT_WIFI_CMD_T rInitWifiCmd; +} INIT_HIF_TX_HEADER_T, *P_INIT_HIF_TX_HEADER_T; + +#define DOWNLOAD_BUF_ENCRYPTION_MODE BIT(0) +#define DOWNLOAD_BUF_NO_CRC_CHECKING BIT(30) +#define DOWNLOAD_BUF_ACK_OPTION BIT(31) +typedef struct _INIT_CMD_DOWNLOAD_BUF { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4CRC32; + UINT_32 u4DataMode; + UINT_8 aucBuffer[0]; +} INIT_CMD_DOWNLOAD_BUF, *P_INIT_CMD_DOWNLOAD_BUF; + +typedef struct _INIT_CMD_WIFI_START { + UINT_32 u4Override; + UINT_32 u4Address; +} INIT_CMD_WIFI_START, *P_INIT_CMD_WIFI_START; + +typedef struct _INIT_CMD_ACCESS_REG { + UINT_8 ucSetQuery; + UINT_8 aucReserved[3]; + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_CMD_ACCESS_REG, *P_INIT_CMD_ACCESS_REG; + +/* Events */ +typedef struct _INIT_WIFI_EVENT_T { + UINT_16 u2RxByteCount; + UINT_8 ucEID; + UINT_8 ucSeqNum; + UINT_8 aucBuffer[0]; +} INIT_WIFI_EVENT_T, *P_INIT_WIFI_EVENT_T; + +typedef struct _INIT_HIF_RX_HEADER_T { + INIT_WIFI_EVENT_T rInitWifiEvent; +} INIT_HIF_RX_HEADER_T, *P_INIT_HIF_RX_HEADER_T; + +typedef struct _INIT_EVENT_CMD_RESULT { + UINT_8 ucStatus; /* 0: success */ + /* 1: rejected by invalid param */ + /* 2: rejected by incorrect CRC */ + /* 3: rejected by decryption failure */ + /* 4: unknown CMD */ + UINT_8 aucReserved[3]; +} INIT_EVENT_CMD_RESULT, *P_INIT_EVENT_CMD_RESULT, INIT_EVENT_PENDING_ERROR, *P_INIT_EVENT_PENDING_ERROR; + +typedef struct _INIT_EVENT_ACCESS_REG { + UINT_32 u4Address; + UINT_32 u4Data; +} INIT_EVENT_ACCESS_REG, *P_INIT_EVENT_ACCESS_REG; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _NIC_INIT_CMD_EVENT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h new file mode 100644 index 0000000000000..85af819f4e624 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_precomp.h @@ -0,0 +1,201 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/p2p_precomp.h#1 +*/ + +/*! \file p2p_precomp.h + \brief Collection of most compiler flags for p2p driver are described here. + + In this file we collect all compiler flags and detail the p2p driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + +#ifndef _P2P_PRECOMP_H +#define _P2P_PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" /* Include "config.h" */ + +#include "gl_p2p_os.h" + +#include "debug.h" + +#include "link.h" +#include "queue.h" + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ +#include "wlan_typedef.h" + +#include "mac.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "wlan_def.h" + +#include "roaming_fsm.h" + +/*------------------------------------------------------------------------------ + * .\include\nic + *------------------------------------------------------------------------------ + */ +/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ +#include "cmd_buf.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "nic_cmd_event.h" + +/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ +#include "nic.h" + +#include "nic_init_cmd_event.h" + +#include "hif_rx.h" +#include "hif_tx.h" + +#include "nic_tx.h" + +/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ +#include "nic_rx.h" + +#include "que_mgt.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#include "wlan_p2p.h" + +#include "hal.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" + +#include "aa_fsm.h" + +#include "cnm_timer.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +/* Dependency: cnm_timer.h (TIMER_T) */ +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + +#include "ais_fsm.h" + +#include "adapter.h" + +#include "que_mgt.h" +#include "rftest.h" + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#include "gl_p2p_kal.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /*_P2P_PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h new file mode 100644 index 0000000000000..a02d391d36430 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/p2p_typedef.h @@ -0,0 +1,165 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/p2p_typedef.h#1 +*/ + +/*! \file p2p_typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to all MGMT Protocol Stack. +*/ + +#ifndef _P2P_TYPEDEF_H +#define _P2P_TYPEDEF_H + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* +* type definition of pointer to p2p structure +*/ +/* typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; */ +typedef struct _P2P_INFO_T P2P_INFO_T, *P_P2P_INFO_T; + +typedef struct _P2P_FSM_INFO_T P2P_FSM_INFO_T, *P_P2P_FSM_INFO_T; + +typedef struct _P2P_CONNECTION_SETTINGS_T P2P_CONNECTION_SETTINGS_T, *P_P2P_CONNECTION_SETTINGS_T; + +/* Type definition for function pointer to p2p function*/ +typedef BOOLEAN(*P2P_LAUNCH) (P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*P2P_REMOVE) (P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsWlanLaunched); + +typedef BOOLEAN(*KAL_P2P_GET_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_TKIP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_CCMP_CIPHER) (IN P_GLUE_INFO_T prGlueInfo); + +typedef BOOLEAN(*KAL_P2P_GET_WSC_MODE) (IN P_GLUE_INFO_T prGlueInfo); + +typedef struct net_device *(*KAL_P2P_GET_DEV_HDLR) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*KAL_P2P_SET_MULTICAST_WORK_ITEM) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*P2P_NET_REGISTER) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*P2P_NET_UNREGISTER) (P_GLUE_INFO_T prGlueInfo); + +typedef VOID(*KAL_P2P_UPDATE_ASSOC_INFO) (IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, + IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +typedef BOOLEAN(*P2P_VALIDATE_AUTH) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +typedef BOOLEAN(*P2P_VALIDATE_ASSOC_REQ) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu4ControlFlags); + +typedef VOID(*P2P_RUN_EVENT_AAA_TX_FAIL) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +typedef BOOLEAN(*P2P_PARSE_CHECK_FOR_P2P_INFO_ELEM) (IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType); + +typedef WLAN_STATUS(*P2P_RUN_EVENT_AAA_COMPLETE) (IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +typedef VOID(*P2P_PROCESS_EVENT_UPDATE_NOA_PARAM) (IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam); + +typedef VOID(*SCAN_P2P_PROCESS_BEACON_AND_PROBE_RESP) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, + IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame); + +typedef VOID(*P2P_RX_PUBLIC_ACTION_FRAME) (P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_RSP_GENERATE_OBSS_SCAN_IE) (P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo); + +typedef VOID(*RLM_UPDATE_BW_BY_CH_LIST_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +typedef VOID(*RLM_PROCESS_PUBLIC_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_PROCESS_HT_ACTION) (P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb); + +typedef VOID(*RLM_UPDATE_PARAMS_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon); + +typedef VOID(*RLM_HANDLE_OBSS_STATUS_EVENT_PKT) (P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus); + +typedef BOOLEAN(*P2P_FUNC_VALIDATE_PROBE_REQ) (IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +typedef VOID(*RLM_BSS_INIT_FOR_AP) (P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +typedef UINT_32(*P2P_GET_PROB_RSP_IE_TABLE_SIZE) (VOID); + +typedef PUINT_8(*P2P_BUILD_REASSOC_REQ_FRAME_COMMON_IES) (IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer); + +typedef VOID(*P2P_FUNC_DISCONNECT) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode); + +typedef VOID(*P2P_FSM_RUN_EVENT_RX_DEAUTH) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*P2P_FSM_RUN_EVENT_RX_DISASSOC) (IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +typedef BOOLEAN(*P2P_FUN_IS_AP_MODE) (IN P_P2P_FSM_INFO_T prP2pFsmInfo); + +typedef VOID(*P2P_FSM_RUN_EVENT_BEACON_TIMEOUT) (IN P_ADAPTER_T prAdapter); + +typedef VOID(*P2P_FUNC_STORE_ASSOC_RSP_IE_BUFFER) (IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb); + +typedef VOID(*P2P_GENERATE_P2P_IE) (IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +typedef UINT_32(*P2P_CALCULATE_P2P_IE_LEN) (IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /*CFG_ENABLE_WIFI_DIRECT */ + +#endif /* _P2P_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h new file mode 100644 index 0000000000000..1b7e7ede66e1a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/precomp.h @@ -0,0 +1,388 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/precomp.h#2 +*/ + +/*! \file precomp.h + \brief Collection of most compiler flags are described here. + + In this file we collect all compiler flags and detail the driver behavior if + enable/disable such switch or adjust numeric parameters. +*/ + +/* +** Log: precomp.h + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628-specific definitions. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Isolate P2P related function for Hardware Software Bundle + * + * 09 14 2010 chinghwa.yu + * NULL + * Fix BOW_FSM_INFO_T dependence. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 28 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * 1st draft code for RLM module + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge cnm_scan.h and hem_mbox.h + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 03 16 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * build up basic data structure and definitions to support BT-over-WiFi + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 11:30:58 GMT mtk02752 +** add rftest.h for implementing RF test mode in driver land +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-11-23 22:02:00 GMT mtk02468 +** Added que_mgt.h +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-10-13 21:58:36 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-21 09:40:11 GMT mtk01461 +** Add nic_cmd_event.h +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-17 20:00:26 GMT mtk01461 +** Add cmd_buf.h +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-19 18:32:44 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:25 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:38 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _PRECOMP_H +#define _PRECOMP_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" /* Include "config.h" */ + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +#include "debug.h" + +#include "link.h" +#include "queue.h" + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ +#include "wlan_typedef.h" + +#include "mac.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "wlan_def.h" + +#if CFG_SUPPORT_SWCR +#include "swcr.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\nic + *------------------------------------------------------------------------------ + */ +/* Dependency: wlan_def.h (ENUM_NETWORK_TYPE_T) */ +#include "cmd_buf.h" + +/* Dependency: mac.h (MAC_ADDR_LEN) */ +#include "nic_cmd_event.h" + +/* Dependency: nic_cmd_event.h (P_EVENT_CONNECTION_STATUS) */ +#include "nic.h" + +#include "nic_init_cmd_event.h" + +#include "hif_rx.h" +#include "hif_tx.h" + +#include "nic_tx.h" + +/* Dependency: hif_rx.h (P_HIF_RX_HEADER_T) */ +#include "nic_rx.h" + +#include "que_mgt.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_typedef.h" +#include "p2p_cmd_buf.h" +#include "p2p_nic_cmd_event.h" +#include "p2p_mac.h" +#include "p2p_nic.h" +#endif + +/*------------------------------------------------------------------------------ + * .\include\mgmt + *------------------------------------------------------------------------------ + */ + +#include "hem_mbox.h" + +#include "scan.h" +#include "bss.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_bow.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "wlan_p2p.h" +#endif + +#include "hal.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#elif defined(MT6628) +/* #include "mt6628_reg.h" */ +#include "mtreg.h" +#endif + +#include "rlm.h" +#include "rlm_domain.h" +#include "rlm_protection.h" +#include "rlm_obss.h" +#include "rate.h" +#if CFG_SUPPORT_802_11V +#include "wnm.h" +#endif + +#include "aa_fsm.h" + +#include "cnm_timer.h" + +#if CFG_ENABLE_BT_OVER_WIFI +#include "bow.h" +#include "bow_fsm.h" +#endif + +#include "pwr_mgt.h" + +#if (CFG_SUPPORT_STATISTICS == 1) +#include "stats.h" +#endif /* CFG_SUPPORT_STATISTICS */ + +#include "cnm.h" +/* Dependency: aa_fsm.h (ENUM_AA_STATE_T), p2p_fsm.h (WPS_ATTRI_MAX_LEN_DEVICE_NAME) */ +#include "cnm_mem.h" +#include "cnm_scan.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "p2p_rlm_obss.h" +#include "p2p_bss.h" +#include "p2p.h" +#include "p2p_fsm.h" +#include "p2p_scan.h" +#include "p2p_state.h" +#include "p2p_func.h" +#include "p2p_rlm.h" +#include "p2p_assoc.h" +#include "p2p_ie.h" +#endif + +#include "privacy.h" + +#include "mib.h" + +#include "auth.h" +#include "assoc.h" + +#if CFG_SUPPORT_ROAMING +#include "roaming_fsm.h" +#endif /* CFG_SUPPORT_ROAMING */ + +#include "ais_fsm.h" + +#include "adapter.h" + +#include "que_mgt.h" +#include "rftest.h" + +#if CFG_RSN_MIGRATION +#include "rsn.h" +#include "sec_fsm.h" +#endif + +#if CFG_SUPPORT_WAPI +#include "wapi.h" +#endif + +/*------------------------------------------------------------------------------ + * NVRAM structure + *------------------------------------------------------------------------------ + */ +#include "CFG_Wifi_File.h" + +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_kal.h" +#endif + +typedef int (*set_p2p_mode) (struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +typedef void (*set_dbg_level) (unsigned char modules[DBG_MODULE_NUM]); + +extern void wlanRegisterNotifier(void); +extern void wlanUnregisterNotifier(void); +extern void register_set_p2p_mode_handler(set_p2p_mode handler); +extern void register_set_dbg_level_handler(set_dbg_level handler); + +#if CFG_TC1_FEATURE +#define NIC_INF_NAME_IN_AP_MODE "legacy%d" +extern volatile int wlan_if_changed; +#endif +extern BOOLEAN fgIsResetting; + +extern UINT_8 g_aucBufIpAddr[32]; +extern UINT_8 aucDebugModule[]; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PRECOMP_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h new file mode 100644 index 0000000000000..40f52dcc9d681 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/pwr_mgt.h @@ -0,0 +1,141 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/pwr_mgt.h#1 +*/ + +/*! \file "pwr_mgt.h" + \brief In this file we define the STATE and EVENT for Power Management FSM. + + The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter + ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail + description. +*/ + +/* +** Log: pwr_mgt.h + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL + * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. + + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * firmware download load address & start address are now configured from config.h + * * * due to the different configurations on FPGA and ASIC +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-10 16:39:10 GMT mtk02752 +** disable PM macros temporally +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-29 19:48:37 GMT mtk01084 +** temp remove power management macro +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-08 16:51:11 GMT mtk01084 +** update for power management control macro +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-04-03 14:59:58 GMT mtk01426 +** Add #if CFG_HIF_LOOPBACK_PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:53:10 GMT mtk01084 +** modify ACQUIRE_POWER_CONTROL_FROM_PM() and RECLAIM_POWER_CONTROL_TO_PM() macro +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:32:47 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:20 GMT mtk01084 +** Initial version +** +*/ + +#ifndef _PWR_MGT_H +#define _PWR_MGT_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define PM_UAPSD_AC0 (BIT(0)) +#define PM_UAPSD_AC1 (BIT(1)) +#define PM_UAPSD_AC2 (BIT(2)) +#define PM_UAPSD_AC3 (BIT(3)) + +#define PM_UAPSD_ALL (PM_UAPSD_AC0 | PM_UAPSD_AC1 | PM_UAPSD_AC2 | PM_UAPSD_AC3) +#define PM_UAPSD_NONE 0 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PM_PROFILE_SETUP_INFO_T { + /* Profile setup */ + UINT_8 ucBmpDeliveryAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + UINT_8 ucBmpTriggerAC; /* 0: AC_BE, 1: AC_BK, 2: AC_VI, 3: AC_VO */ + + UINT_8 ucUapsdSp; /* Number of triggered packets in UAPSD */ + +} PM_PROFILE_SETUP_INFO_T, *P_PM_PROFILE_SETUP_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if !CFG_ENABLE_FULL_PM +#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) +#else +#define ACQUIRE_POWER_CONTROL_FROM_PM(_prAdapter) \ + { \ + if (_prAdapter->fgIsFwOwn) { \ + nicpmSetDriverOwn(_prAdapter); \ + } \ + /* Increase Block to Enter Low Power Semaphore count */ \ + GLUE_INC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + } + +#define RECLAIM_POWER_CONTROL_TO_PM(_prAdapter, _fgEnableGINT_in_IST) \ + { \ + ASSERT(_prAdapter->u4PwrCtrlBlockCnt != 0); \ + /* Decrease Block to Enter Low Power Semaphore count */ \ + GLUE_DEC_REF_CNT(_prAdapter->u4PwrCtrlBlockCnt); \ + if (_prAdapter->fgWiFiInSleepyState && (_prAdapter->u4PwrCtrlBlockCnt == 0)) { \ + nicpmSetFWOwn(_prAdapter, _fgEnableGINT_in_IST); \ + } \ + } +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _PWR_MGT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h new file mode 100644 index 0000000000000..a9e74b58a8c97 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/queue.h @@ -0,0 +1,195 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/queue.h#1 +*/ + +/*! \file queue.h + \brief Definition for singly queue operations. + + In this file we define the singly queue data structure and its + queue operation MACROs. +*/ + +/* +** Log: queue.h + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:46 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _QUEUE_H +#define _QUEUE_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Singly Queue Structures - Entry Part */ +typedef struct _QUE_ENTRY_T { + struct _QUE_ENTRY_T *prNext; + struct _QUE_ENTRY_T *prPrev; /* For Rx buffer reordering used only */ +} QUE_ENTRY_T, *P_QUE_ENTRY_T; + +/* Singly Queue Structures - Queue Part */ +typedef struct _QUE_T { + P_QUE_ENTRY_T prHead; + P_QUE_ENTRY_T prTail; + UINT_32 u4NumElem; +} QUE_T, *P_QUE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/* + * To resolve compiler warning of address check -Waddress + * Redefine a ASSERT dedicate for queue operation + */ +#if DBG +#define QUE_ASSERT ASSERT +#else +#define QUE_ASSERT(_exp) +#endif + +#define QUEUE_INITIALIZE(prQueue) \ + { \ + (prQueue)->prHead = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + (prQueue)->u4NumElem = 0; \ + } + +#define QUEUE_IS_EMPTY(prQueue) (((P_QUE_T)(prQueue))->prHead == (P_QUE_ENTRY_T)NULL) + +#define QUEUE_IS_NOT_EMPTY(prQueue) ((prQueue)->u4NumElem > 0) + +#define QUEUE_GET_HEAD(prQueue) ((prQueue)->prHead) + +#define QUEUE_GET_TAIL(prQueue) ((prQueue)->prTail) + +#define QUEUE_GET_NEXT_ENTRY(prQueueEntry) ((prQueueEntry)->prNext) + +#define QUEUE_INSERT_HEAD(prQueue, prQueueEntry) \ + { \ + QUE_ASSERT(prQueue); \ + QUE_ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (prQueue)->prHead; \ + (prQueue)->prHead = (prQueueEntry); \ + if ((prQueue)->prTail == (P_QUE_ENTRY_T)NULL) { \ + (prQueue)->prTail = (prQueueEntry); \ + } \ + ((prQueue)->u4NumElem)++; \ + } + +#define QUEUE_INSERT_TAIL(prQueue, prQueueEntry) \ + { \ + QUE_ASSERT(prQueue); \ + QUE_ASSERT(prQueueEntry); \ + (prQueueEntry)->prNext = (P_QUE_ENTRY_T)NULL; \ + if ((prQueue)->prTail) { \ + ((prQueue)->prTail)->prNext = (prQueueEntry); \ + } else { \ + (prQueue)->prHead = (prQueueEntry); \ + } \ + (prQueue)->prTail = (prQueueEntry); \ + ((prQueue)->u4NumElem)++; \ + } + +/* NOTE: We assume the queue entry located at the beginning of "prQueueEntry Type", + * so that we can cast the queue entry to other data type without doubts. + * And this macro also decrease the total entry count at the same time. + */ +#define QUEUE_REMOVE_HEAD(prQueue, prQueueEntry, _P_TYPE) \ + { \ + QUE_ASSERT(prQueue); \ + prQueueEntry = (_P_TYPE)((prQueue)->prHead); \ + if (prQueueEntry) { \ + (prQueue)->prHead = ((P_QUE_ENTRY_T)(prQueueEntry))->prNext; \ + if ((prQueue)->prHead == (P_QUE_ENTRY_T)NULL) { \ + (prQueue)->prTail = (P_QUE_ENTRY_T)NULL; \ + } \ + ((P_QUE_ENTRY_T)(prQueueEntry))->prNext = (P_QUE_ENTRY_T)NULL; \ + ((prQueue)->u4NumElem)--; \ + } \ + } + +#define QUEUE_MOVE_ALL(prDestQueue, prSrcQueue) \ + { \ + QUE_ASSERT(prDestQueue); \ + QUE_ASSERT(prSrcQueue); \ + *(P_QUE_T)prDestQueue = *(P_QUE_T)prSrcQueue; \ + QUEUE_INITIALIZE(prSrcQueue); \ + } + +#define QUEUE_CONCATENATE_QUEUES(prDestQueue, prSrcQueue) \ + { \ + QUE_ASSERT(prDestQueue); \ + QUE_ASSERT(prSrcQueue); \ + if (prSrcQueue->u4NumElem > 0) { \ + if ((prDestQueue)->prTail) { \ + ((prDestQueue)->prTail)->prNext = (prSrcQueue)->prHead; \ + } else { \ + (prDestQueue)->prHead = (prSrcQueue)->prHead; \ + } \ + (prDestQueue)->prTail = (prSrcQueue)->prTail; \ + ((prDestQueue)->u4NumElem) += ((prSrcQueue)->u4NumElem); \ + QUEUE_INITIALIZE(prSrcQueue); \ + } \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _QUEUE_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h new file mode 100644 index 0000000000000..4489e56013025 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/rftest.h @@ -0,0 +1,294 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/rftest.h#1 +*/ + +/*! \file "rftest.h" + \brief definitions for RF Productino test + +*/ + +/* +** Log: rftest.h + * + * 12 20 2011 cp.wu + * [WCXRP00001144] [MT6620 Wi-Fi][Driver][Firmware] Add RF_FUNC_ID for exposing device and related version information + * add driver implementations for RF_AT_FUNCID_FW_INFO & RF_AT_FUNCID_DRV_INFO + * to expose version information + * + * 08 04 2010 cp.wu + * NULL + * add an extra parameter to rftestQueryATInfo 'cause it's necessary to pass u4FuncData for query request. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-12-08 17:35:11 GMT mtk02752 +** * comment out RF test which is not supported on MT6620 +** + API decalre for rftest +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-12-08 11:29:07 GMT mtk02752 +** definitions for RF test mode +** +*/ +#ifndef _RFTEST_H +#define _RFTEST_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Table Version */ +#define RF_AUTO_TEST_FUNCTION_TABLE_VERSION 0x01000001 + +/* Power */ +#define RF_AT_PARAM_POWER_MASK BITS(0, 7) +#define RF_AT_PARAM_POWER_MAX RF_AT_PARAM_POWER_MASK + +/* Rate */ +#define RF_AT_PARAM_RATE_MCS_MASK BIT(31) +#define RF_AT_PARAM_RATE_MASK BITS(0, 7) +#define RF_AT_PARAM_RATE_CCK_MAX 3 +#define RF_AT_PARAM_RATE_1M 0 +#define RF_AT_PARAM_RATE_2M 1 +#define RF_AT_PARAM_RATE_5_5M 2 +#define RF_AT_PARAM_RATE_11M 3 +#define RF_AT_PARAM_RATE_6M 4 +#define RF_AT_PARAM_RATE_9M 5 +#define RF_AT_PARAM_RATE_12M 6 +#define RF_AT_PARAM_RATE_18M 7 +#define RF_AT_PARAM_RATE_24M 8 +#define RF_AT_PARAM_RATE_36M 9 +#define RF_AT_PARAM_RATE_48M 10 +#define RF_AT_PARAM_RATE_54M 11 + +/* Antenna */ +#define RF_AT_PARAM_ANTENNA_ID_MASK BITS(0, 7) +#define RF_AT_PARAM_ANTENNA_ID_MAX 1 + +/* Packet Length */ +#define RF_AT_PARAM_TX_80211HDR_BYTE_MAX (32) +#define RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX (2048) + +#define RF_AT_PARAM_TX_PKTLEN_BYTE_DEFAULT 1024 +#define RF_AT_PARAM_TX_PKTLEN_BYTE_MAX \ + ((UINT_16)(RF_AT_PARAM_TX_80211HDR_BYTE_MAX + RF_AT_PARAM_TX_80211PAYLOAD_BYTE_MAX)) + +/* Packet Count */ +#define RF_AT_PARAM_TX_PKTCNT_DEFAULT 1000 +#define RF_AT_PARAM_TX_PKTCNT_UNLIMITED 0 + +/* Packet Interval */ +#define RF_AT_PARAM_TX_PKT_INTERVAL_US_DEFAULT 50 + +/* ALC */ +#define RF_AT_PARAM_ALC_DISABLE 0 +#define RF_AT_PARAM_ALC_ENABLE 1 + +/* TXOP */ +#define RF_AT_PARAM_TXOP_DEFAULT 0 +#define RF_AT_PARAM_TXOPQUE_QMASK BITS(16, 31) +#define RF_AT_PARAM_TXOPQUE_TMASK BITS(0, 15) +#define RF_AT_PARAM_TXOPQUE_AC0 (0<<16) +#define RF_AT_PARAM_TXOPQUE_AC1 (1<<16) +#define RF_AT_PARAM_TXOPQUE_AC2 (2<<16) +#define RF_AT_PARAM_TXOPQUE_AC3 (3<<16) +#define RF_AT_PARAM_TXOPQUE_AC4 (4<<16) +#define RF_AT_PARAM_TXOPQUE_QOFFSET 16 + +/* Retry Limit */ +#define RF_AT_PARAM_TX_RETRY_DEFAULT 0 +#define RF_AT_PARAM_TX_RETRY_MAX 6 + +/* QoS Queue */ +#define RF_AT_PARAM_QOSQUE_AC0 0 +#define RF_AT_PARAM_QOSQUE_AC1 1 +#define RF_AT_PARAM_QOSQUE_AC2 2 +#define RF_AT_PARAM_QOSQUE_AC3 3 +#define RF_AT_PARAM_QOSQUE_AC4 4 +#define RF_AT_PARAM_QOSQUE_DEFAULT RF_AT_PARAM_QOSQUE_AC0 + +/* Bandwidth */ +#define RF_AT_PARAM_BANDWIDTH_20MHZ 0 +#define RF_AT_PARAM_BANDWIDTH_40MHZ 1 +#define RF_AT_PARAM_BANDWIDTH_U20_IN_40MHZ 2 +#define RF_AT_PARAM_BANDWIDTH_D20_IN_40MHZ 3 +#define RF_AT_PARAM_BANDWIDTH_DEFAULT RF_AT_PARAM_BANDWIDTH_20MHZ + +/* GI (Guard Interval) */ +#define RF_AT_PARAM_GI_800NS 0 +#define RF_AT_PARAM_GI_400NS 1 +#define RF_AT_PARAM_GI_DEFAULT RF_AT_PARAM_GI_800NS + +/* STBC */ +#define RF_AT_PARAM_STBC_DISABLE 0 +#define RF_AT_PARAM_STBC_ENABLE 1 + +/* RIFS */ +#define RF_AT_PARAM_RIFS_DISABLE 0 +#define RF_AT_PARAM_RIFS_ENABLE 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Function ID List */ +typedef enum _ENUM_RF_AT_FUNCID_T { + RF_AT_FUNCID_VERSION = 0, + RF_AT_FUNCID_COMMAND, + RF_AT_FUNCID_POWER, + RF_AT_FUNCID_RATE, + RF_AT_FUNCID_PREAMBLE, + RF_AT_FUNCID_ANTENNA, + RF_AT_FUNCID_PKTLEN, + RF_AT_FUNCID_PKTCNT, + RF_AT_FUNCID_PKTINTERVAL, + RF_AT_FUNCID_TEMP_COMPEN, + RF_AT_FUNCID_TXOPLIMIT, + RF_AT_FUNCID_ACKPOLICY, + RF_AT_FUNCID_PKTCONTENT, + RF_AT_FUNCID_RETRYLIMIT, + RF_AT_FUNCID_QUEUE, + RF_AT_FUNCID_BANDWIDTH, + RF_AT_FUNCID_GI, + RF_AT_FUNCID_STBC, + RF_AT_FUNCID_CHNL_FREQ, + RF_AT_FUNCID_RIFS, + RF_AT_FUNCID_TRSW_TYPE, + RF_AT_FUNCID_RF_SX_SHUTDOWN, + RF_AT_FUNCID_PLL_SHUTDOWN, + RF_AT_FUNCID_SLOW_CLK_MODE, + RF_AT_FUNCID_ADC_CLK_MODE, + RF_AT_FUNCID_MEASURE_MODE, + RF_AT_FUNCID_VOLT_COMPEN, + RF_AT_FUNCID_DPD_TX_GAIN, + RF_AT_FUNCID_DPD_MODE, + RF_AT_FUNCID_TSSI_MODE, + RF_AT_FUNCID_TX_GAIN_CODE, + RF_AT_FUNCID_TX_PWR_MODE, + + /* Query command */ + RF_AT_FUNCID_TXED_COUNT = 32, + RF_AT_FUNCID_TXOK_COUNT, + RF_AT_FUNCID_RXOK_COUNT, + RF_AT_FUNCID_RXERROR_COUNT, + RF_AT_FUNCID_RESULT_INFO, + RF_AT_FUNCID_TRX_IQ_RESULT, + RF_AT_FUNCID_TSSI_RESULT, + RF_AT_FUNCID_DPD_RESULT, + RF_AT_FUNCID_RXV_DUMP, + RF_AT_FUNCID_RX_PHY_STATIS, + RF_AT_FUNCID_MEASURE_RESULT, + RF_AT_FUNCID_TEMP_SENSOR, + RF_AT_FUNCID_VOLT_SENSOR, + RF_AT_FUNCID_READ_EFUSE, + RF_AT_FUNCID_RX_RSSI, + RF_AT_FUNCID_FW_INFO, + RF_AT_FUNCID_DRV_INFO, + + /* Set command */ + RF_AT_FUNCID_SET_DPD_RESULT = 64, + RF_AT_FUNCID_SET_CW_MODE, + RF_AT_FUNCID_SET_JAPAN_CH14_FILTER, + RF_AT_FUNCID_WRITE_EFUSE, + RF_AT_FUNCID_SET_MAC_ADDRESS +} ENUM_RF_AT_FUNCID_T; + +/* Command */ +typedef enum _ENUM_RF_AT_COMMAND_T { + RF_AT_COMMAND_STOPTEST = 0, + RF_AT_COMMAND_STARTTX, + RF_AT_COMMAND_STARTRX, + RF_AT_COMMAND_RESET, + RF_AT_COMMAND_OUTPUT_POWER, /* Payload */ + RF_AT_COMMAND_LO_LEAKAGE, /* Local freq is renamed to Local leakage */ + RF_AT_COMMAND_CARRIER_SUPPR, /* OFDM (LTF/STF), CCK (PI,PI/2) */ + RF_AT_COMMAND_TRX_IQ_CAL, + RF_AT_COMMAND_TSSI_CAL, + RF_AT_COMMAND_DPD_CAL, + RF_AT_COMMAND_CW, + RF_AT_COMMAND_NUM +} ENUM_RF_AT_COMMAND_T; + +/* Preamble */ +typedef enum _ENUM_RF_AT_PREAMBLE_T { + RF_AT_PREAMBLE_NORMAL = 0, + RF_AT_PREAMBLE_CCK_SHORT, + RF_AT_PREAMBLE_11N_MM, + RF_AT_PREAMBLE_11N_GF, + RF_AT_PREAMBLE_NUM +} ENUM_RF_AT_PREAMBLE_T; + +/* Ack Policy */ +typedef enum _ENUM_RF_AT_ACK_POLICY_T { + RF_AT_ACK_POLICY_NORMAL = 0, + RF_AT_ACK_POLICY_NOACK, + RF_AT_ACK_POLICY_NOEXPLICTACK, + RF_AT_ACK_POLICY_BLOCKACK, + RF_AT_ACK_POLICY_NUM +} ENUM_RF_AT_ACK_POLICY_T; + +typedef enum _ENUM_RF_AUTOTEST_STATE_T { + RF_AUTOTEST_STATE_STANDBY = 0, + RF_AUTOTEST_STATE_TX, + RF_AUTOTEST_STATE_RX, + RF_AUTOTEST_STATE_RESET, + RF_AUTOTEST_STATE_OUTPUT_POWER, + RF_AUTOTEST_STATE_LOCA_FREQUENCY, + RF_AUTOTEST_STATE_CARRIER_SUPRRESION, + RF_AUTOTEST_STATE_NUM +} ENUM_RF_AUTOTEST_STATE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +WLAN_STATUS rftestSetATInfo(IN P_ADAPTER_T prAdapter, UINT_32 u4FuncIndex, UINT_32 u4FuncData); + +WLAN_STATUS +rftestQueryATInfo(IN P_ADAPTER_T prAdapter, + UINT_32 u4FuncIndex, UINT_32 u4FuncData, OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +WLAN_STATUS rftestSetFrequency(IN P_ADAPTER_T prAdapter, IN UINT_32 u4FreqInKHz, IN PUINT_32 pu4SetInfoLen); + +#endif /* _RFTEST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h new file mode 100644 index 0000000000000..8ee184591fc2f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/tdls_extr.h @@ -0,0 +1,427 @@ +/* +** Id: include/tdls_extr.h#1 +*/ + +/*! \file "tdls_extr.h" + \brief This file contains the external used in other modules + for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: tdls_extr.h + * + * 11 18 2013 vend_samp.lin + * NULL + * Initial version. + * + ** + */ + +#ifndef _TDLS_EXTR_H +#define _TDLS_EXTR_H + +#if (CFG_SUPPORT_TDLS == 1) + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#define TDLS_TX_QUOTA_EMPTY_TIMEOUT 10 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* protocol */ +#define TDLS_FRM_PROT_TYPE 0x890d + +/* TDLS uses Ethertype 89-0d frames. The UP shall be AC_VI, unless otherwise specified. */ +#define USER_PRIORITY_TDLS 5 + +/* Status code */ +#define TDLS_STATUS WLAN_STATUS + +#define TDLS_STATUS_SUCCESS WLAN_STATUS_SUCCESS +#define TDLS_STATUS_FAILURE WLAN_STATUS_FAILURE +#define TDLS_STATUS_INVALID_LENGTH WLAN_STATUS_INVALID_LENGTH +#define TDLS_STATUS_RESOURCES WLAN_STATUS_RESOURCES + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#define TDLS_U32 UINT32 +#define TDLS_U16 UINT16 +#define TDLS_U8 UINT8 + +typedef enum _TDLS_REASON_CODE { + TDLS_REASON_CODE_UNREACHABLE = 25, + TDLS_REASON_CODE_UNSPECIFIED = 26, + + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN = 0x80, /* 128 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WIFI_OFF = 0x81, /* 129 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING = 0x82, /* 130 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT = 0x83, /* 131 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT = 0x84, /* 132 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY = 0x85, /* 133 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL = 0x86, /* 134 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL = 0x87, /* 135 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX = 0x88, /* 136 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3 = 0x89, /* 137 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY = 0x8a, /* 138 */ + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN = 0x8b /* 139 */ +} TDLS_REASON_CODE; + +/* TDLS FSM */ +typedef struct _TDLS_CMD_PEER_ADD_T { + + TDLS_U8 aucPeerMac[6]; + +#if 0 + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + UINT_16 u2CapInfo; + + UINT_16 u2OperationalRateSet; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + UINT_8 ucPhyTypeSet; +#endif +} TDLS_CMD_PEER_ADD_T; + +typedef struct _TDLS_CMD_LINK_T { + + TDLS_U8 aucPeerMac[6]; + BOOLEAN fgIsEnabled; +} TDLS_CMD_LINK_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T { + TDLS_U8 arRxMask[10]; + TDLS_U16 u2RxHighest; + TDLS_U8 ucTxParams; + TDLS_U8 Reserved[3]; +} TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_HT_CAP_T { + TDLS_U16 u2CapInfo; + TDLS_U8 ucAmpduParamsInfo; + + /* 16 bytes MCS information */ + TDLS_CMD_PEER_UPDATE_HT_CAP_MCS_INFO_T rMCS; + + TDLS_U16 u2ExtHtCapInfo; + TDLS_U32 u4TxBfCapInfo; + TDLS_U8 ucAntennaSelInfo; +} TDLS_CMD_PEER_UPDATE_HT_CAP_T; + +typedef struct _TDLS_CMD_PEER_UPDATE_T { + + TDLS_U8 aucPeerMac[6]; + +#define TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX 50 + TDLS_U8 aucSupChan[TDLS_CMD_PEER_UPDATE_SUP_CHAN_MAX]; + + TDLS_U16 u2StatusCode; + +#define TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX 50 + TDLS_U8 aucSupRate[TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX]; + TDLS_U16 u2SupRateLen; + + TDLS_U8 UapsdBitmap; + TDLS_U8 UapsdMaxSp; /* MAX_SP */ + + TDLS_U16 u2Capability; +#define TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN 5 + TDLS_U8 aucExtCap[TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN]; + TDLS_U16 u2ExtCapLen; + + TDLS_CMD_PEER_UPDATE_HT_CAP_T rHtCap; + BOOLEAN fgIsSupHt; + +} TDLS_CMD_PEER_UPDATE_T; + +/* Command to TDLS core module */ +typedef enum _TDLS_CMD_CORE_ID { + TDLS_CORE_CMD_TEST_NULL_RCV = 0x00, + TDLS_CORE_CMD_TEST_PTI_RSP = 0x01, + TDLS_CORE_CMD_MIB_UPDATE = 0x02, + TDLS_CORE_CMD_TEST_TX_FAIL_SKIP = 0x03, + TDLS_CORE_CMD_UAPSD_CONF = 0x04, + TDLS_CORE_CMD_TEST_DATA_RCV = 0x05, + TDLS_CORE_CMD_TEST_PTI_REQ = 0x06, + TDLS_CORE_CMD_TEST_CHSW_REQ = 0x07, + TDLS_CORE_CMD_CHSW_CONF = 0x08, + TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP = 0x09, + TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP = 0x0a, + TDLS_CORE_CMD_TEST_CHSW_RSP = 0x0b, + TDLS_CORE_CMD_TEST_SCAN_SKIP = 0x0c, + TDLS_CORE_CMD_SETUP_CONF = 0x0d, + TDLS_CORE_CMD_TEST_TEAR_DOWN = 0x0e, + TDLS_CORE_CMD_KEY_INFO = 0x0f, + TDLS_CORE_CMD_TEST_PTI_TX_FAIL = 0x10 +} TDLS_CMD_CORE_ID; + +typedef struct _TDLS_CMD_CORE_TEST_NULL_RCV_T { + + TDLS_U32 u4PM; +} TDLS_CMD_CORE_TEST_NULL_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T { + + TDLS_U32 u4DialogToken; +} TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T { + + TDLS_U32 u4DialogToken; + TDLS_U32 u4PM; +} TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T { + + TDLS_U32 u4ReasonCode; +} TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T { + + TDLS_U32 u4Chan; + TDLS_U32 u4RegClass; + TDLS_U32 u4SecChanOff; + TDLS_U32 u4SwitchTime; + TDLS_U32 u4SwitchTimeout; +} TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T { + + TDLS_U32 u4Chan; + TDLS_U32 u4SwitchTime; + TDLS_U32 u4SwitchTimeout; + TDLS_U32 u4StatusCode; +} TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T; + +typedef struct _TDLS_CMD_CORE_TEST_DATA_RCV_T { + + TDLS_U32 u4PM; + TDLS_U32 u4UP; + TDLS_U32 u4EOSP; + TDLS_U32 u4IsNull; +} TDLS_CMD_CORE_TEST_DATA_RCV_T; + +typedef struct _TDLS_CMD_CORE_MIB_PARAM_UPDATE_T { + + BOOLEAN Tdlsdot11TunneledDirectLinkSetupImplemented; + BOOLEAN Tdlsdot11TDLSPeerUAPSDBufferSTAActivated; + BOOLEAN Tdlsdot11TDLSPeerPSMActivated; + TDLS_U16 Tdlsdot11TDLSPeerUAPSDIndicationWindow; + BOOLEAN Tdlsdot11TDLSChannelSwitchingActivated; + TDLS_U8 Tdlsdot11TDLSPeerSTAMissingAckRetryLimit; + TDLS_U8 Tdlsdot11TDLSResponseTimeout; + TDLS_U16 Tdlsdot11TDLSProbeDelay; + TDLS_U8 Tdlsdot11TDLSDiscoveryRequestWindow; + TDLS_U8 Tdlsdot11TDLSACDeterminationInterval; +} TDLS_CMD_CORE_MIB_PARAM_UPDATE_T; + +typedef struct _TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T; + +typedef struct _TDLS_CMD_CORE_UAPSD_CONFIG_T { + + BOOLEAN fgIsSpTimeoutSkip; + BOOLEAN fgIsPtiTimeoutSkip; +} TDLS_CMD_CORE_UAPSD_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_SETUP_CONFIG_T { + + BOOLEAN fgIs2040Supported; +} TDLS_CMD_CORE_SETUP_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_CHSW_CONFIG_T { + + TDLS_U8 ucNetTypeIndex; + BOOLEAN fgIsChSwEnabled; + BOOLEAN fgIsChSwStarted; + TDLS_U8 ucRegClass; + TDLS_U8 ucTargetChan; + TDLS_U8 ucSecChanOff; + BOOLEAN fgIsChSwRegular; +} TDLS_CMD_CORE_CHSW_CONFIG_T; + +typedef struct _TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T; + +typedef struct _TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T; + +typedef struct _TDLS_CMD_CORE_TEST_PROHIBIT_T { + + BOOLEAN fgIsEnable; + BOOLEAN fgIsSet; +} TDLS_CMD_CORE_TEST_PROHIBIT_T; + +typedef struct _TDLS_CMD_CORE_TEST_SCAN_SKIP_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_SCAN_SKIP_T; + +typedef struct _TDLS_CMD_CORE_INFO_DISPLAY_T { + + BOOLEAN fgIsToClearAllHistory; +} TDLS_CMD_CORE_INFO_DISPLAY_T; + +typedef struct _TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T { + + BOOLEAN fgIsEnable; +} TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T; + +typedef struct _TDLS_CMD_CORE_T { + + TDLS_U32 u4Command; /* TDLS_CMD_CORE_ID */ + + TDLS_U8 aucPeerMac[6]; + TDLS_U8 ucNetTypeIndex; + +#define TDLS_CMD_CORE_RESERVED_SIZE 50 + union { + TDLS_CMD_CORE_TEST_NULL_RCV_T rCmdNullRcv; + TDLS_CMD_CORE_TEST_PTI_REQ_RCV_T rCmdPtiReqRcv; + TDLS_CMD_CORE_TEST_PTI_RSP_RCV_T rCmdPtiRspRcv; + TDLS_CMD_CORE_TEST_TEAR_DOWN_RCV_T rCmdTearDownRcv; + TDLS_CMD_CORE_TEST_CHST_REQ_RCV_T rCmdChStReqRcv; + TDLS_CMD_CORE_TEST_CHST_RSP_RCV_T rCmdChStRspRcv; + TDLS_CMD_CORE_TEST_DATA_RCV_T rCmdDatRcv; + TDLS_CMD_CORE_TEST_TX_FAIL_SKIP_T rCmdTxFailSkip; + TDLS_CMD_CORE_TEST_KEEP_ALIVE_SKIP_T rCmdKeepAliveSkip; + TDLS_CMD_CORE_TEST_CHSW_TIMEOUT_SKIP_T rCmdChSwTimeoutSkip; + TDLS_CMD_CORE_TEST_PROHIBIT_T rCmdProhibit; + TDLS_CMD_CORE_TEST_SCAN_SKIP_T rCmdScanSkip; + TDLS_CMD_CORE_TEST_PTI_TX_FAIL_T rCmdPtiTxFail; + + TDLS_CMD_CORE_MIB_PARAM_UPDATE_T rCmdMibUpdate; + TDLS_CMD_CORE_UAPSD_CONFIG_T rCmdUapsdConf; + TDLS_CMD_CORE_CHSW_CONFIG_T rCmdChSwConf; + TDLS_CMD_CORE_SETUP_CONFIG_T rCmdSetupConf; + TDLS_CMD_CORE_INFO_DISPLAY_T rCmdInfoDisplay; + TDLS_U8 Reserved[TDLS_CMD_CORE_RESERVED_SIZE]; + } Content; +} TDLS_CMD_CORE_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* + assign station record idx for the packet only when STA_STATE_3 + Or we will try to send data frame when the TDLS peer's state is STA_STATE_1 + EX: + 1. mtk_cfg80211_add_station: First create the STA_RECORD_T; + 2. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. + 3. mtk_cfg80211_add_station: Change state to STA_STATE_1. + 4. TdlsexCfg80211TdlsMgmt: Send a TDLS request frame. +*/ +#define TDLSEX_STA_REC_IDX_GET(__prAdapter__, __MsduInfo__) \ +{ \ + STA_RECORD_T *__StaRec__; \ + __MsduInfo__->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; \ + __StaRec__ = cnmGetStaRecByAddress(__prAdapter__, \ + (UINT_8) NETWORK_TYPE_AIS_INDEX, \ + __MsduInfo__->aucEthDestAddr); \ + if ((__StaRec__ != NULL) && \ + ((__StaRec__)->ucStaState == STA_STATE_3) && \ + (IS_TDLS_STA(__StaRec__))) { \ + __MsduInfo__->ucStaRecIndex = __StaRec__->ucIndex; \ + } \ +} + +/* fill wiphy flag */ +#define TDLSEX_WIPHY_FLAGS_INIT(__fgFlag__)\ +{ \ + __fgFlag__ |= (WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP);\ +} + +/* assign user priority of a TDLS action frame */ +/* + According to 802.11z: Setup req/resp are sent in AC_BK, otherwise we should default + to AC_VI. +*/ +#define TDLSEX_UP_ASSIGN(__UserPriority__) \ +{ \ + __UserPriority__ = USER_PRIORITY_TDLS; \ +} + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int +TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len); + +int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper); + +VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE); + +VOID TdlsexEventHandle(P_GLUE_INFO_T prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey); + +VOID TdlsexInit(ADAPTER_T *prAdapter); + +BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter); + +TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +VOID +TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode); + +TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +TDLS_STATUS TdlsexPeerAdd(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +TDLS_STATUS TdlsexPeerUpdate(P_ADAPTER_T prAdapter, PVOID pvSetBuffer, UINT_32 u4SetBufferLen, PUINT_32 pu4SetInfoLen); + +BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, UINT_8 *pPkt); + +VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, UINT8 *pPkt, UINT16 u2PktLen); + +TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo); + +VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota); + +VOID TdlsexUninit(ADAPTER_T *prAdapter); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* CFG_SUPPORT_TDLS */ + +#endif /* _TDLS_EXTR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h new file mode 100644 index 0000000000000..7ab62dae8813e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/typedef.h @@ -0,0 +1,244 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/typedef.h#1 +*/ + +/*! \file typedef.h + \brief Declaration of data type and return values of internal protocol stack. + + In this file we declare the data type and return values which will be exported + to the GLUE Layer. +*/ + +/* +** Log: typedef.h + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add necessary changes to driver data paths. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add definitions for module migration. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add aa_fsm.h, ais_fsm.h, bss.h, mib.h and scan.h. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add Ethernet destination address information in packet info for TX + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:41:37 GMT mtk01461 +** Update PACKET_INFO_INIT for TX Path +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:30:17 GMT mtk01461 +** Add parameter in PACKET_INFO_T for HIF Loopback +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:22 GMT mtk01461 +** Fix LINT warning +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:28 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:11:54 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _TYPEDEF_H +#define _TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/* ieee80211.h of linux has duplicated definitions */ +#if defined(WLAN_STATUS_SUCCESS) +#undef WLAN_STATUS_SUCCESS +#endif + +#define WLAN_STATUS_SUCCESS ((WLAN_STATUS) 0x00000000L) +#define WLAN_STATUS_PENDING ((WLAN_STATUS) 0x00000103L) +#define WLAN_STATUS_NOT_ACCEPTED ((WLAN_STATUS) 0x00010003L) + +#define WLAN_STATUS_MEDIA_CONNECT ((WLAN_STATUS) 0x4001000BL) +#define WLAN_STATUS_MEDIA_DISCONNECT ((WLAN_STATUS) 0x4001000CL) +#define WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ((WLAN_STATUS) 0x4001000DL) + +#define WLAN_STATUS_MEDIA_SPECIFIC_INDICATION ((WLAN_STATUS) 0x40010012L) + +#define WLAN_STATUS_SCAN_COMPLETE ((WLAN_STATUS) 0x60010001L) +#define WLAN_STATUS_MSDU_OK ((WLAN_STATUS) 0x60010002L) + +/* TODO(Kevin): double check if 0x60010001 & 0x60010002 is proprietary */ +#define WLAN_STATUS_ROAM_OUT_FIND_BEST ((WLAN_STATUS) 0x60010101L) +#define WLAN_STATUS_ROAM_DISCOVERY ((WLAN_STATUS) 0x60010102L) + +#define WLAN_STATUS_FAILURE ((WLAN_STATUS) 0xC0000001L) +#define WLAN_STATUS_RESOURCES ((WLAN_STATUS) 0xC000009AL) +#define WLAN_STATUS_NOT_SUPPORTED ((WLAN_STATUS) 0xC00000BBL) + +#define WLAN_STATUS_MULTICAST_FULL ((WLAN_STATUS) 0xC0010009L) +#define WLAN_STATUS_INVALID_PACKET ((WLAN_STATUS) 0xC001000FL) +#define WLAN_STATUS_ADAPTER_NOT_READY ((WLAN_STATUS) 0xC0010011L) +#define WLAN_STATUS_NOT_INDICATING ((WLAN_STATUS) 0xC0010013L) +#define WLAN_STATUS_INVALID_LENGTH ((WLAN_STATUS) 0xC0010014L) +#define WLAN_STATUS_INVALID_DATA ((WLAN_STATUS) 0xC0010015L) +#define WLAN_STATUS_BUFFER_TOO_SHORT ((WLAN_STATUS) 0xC0010016L) + +#define WLAN_STATUS_BWCS_UPDATE ((WLAN_STATUS) 0xC0010017L) + +#define WLAN_STATUS_CONNECT_INDICATION ((WLAN_STATUS) 0xC0010018L) + +/* NIC status flags */ +#define ADAPTER_FLAG_HW_ERR 0x00400000 + +/* Type Length */ +#define TL_IPV4 0x0008 +#define TL_IPV6 0xDD86 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for GLUE_INFO structure */ +typedef struct _GLUE_INFO_T GLUE_INFO_T, *P_GLUE_INFO_T; + +/* Type definition for WLAN STATUS */ +typedef UINT_32 WLAN_STATUS, *P_WLAN_STATUS; + +/* Type definition for ADAPTER structure */ +typedef struct _ADAPTER_T ADAPTER_T, *P_ADAPTER_T; + +/* Type definition for MESSAGE HEADER structure */ +typedef struct _MSG_HDR_T MSG_HDR_T, *P_MSG_HDR_T; + +/* Type definition for WLAN configuration */ +typedef struct _WLAN_CFG_T WLAN_CFG_T, *P_WLAN_CFG_T; + +/* Type definition for WLAN configuration entry */ +typedef struct _WLAN_CFG_ENTRY_T WLAN_CFG_ENTRY_T, *P_WLAN_CFG_ENTRY_T; + +/* Type definition for WLAN configuration callback */ +typedef WLAN_STATUS(*WLAN_CFG_SET_CB) (P_ADAPTER_T prAdapter, + PUINT_8 pucKey, PUINT_8 pucValue, PVOID pPrivate, UINT_32 u4Flags); + +/* Type definition for Pointer to OS Native Packet */ +typedef void *P_NATIVE_PACKET; + +/* Type definition for STA_RECORD_T structure to handle the connectivity and packet reception + * for a particular STA. + */ +typedef struct _STA_RECORD_T STA_RECORD_T, *P_STA_RECORD_T, **PP_STA_RECORD_T; + +/* CMD_INFO_T is used by Glue Layer to send a cluster of Command(OID) information to + * the TX Path to reduce the parameters of a function call. + */ +typedef struct _CMD_INFO_T CMD_INFO_T, *P_CMD_INFO_T; + +/* Following typedef should be removed later, because Glue Layer should not + * be aware of following data type. + */ +typedef struct _SW_RFB_T SW_RFB_T, *P_SW_RFB_T, **PP_SW_RFB_T; + +typedef struct _MSDU_INFO_T MSDU_INFO_T, *P_MSDU_INFO_T; + +typedef struct _REG_ENTRY_T REG_ENTRY_T, *P_REG_ENTRY_T; + +/* IST handler definition */ +typedef VOID(*IST_EVENT_FUNCTION) (P_ADAPTER_T); + +/* Type definition for function pointer of timer handler */ +typedef VOID(*PFN_TIMER_CALLBACK) (IN P_GLUE_INFO_T); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h new file mode 100644 index 0000000000000..e8937166dc4f3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_bow.h @@ -0,0 +1,352 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_bow.h#1 +*/ + +/*! \file "wlan_bow.h" + \brief This file contains the declairations of 802.11 PAL + command processing routines for + MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_bow.h + * + * 05 25 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add BoW Cancel Scan Request and Turn On deactive network function. + * + * 05 23 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Add some BoW error handling. + * + * 05 21 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Protect BoW connection establishment. + * + * 05 17 2011 terry.wu + * [WCXRP00000730] [MT6620 Wi-Fi][BoW] Send deauth while disconnecting + * Send deauth while disconnecting BoW link. + * + * 05 06 2011 terry.wu + * [WCXRP00000707] [MT6620 Wi-Fi][Driver] Fix BoW Multiple Physical Link connect/disconnect issue + * Fix BoW Multiple Physical Link connect/disconnect issue. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW table. + * + * 02 16 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add bowNotifyAllLinkDisconnected interface and change channel grant procedure for bow starting.. + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update bowString and channel grant. + * + * 01 11 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update BOW Activity Report structure and bug fix. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * 1) all BT physical handles shares the same RSSI/Link Quality. + * 2) simplify BT command composing + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose +** +*/ + +#ifndef _WLAN_BOW_H +#define _WLAN_BOW_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "nic/bow.h" +#include "nic/cmd_buf.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +#if CFG_BOW_TEST +extern UINT_32 g_arBowRevPalPacketTime[32]; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define BOWCMD_STATUS_SUCCESS 0 +#define BOWCMD_STATUS_FAILURE 1 +#define BOWCMD_STATUS_UNACCEPTED 2 +#define BOWCMD_STATUS_INVALID 3 +#define BOWCMD_STATUS_TIMEOUT 4 + +#define BOW_WILDCARD_SSID "AMP" +#define BOW_WILDCARD_SSID_LEN 3 +#define BOW_SSID_LEN 21 + + /* 0: query, 1: setup, 2: destroy */ +#define BOW_QUERY_CMD 0 +#define BOW_SETUP_CMD 1 +#define BOW_DESTROY_CMD 2 + +#define BOW_INITIATOR 0 +#define BOW_RESPONDER 1 + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +typedef struct _BOW_TABLE_T { + UINT_8 ucAcquireID; + BOOLEAN fgIsValid; + ENUM_BOW_DEVICE_STATE eState; + UINT_8 aucPeerAddress[6]; + /* UINT_8 ucRole; */ + /* UINT_8 ucChannelNum; */ + UINT_16 u2Reserved; +} BOW_TABLE_T, *P_BOW_TABLE_T; + +typedef WLAN_STATUS(*PFN_BOW_CMD_HANDLE) (P_ADAPTER_T, P_AMPC_COMMAND); + +typedef struct _BOW_CMD_T { + UINT_8 uCmdID; + PFN_BOW_CMD_HANDLE pfCmdHandle; +} BOW_CMD_T, *P_BOW_CMD_T; + +typedef struct _BOW_EVENT_ACTIVITY_REPORT_T { + UINT_8 ucReason; + UINT_8 aucReserved; + UINT_8 aucPeerAddress[6]; +} BOW_EVENT_ACTIVITY_REPORT_T, *P_BOW_EVENT_ACTIVITY_REPORT_T; + +/* +ucReason: 0: success + 1: general failure + 2: too much time (> 2/3 second totally) requested for scheduling. + Others: reserved. +*/ + +typedef struct _BOW_EVENT_SYNC_TSF_T { + UINT_64 u4TsfTime; + UINT_32 u4TsfSysTime; + UINT_32 u4ScoTime; + UINT_32 u4ScoSysTime; +} BOW_EVENT_SYNC_TSF_T, *P_BOW_EVENT_SYNC_TSF_T; + +typedef struct _BOW_ACTIVITY_REPORT_BODY_T { + UINT_32 u4StartTime; + UINT_32 u4Duration; + UINT_32 u4Periodicity; +} BOW_ACTIVITY_REPORT_BODY_T, *P_BOW_ACTIVITY_REPORT_BODY_T; + +typedef struct _BOW_ACTIVITY_REPORT_T { + UINT_8 aucPeerAddress[6]; + UINT_8 ucScheduleKnown; + UINT_8 ucNumReports; + BOW_ACTIVITY_REPORT_BODY_T arBowActivityReportBody[MAX_ACTIVITY_REPORT]; +} BOW_ACTIVITY_REPORT_T, *P_BOW_ACTIVITY_REPORT_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*--------------------------------------------------------------*/ +/* Firmware Command Packer */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendSetQueryBowCmd(IN P_ADAPTER_T prAdapter, + UINT_8 ucCID, + BOOLEAN fgSetQuery, + BOOLEAN fgNeedResp, + PFN_CMD_DONE_HANDLER pfCmdDoneHandler, + PFN_CMD_TIMEOUT_HANDLER pfCmdTimeoutHandler, + UINT_32 u4SetQueryInfoLen, PUINT_8 pucInfoBuffer, IN UINT_8 ucSeqNumber); + +/*--------------------------------------------------------------*/ +/* Command Dispatcher */ +/*--------------------------------------------------------------*/ +WLAN_STATUS wlanbowHandleCommand(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS bowCmdGetMacStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdSetupConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdDestroyConnection(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdSetPTK(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdReadRSSI(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdShortRangeMode(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +WLAN_STATUS bowCmdGetChannelList(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd); + +VOID wlanbowCmdEventSetStatus(IN P_ADAPTER_T prAdapter, IN P_AMPC_COMMAND prCmd, IN UINT_8 ucEventBuf); + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ +VOID wlanbowCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventLinkConnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventLinkDisconnected(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventSetSetupConnection(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventReadLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdEventReadRssi(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanbowCmdTimeoutHandler(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID bowStopping(IN P_ADAPTER_T prAdapter); + +VOID bowStarting(IN P_ADAPTER_T prAdapter); + +VOID bowAssignSsid(IN PUINT_8 pucSsid, IN PUINT_8 pucSsidLen); + +BOOLEAN bowValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags); + +VOID bowSendBeacon(IN P_ADAPTER_T prAdapter, ULONG ulParam); + +VOID bowResponderScan(IN P_ADAPTER_T prAdapter); + +VOID bowResponderScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowResponderCancelScan(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgIsChannelExtention); + +VOID bowResponderJoin(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc); + +VOID bowFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID +bowIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication); + +VOID bowRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec); + +WLAN_STATUS bowRunEventRxDeAuth(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb); + +VOID bowDisconnectLink(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus); + +BOOLEAN bowValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode); + +BOOLEAN +bowValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode); + +VOID bowRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr); + +VOID bowRequestCh(IN P_ADAPTER_T prAdapter); + +VOID bowReleaseCh(IN P_ADAPTER_T prAdapter); + +VOID bowChGrantedTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam); + +BOOLEAN bowNotifyAllLinkDisconnected(IN P_ADAPTER_T prAdapter); + +BOOLEAN bowCheckBowTableIfVaild(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowGetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, OUT P_BOW_TABLE_T prBowTable); + +BOOLEAN +bowGetBowTableEntryByPeerAddress(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], OUT PUINT_8 pucBowTableIdx); + +BOOLEAN bowGetBowTableFreeEntry(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucBowTableIdx); + +ENUM_BOW_DEVICE_STATE bowGetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6]); + +BOOLEAN bowSetBowTableState(IN P_ADAPTER_T prAdapter, IN UINT_8 aucPeerAddress[6], IN ENUM_BOW_DEVICE_STATE eState); + +BOOLEAN bowSetBowTableContent(IN P_ADAPTER_T prAdapter, IN UINT_8 ucBowTableIdx, IN P_BOW_TABLE_T prBowTable); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_BOW_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h new file mode 100644 index 0000000000000..87259397a93d1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_lib.h @@ -0,0 +1,1001 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_lib.h#1 +*/ + +/*! \file "wlan_lib.h" + \brief The declaration of the functions of the wlanAdpater objects + + Detail description. +*/ + +/* +** Log: wlan_lib.h + * + * 06 08 2012 eason.tsai + * NULL + * Nvram context covert from 6620 to 6628 for old 6620 meta tool + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for + * preferred band configuration with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for + * setting preferred band configuration corresponding to network type. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * eliminate win32 native data types. + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 10 03 2011 cp.wu + * [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware downloading aggregated path. + * + * 09 20 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * change window registry of driver for roaming. + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 25 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add DFS switch. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 15 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * support to load different firmware image for E3/E4/E5 and E6 ASIC on win32 platforms. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, + * TX deauth to a disconnecting device issue. + * Fix GO send deauth frame issue. + * + * 07 22 2011 jeffrey.chang + * [WCXRP00000864] [MT5931] Add command to adjust OSC stable time + * modify driver to set OSC stable time after f/w download + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Support current measure mode, assigned by registry (XP only). + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result + * in OID handling layer when the corresponding BSS is disconnected due to beacon timeout + * remove from scanning result when the BSS is disconnected due to beacon timeout. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to + * disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000137] [MT6620 Wi-Fi] [FW] Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * divide a single function into 2 part to surpress a weird compiler warning from gcc-4.4.0 + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 09 24 2010 cp.wu + * [WCXRP00000057] [MT6620 Wi-Fi][Driver] Modify online scan to a run-time switchable feature + * Modify online scan as a run-time adjustable option (for Windows, in registry) + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 26 2010 yuche.tsai + * NULL + * Add AT GO test configure mode under WinXP. + * Please enable 1. CFG_ENABLE_WIFI_DIRECT, 2. CFG_TEST_WIFI_DIRECT_GO, 3. CFG_SUPPORT_AAA + * + * 08 25 2010 george.huang + * NULL + * . + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid + * descriptor underflow under concurrent network operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * simplify timer usage. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add extra 64 adjustable parameters for CoEX scenario. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * 2) add 2 kal API for later integration + * + * 04 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change to use WIFI_TCM_ALWAYS_ON as firmware image + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add two option for ACK and ENCRYPTION for firmware download + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * separate wlanProcesQueuePacket() into 2 APIs upon request + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add new API: wlanProcessQueuedPackets() + * + * 02 11 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. add logic for firmware download + * * * 2. firmware image filename and start/load address are now retrieved from registry + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * 4) nicRxWaitResponse() revised + * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * 4. correct some HAL implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:39:55 GMT mtk02752 +** eliminate unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-10-13 21:58:41 GMT mtk01084 +** update for new macro define +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-05-19 10:43:06 GMT mtk01461 +** Add wlanReleasePendingOid() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-13 16:38:44 GMT mtk01084 +** add WIFI start function +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-08 16:51:14 GMT mtk01084 +** Update for the image download part +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-04-01 10:57:38 GMT mtk01461 +** Add wlanSendLeftClusteredFrames() for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-23 00:31:02 GMT mtk01461 +** Add declaration of FW Image download reference code +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:08:31 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:04 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_LIB_H +#define _WLAN_LIB_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "CFG_Wifi_File.h" +#include "rlm_domain.h" +#include "wlan_typedef.h" + + +extern BOOLEAN fgIsResetting; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define MAX_NUM_GROUP_ADDR 32 /* max number of group addresses */ + +#define TX_CS_TCP_UDP_GEN BIT(1) +#define TX_CS_IP_GEN BIT(0) + +#define CSUM_OFFLOAD_EN_TX_TCP BIT(0) +#define CSUM_OFFLOAD_EN_TX_UDP BIT(1) +#define CSUM_OFFLOAD_EN_TX_IP BIT(2) +#define CSUM_OFFLOAD_EN_RX_TCP BIT(3) +#define CSUM_OFFLOAD_EN_RX_UDP BIT(4) +#define CSUM_OFFLOAD_EN_RX_IPv4 BIT(5) +#define CSUM_OFFLOAD_EN_RX_IPv6 BIT(6) +#define CSUM_OFFLOAD_EN_TX_MASK BITS(0, 2) +#define CSUM_OFFLOAD_EN_ALL BITS(0, 6) + +/* TCP, UDP, IP Checksum */ +#define RX_CS_TYPE_UDP BIT(7) +#define RX_CS_TYPE_TCP BIT(6) +#define RX_CS_TYPE_IPv6 BIT(5) +#define RX_CS_TYPE_IPv4 BIT(4) + +#define RX_CS_STATUS_UDP BIT(3) +#define RX_CS_STATUS_TCP BIT(2) +#define RX_CS_STATUS_IP BIT(0) + +#define CSUM_NOT_SUPPORTED 0x0 + +#define TXPWR_USE_PDSLOPE 0 + +/* NVRAM error code definitions */ +#define NVRAM_ERROR_VERSION_MISMATCH BIT(1) +#define NVRAM_ERROR_INVALID_TXPWR BIT(2) +#define NVRAM_ERROR_INVALID_DPD BIT(3) +#define NVRAM_ERROR_INVALID_MAC_ADDR BIT(4) +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +#define NVRAM_POWER_LIMIT_TABLE_INVALID BIT(5) +#endif + +#define NUM_TC_RESOURCE_TO_STATISTICS 4 + +#define WLAN_CFG_ARGV_MAX 8 +#define WLAN_CFG_ENTRY_NUM_MAX 128 +#define WLAN_CFG_KEY_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_VALUE_LEN_MAX 32 /* include \x00 EOL */ +#define WLAN_CFG_FLAG_SKIP_CB BIT(0) +#define WLAN_CFG_FILE_BUF_SIZE 2048 + +#define WLAN_CFG_SET_CHIP_LEN_MAX 10 +#define WLAN_CFG_SET_DEBUG_LEVEL_LEN_MAX 10 +#define WLAN_CFG_SET_SW_CTRL_LEN_MAX 10 + +#define WLAN_OID_TIMEOUT_THRESHOLD 2000 /* OID timeout (in ms) */ +#define WLAN_OID_TIMEOUT_THRESHOLD_IN_RESETTING 300 /* OID timeout during chip-resetting (in ms) */ + +#define WLAN_OID_NO_ACK_THRESHOLD 3 + +#define WLAN_TX_THREAD_TASK_PRIORITY 0 /* If not setting the priority, 0 is the default */ +#define WLAN_TX_THREAD_TASK_NICE (-10) /* If not setting the nice, -10 is the default */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef WLAN_STATUS(*PFN_OID_HANDLER_FUNC) (IN P_ADAPTER_T prAdapter, + IN PVOID pvBuf, IN UINT_32 u4BufLen, OUT PUINT_32 pu4OutInfoLen); + +typedef enum _ENUM_CSUM_TYPE_T { + CSUM_TYPE_IPV4, + CSUM_TYPE_IPV6, + CSUM_TYPE_TCP, + CSUM_TYPE_UDP, + CSUM_TYPE_NUM +} ENUM_CSUM_TYPE_T, *P_ENUM_CSUM_TYPE_T; + +typedef enum _ENUM_CSUM_RESULT_T { + CSUM_RES_NONE, + CSUM_RES_SUCCESS, + CSUM_RES_FAILED, + CSUM_RES_NUM +} ENUM_CSUM_RESULT_T, *P_ENUM_CSUM_RESULT_T; + +typedef enum _ENUM_PHY_MODE_T { + ENUM_PHY_2G4_CCK, + ENUM_PHY_2G4_OFDM_BPSK, + ENUM_PHY_2G4_OFDM_QPSK, + ENUM_PHY_2G4_OFDM_16QAM, + ENUM_PHY_2G4_OFDM_48M, + ENUM_PHY_2G4_OFDM_54M, + ENUM_PHY_2G4_HT20_BPSK, + ENUM_PHY_2G4_HT20_QPSK, + ENUM_PHY_2G4_HT20_16QAM, + ENUM_PHY_2G4_HT20_MCS5, + ENUM_PHY_2G4_HT20_MCS6, + ENUM_PHY_2G4_HT20_MCS7, + ENUM_PHY_2G4_HT40_BPSK, + ENUM_PHY_2G4_HT40_QPSK, + ENUM_PHY_2G4_HT40_16QAM, + ENUM_PHY_2G4_HT40_MCS5, + ENUM_PHY_2G4_HT40_MCS6, + ENUM_PHY_2G4_HT40_MCS7, + ENUM_PHY_5G_OFDM_BPSK, + ENUM_PHY_5G_OFDM_QPSK, + ENUM_PHY_5G_OFDM_16QAM, + ENUM_PHY_5G_OFDM_48M, + ENUM_PHY_5G_OFDM_54M, + ENUM_PHY_5G_HT20_BPSK, + ENUM_PHY_5G_HT20_QPSK, + ENUM_PHY_5G_HT20_16QAM, + ENUM_PHY_5G_HT20_MCS5, + ENUM_PHY_5G_HT20_MCS6, + ENUM_PHY_5G_HT20_MCS7, + ENUM_PHY_5G_HT40_BPSK, + ENUM_PHY_5G_HT40_QPSK, + ENUM_PHY_5G_HT40_16QAM, + ENUM_PHY_5G_HT40_MCS5, + ENUM_PHY_5G_HT40_MCS6, + ENUM_PHY_5G_HT40_MCS7, + ENUM_PHY_MODE_NUM +} ENUM_PHY_MODE_T, *P_ENUM_PHY_MODE_T; + +typedef enum _ENUM_POWER_SAVE_POLL_MODE_T { + ENUM_POWER_SAVE_POLL_DISABLE, + ENUM_POWER_SAVE_POLL_LEGACY_NULL, + ENUM_POWER_SAVE_POLL_QOS_NULL, + ENUM_POWER_SAVE_POLL_NUM +} ENUM_POWER_SAVE_POLL_MODE_T, *P_ENUM_POWER_SAVE_POLL_MODE_T; + +typedef enum _ENUM_AC_TYPE_T { + ENUM_AC_TYPE_AC0, + ENUM_AC_TYPE_AC1, + ENUM_AC_TYPE_AC2, + ENUM_AC_TYPE_AC3, + ENUM_AC_TYPE_AC4, + ENUM_AC_TYPE_AC5, + ENUM_AC_TYPE_AC6, + ENUM_AC_TYPE_BMC, + ENUM_AC_TYPE_NUM +} ENUM_AC_TYPE_T, *P_ENUM_AC_TYPE_T; + +typedef enum _ENUM_ADV_AC_TYPE_T { + ENUM_ADV_AC_TYPE_RX_NSW, + ENUM_ADV_AC_TYPE_RX_PTA, + ENUM_ADV_AC_TYPE_RX_SP, + ENUM_ADV_AC_TYPE_TX_PTA, + ENUM_ADV_AC_TYPE_TX_RSP, + ENUM_ADV_AC_TYPE_NUM +} ENUM_ADV_AC_TYPE_T, *P_ENUM_ADV_AC_TYPE_T; + +typedef enum _ENUM_REG_CH_MAP_T { + REG_CH_MAP_COUNTRY_CODE, + REG_CH_MAP_TBL_IDX, + REG_CH_MAP_CUSTOMIZED, + REG_CH_MAP_NUM +} ENUM_REG_CH_MAP_T, *P_ENUM_REG_CH_MAP_T; + +#define CHIP_CONFIG_RESP_SIZE 320 +enum { + CHIP_CONFIG_TYPE_WO_RESPONSE = 0x00, + CHIP_CONFIG_TYPE_MEM8 = 0x01, + CHIP_CONFIG_TYPE_MEM32 = 0x02, + CHIP_CONFIG_TYPE_ASCII = 0x03, + CHIP_CONFIG_TYPE_BINARY = 0x04, + CHIP_CONFIG_TYPE_DRV_PASSTHROUGH = 0x05, + CHIP_CONFIG_TYPE_END +}; + +typedef struct _SET_TXPWR_CTRL_T { + INT_8 c2GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c2GHotspotPwrOffset; + INT_8 c2GP2pPwrOffset; + INT_8 c2GBowPwrOffset; + INT_8 c5GLegacyStaPwrOffset; /* Unit: 0.5dBm, default: 0 */ + INT_8 c5GHotspotPwrOffset; + INT_8 c5GP2pPwrOffset; + INT_8 c5GBowPwrOffset; + UINT_8 ucConcurrencePolicy; /* TX power policy when concurrence + in the same channel + 0: Highest power has priority + 1: Lowest power has priority */ + INT_8 acReserved1[3]; /* Must be zero */ + + /* Power limit by channel for all data rates */ + INT_8 acTxPwrLimit2G[14]; /* Channel 1~14, Unit: 0.5dBm */ + INT_8 acTxPwrLimit5G[4]; /* UNII 1~4 */ + INT_8 acReserved2[2]; /* Must be zero */ +} SET_TXPWR_CTRL_T, *P_SET_TXPWR_CTRL_T; + +/* For storing driver initialization value from glue layer */ +typedef struct _REG_INFO_T { + UINT_32 u4SdBlockSize; /* SDIO block size */ + UINT_32 u4SdBusWidth; /* SDIO bus width. 1 or 4 */ + UINT_32 u4SdClockRate; /* SDIO clock rate. (in unit of HZ) */ + UINT_32 u4StartAddress; /* Starting address of Wi-Fi Firmware */ + UINT_32 u4LoadAddress; /* Load address of Wi-Fi Firmware */ + UINT_16 aucFwImgFilename[65]; /* Firmware filename */ + UINT_16 aucFwImgFilenameE6[65]; /* Firmware filename for E6 */ + UINT_32 u4StartFreq; /* Start Frequency for Ad-Hoc network : in unit of KHz */ + UINT_32 u4AdhocMode; /* Default mode for Ad-Hoc network : ENUM_PARAM_AD_HOC_MODE_T */ + UINT_32 u4RddStartFreq; + UINT_32 u4RddStopFreq; + UINT_32 u4RddTestMode; + UINT_32 u4RddShutFreq; + UINT_32 u4RddDfs; + INT_32 i4HighRssiThreshold; + INT_32 i4MediumRssiThreshold; + INT_32 i4LowRssiThreshold; + INT_32 au4TxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4RxPriorityTag[ENUM_AC_TYPE_NUM]; + INT_32 au4AdvPriorityTag[ENUM_ADV_AC_TYPE_NUM]; + UINT_32 u4FastPSPoll; + UINT_32 u4PTA; /* 0: disable, 1: enable */ + UINT_32 u4TXLimit; /* 0: disable, 1: enable */ + UINT_32 u4SilenceWindow; /* range: 100 - 625, unit: us */ + UINT_32 u4TXLimitThreshold; /* range: 250 - 1250, unit: us */ + UINT_32 u4PowerMode; + UINT_32 fgEnArpFilter; + UINT_32 u4PsCurrentMeasureEn; + UINT_32 u4UapsdAcBmp; + UINT_32 u4MaxSpLen; + UINT_32 fgDisOnlineScan; /* 0: enable online scan, non-zero: disable online scan */ + UINT_32 fgDisBcnLostDetection; /* 0: enable online scan, non-zero: disable online scan */ + UINT_32 u4FixedRate; /* 0: automatic, non-zero: fixed rate */ + UINT_32 u4ArSysParam0; + UINT_32 u4ArSysParam1; + UINT_32 u4ArSysParam2; + UINT_32 u4ArSysParam3; + UINT_32 fgDisRoaming; /* 0:enable roaming 1:disable */ + + /* NVRAM - MP Data -START- */ + UINT_8 aucMacAddr[6]; + UINT_16 au2CountryCode[4]; /* Country code (in ISO 3166-1 expression, ex: "US", "TW") */ + TX_PWR_PARAM_T rTxPwr; + UINT_8 aucEFUSE[144]; + UINT_8 ucTxPwrValid; + UINT_8 ucSupport5GBand; + UINT_8 fg2G4BandEdgePwrUsed; + INT_8 cBandEdgeMaxPwrCCK; + INT_8 cBandEdgeMaxPwrOFDM20; + INT_8 cBandEdgeMaxPwrOFDM40; + ENUM_REG_CH_MAP_T eRegChannelListMap; + UINT_8 ucRegChannelListIndex; + DOMAIN_INFO_ENTRY rDomainInfo; + /* NVRAM - MP Data -END- */ + + /* NVRAM - Functional Data -START- */ + UINT_8 uc2G4BwFixed20M; + UINT_8 uc5GBwFixed20M; + UINT_8 ucEnable5GBand; + UINT_8 uc2GRssiCompensation; + UINT_8 uc5GRssiCompensation; + UINT_8 fgRssiCompensationValidbit; + UINT_8 ucRxAntennanumber; + /* NVRAM - Functional Data -END- */ + +} REG_INFO_T, *P_REG_INFO_T; + +/* for divided firmware loading */ +typedef struct _FWDL_SECTION_INFO_T { + UINT_32 u4Offset; + UINT_32 u4Reserved; + UINT_32 u4Length; + UINT_32 u4DestAddr; +} FWDL_SECTION_INFO_T, *P_FWDL_SECTION_INFO_T; + +typedef struct _FIRMWARE_DIVIDED_DOWNLOAD_T { + UINT_32 u4Signature; + UINT_32 u4CRC; /* CRC calculated without first 8 bytes included */ + UINT_32 u4NumOfEntries; + UINT_32 u4Reserved; + FWDL_SECTION_INFO_T arSection[]; +} FIRMWARE_DIVIDED_DOWNLOAD_T, *P_FIRMWARE_DIVIDED_DOWNLOAD_T; + +typedef struct _PARAM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_MCR_RW_STRUCT_T, *P_PARAM_MCR_RW_STRUCT_T; + +typedef struct _PARAM_GET_STA_STATISTICS { + UINT_8 ucInvalid; + UINT_8 ucVersion; + /* Per-STA statistic */ + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + UINT_32 u4LinkScore; + UINT_32 u4Flag; + + /* From FW */ + UINT_8 ucPer; /* base: 128 */ + UINT_8 ucRcpi; + UINT_32 u4PhyMode; + UINT_16 u2LinkSpeed; /* unit is 0.5 Mbits */ + + UINT_32 u4TxFailCount; + UINT_32 u4TxLifeTimeoutCount; + UINT_32 u4TxAverageAirTime; + + /* From driver */ + UINT_32 u4TxTotalCount; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxAverageProcessTime; + + UINT_32 u4TxMaxTime; + UINT_32 u4TxMaxHifTime; + UINT_32 u4TxAverageHifTime; + + /* + * How many packages Enqueue/Deqeue during statistics interval + */ + UINT_32 u4EnqueueCounter; + UINT_32 u4DequeueCounter; + + UINT_32 u4EnqueueStaCounter; + UINT_32 u4DequeueStaCounter; + + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrRxCnt; + UINT_32 IsrTxCnt; + + UINT_32 au4TcResourceEmptyCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4DequeueNoTcResource[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceBackCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_32 au4TcResourceUsedCount[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcResourceWantedCount[NUM_TC_RESOURCE_TO_STATISTICS]; + + UINT_32 au4TcQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + /* Global queue management statistic */ + UINT_32 au4TcAverageQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + UINT_32 au4TcCurrentQueLen[NUM_TC_RESOURCE_TO_STATISTICS]; + + /* Reserved fields */ + UINT_8 au4Reserved[32]; +} PARAM_GET_STA_STA_STATISTICS, *P_PARAM_GET_STA_STATISTICS; + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR { + NL80211_TESTMODE_AVAILABLE_CHAN_INVALID = 0, + NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, + + NL80211_TESTMODE_AVAILABLE_CHAN_NUM, +} ENUM_TESTMODE_AVAILABLE_CHAN_ATTR; + +typedef struct _LTE_SAFE_CH_INFO_T { + UINT_32 au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_NUM - 1]; +} LTE_SAFE_CH_INFO_T, *P_CMD_LTE_SAFE_CH_INFO_T; + + /* Record Each CH Load */ +typedef struct _PARAM_CHN_LOAD_INFO { + /* Per-CHN Load */ + UINT_32 u4Flag; + + UINT_8 ucChannel; + UINT_16 u2ChannelLoad; + UINT_8 au4Reserved[1]; + + UINT_16 u2APNum; + UINT_16 u2APNumTmpCountingBuf; + + /* Reserved fields */ + UINT_8 au4Reserved1[8]; +} PARAM_CHN_LOAD_INFO, *P_PARAM_CHN_LOAD_INFO; + +typedef struct _PARAM_GET_CHN_LOAD { + LTE_SAFE_CH_INFO_T rLteSafeChnList; + PARAM_CHN_LOAD_INFO rEachChnLoad[MAX_AUTO_CHAL_NUM]; + BOOLEAN fgDataReadyBit; + UINT_8 au4Reserved1[3]; +} PARAM_GET_CHN_LOAD, *P_PARAM_GET_CHN_LOAD; + +typedef struct _PARAM_PREFER_CHN_INFO { + + UINT_8 ucChannel; + UINT_16 u2APNum; + UINT_8 au4Reserved1[1]; +} PARAM_PREFER_CHN_INFO, *P_PARAM_PREFER_CHN_INFO; + +typedef struct _PARAM_GET_LTE_MODE { + /* Event Body */ + UINT_8 ucVersion; + UINT_8 aucReserved1[3]; + UINT_32 u4Flags; /* Bit0: valid */ + + LTE_SAFE_CH_INFO_T LTE_MODE; + UINT_8 aucReserved4[3]; + + UINT_8 aucReserved[4]; + +} PARAM_GET_LTE_MODE, *P_PARAM_GET_LTE_MODE; + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define BUILD_SIGN(ch0, ch1, ch2, ch3) \ + ((UINT_32)(UINT_8)(ch0) | ((UINT_32)(UINT_8)(ch1) << 8) | \ + ((UINT_32)(UINT_8)(ch2) << 16) | ((UINT_32)(UINT_8)(ch3) << 24)) + +#define MTK_WIFI_SIGNATURE BUILD_SIGN('M', 'T', 'K', 'W') + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +P_ADAPTER_T wlanAdapterCreate(IN P_GLUE_INFO_T prGlueInfo); + +VOID wlanAdapterDestroy(IN P_ADAPTER_T prAdapter); + +VOID wlanCardEjected(IN P_ADAPTER_T prAdapter); + +VOID wlanIST(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanISR(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgGlobalIntrCtrl); + +WLAN_STATUS wlanProcessCommandQueue(IN P_ADAPTER_T prAdapter, IN P_QUE_T prCmdQue); + +WLAN_STATUS wlanSendCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID wlanReleaseCommand(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +VOID wlanReleasePendingOid(IN P_ADAPTER_T prAdapter, IN ULONG ulData); + +VOID wlanReleasePendingCMDbyNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType); + +VOID wlanReturnPacket(IN P_ADAPTER_T prAdapter, IN PVOID pvPacket); + +VOID wlanReturnIndicatedPacketsTimeOut(IN P_ADAPTER_T prAdapter, IN ULONG ulData); + +WLAN_STATUS +wlanQueryInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidQryHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4QryInfoLen); + +WLAN_STATUS +wlanSetInformation(IN P_ADAPTER_T prAdapter, + IN PFN_OID_HANDLER_FUNC pfOidSetHandler, + IN PVOID pvInfoBuf, IN UINT_32 u4InfoBufLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanAdapterStart(IN P_ADAPTER_T prAdapter, + IN P_REG_INFO_T prRegInfo, IN PVOID pvFwImageMapFile, IN UINT_32 u4FwImageFileLength); + +WLAN_STATUS wlanAdapterStop(IN P_ADAPTER_T prAdapter); + +#if CFG_SUPPORT_WAPI +BOOLEAN wlanQueryWapiMode(IN P_ADAPTER_T prAdapter); +#endif + +VOID wlanReturnRxPacket(IN PVOID pvAdapter, IN PVOID pvPacket); + +VOID wlanRxSetBroadcast(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableBroadcast); + +BOOLEAN wlanIsHandlerNeedHwAccess(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); + +VOID wlanSetPromiscuousMode(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnablePromiscuousMode); + +#if CFG_ENABLE_FW_DOWNLOAD +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION +WLAN_STATUS +wlanImageSectionDownloadAggregated(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); +#endif + +WLAN_STATUS +wlanImageSectionDownload(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DestAddr, IN UINT_32 u4ImgSecSize, IN PUINT_8 pucImgSecBuf); + +#if !CFG_ENABLE_FW_DOWNLOAD_ACK +WLAN_STATUS wlanImageQueryStatus(IN P_ADAPTER_T prAdapter); +#else +WLAN_STATUS wlanImageSectionDownloadStatus(IN P_ADAPTER_T prAdapter, IN UINT_8 ucCmdSeqNum); +#endif + +WLAN_STATUS wlanConfigWifiFunc(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable, IN UINT_32 u4StartAddress); + +UINT_32 wlanCRC32(PUINT_8 buf, UINT_32 len); + +#endif + +WLAN_STATUS wlanSendNicPowerCtrlCmd(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPowerMode); + +BOOLEAN wlanIsHandlerAllowedInRFTest(IN PFN_OID_HANDLER_FUNC pfnOidHandler, IN BOOLEAN fgSetInfo); + +WLAN_STATUS wlanProcessQueuedSwRfb(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead); + +WLAN_STATUS wlanProcessQueuedMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead); + +BOOLEAN wlanoidTimeoutCheck(IN P_ADAPTER_T prAdapter, IN PFN_OID_HANDLER_FUNC pfnOidHandler); + +VOID wlanoidClearTimeoutCheck(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanUpdateNetworkAddress(IN P_ADAPTER_T prAdapter); + +BOOLEAN wlanQueryTestMode(IN P_ADAPTER_T prAdapter); + +/* Security Frame Handling */ +BOOLEAN wlanProcessSecurityFrame(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prPacket); + +VOID wlanSecurityFrameTxDone(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf); + +VOID wlanSecurityFrameTxTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo); + +/*----------------------------------------------------------------------------*/ +/* OID/IOCTL Handling */ +/*----------------------------------------------------------------------------*/ +VOID wlanClearScanningResult(IN P_ADAPTER_T prAdapter); + +VOID wlanClearBssInScanningResult(IN P_ADAPTER_T prAdapter, IN PUINT_8 arBSSID); + +#if CFG_TEST_WIFI_DIRECT_GO +VOID wlanEnableP2pFunction(IN P_ADAPTER_T prAdapter); + +VOID wlanEnableATGO(IN P_ADAPTER_T prAdapter); +#endif + +/*----------------------------------------------------------------------------*/ +/* Address Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPermanentAddress(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryNicCapability(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* NIC Capability Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryDebugCode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Compiler Flags Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryCompileFlags(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* PD MCR Retrieve by Polling */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanQueryPdMcr(IN P_ADAPTER_T prAdapter, IN P_PARAM_MCR_RW_STRUCT_T prMcrRdInfo); +/*----------------------------------------------------------------------------*/ +/* Loading Manufacture Data */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanLoadManufactureData(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo); + +/*----------------------------------------------------------------------------*/ +/* Media Stream Mode */ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanResetMediaStreamMode(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Timer Timeout Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanTimerTimeoutCheck(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Mailbox Message Check (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanProcessMboxMessage(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* TX Pending Packets Handling (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanEnqueueTxPacket(IN P_ADAPTER_T prAdapter, IN P_NATIVE_PACKET prNativePacket); + +WLAN_STATUS wlanFlushTxPendingPackets(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanTxPendingPackets(IN P_ADAPTER_T prAdapter, IN OUT PBOOLEAN pfgHwAccess); + +/*----------------------------------------------------------------------------*/ +/* Low Power Acquire/Release (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanAcquirePowerControl(IN P_ADAPTER_T prAdapter); + +WLAN_STATUS wlanReleasePowerControl(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* Pending Packets Number Reporting (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +UINT_32 wlanGetTxPendingFrameCount(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* ACPI state inquiry (for Glue Layer) */ +/*----------------------------------------------------------------------------*/ +ENUM_ACPI_STATE_T wlanGetAcpiState(IN P_ADAPTER_T prAdapter); + +VOID wlanSetAcpiState(IN P_ADAPTER_T prAdapter, IN ENUM_ACPI_STATE_T ePowerState); + +VOID wlanDefTxPowerCfg(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* get ECO version from Revision ID register (for Win32) */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetEcoVersion(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* set preferred band configuration corresponding to network type */ +/*----------------------------------------------------------------------------*/ +VOID +wlanSetPreferBandByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* get currently operating channel information */ +/*----------------------------------------------------------------------------*/ +UINT_8 wlanGetChannelNumberByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* get BSS Descriptor information */ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T wlanGetTargetBssDescByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex); + +/*----------------------------------------------------------------------------*/ +/* check for system configuration to generate message on scan list */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS wlanCheckSystemConfiguration(IN P_ADAPTER_T prAdapter); + +/*----------------------------------------------------------------------------*/ +/* query sta statistics information from driver and firmware */ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidQueryStaStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS wlanCfgParseArgument(CHAR *cmdLine, INT_32 *argc, CHAR *argv[]); + +P_WLAN_CFG_ENTRY_T wlanCfgGetEntry(IN P_ADAPTER_T prAdapter, const PCHAR pucKey); + +WLAN_STATUS +wlanCfgGet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, PCHAR pucValueDef, UINT_32 u4Flags); + +UINT_32 wlanCfgGetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4ValueDef); + +INT_32 wlanCfgGetInt32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, INT_32 i4ValueDef); + +WLAN_STATUS wlanCfgSetUint32(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, UINT_32 u4Value); + +WLAN_STATUS wlanCfgSet(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, PCHAR pucValue, UINT_32 u4Flags); + +WLAN_STATUS +wlanCfgSetCb(IN P_ADAPTER_T prAdapter, const PCHAR pucKey, WLAN_CFG_SET_CB pfSetCb, void *pPrivate, UINT_32 u4Flags); + +#if CFG_SUPPORT_CFG_FILE +WLAN_STATUS wlanCfgInit(IN P_ADAPTER_T prAdapter, PUINT_8 pucConfigBuf, UINT_32 u4ConfigBufLen, UINT_32 u4Flags); + +VOID wlanCfgApply(IN P_ADAPTER_T prAdapter); +#endif /* CFG_SUPPORT_CFG_FILE */ + +extern VOID mtk_wcn_wmt_set_wifi_ver(UINT_32 Value); + +#endif /* _WLAN_LIB_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h new file mode 100644 index 0000000000000..45919df996e95 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_oid.h @@ -0,0 +1,1715 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/include/wlan_oid.h#2 +*/ + +/*! \file "wlan_oid.h" + \brief This file contains the declairation file of the WLAN OID processing routines + of Windows driver for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_oid.h + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 02 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * Support UAPSD/OppPS/NoA parameter setting + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wifi_var.h, precomp.h, cnm_timer.h (data type only) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move timer callback to glue layer. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 18 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement Wakeup-on-LAN except firmware integration part + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. + * + + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add NULL OID implementation for WOL-related OIDs. + * + * 04 22 2010 cp.wu + * [WPD00003830]add OID_802_11_PRIVACY_FILTER support + * enable RX filter OID + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) implement timeout mechanism when OID is pending for longer than 1 second + * * * 2) allow OID_802_11_CONFIGURATION to be executed when RF test mode is turned on + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * OID_802_11_RSSI, + * * * * OID_802_11_RSSI_TRIGGER, + * * * * OID_802_11_STATISTICS, + * * * * OID_802_11_DISASSOCIATE, + * * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_SUPPORTED_RATES / OID_802_11_DESIRED_RATES +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-08 11:38:11 GMT mtk02752 +** add declares for RF test related APIs +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-24 22:41:53 GMT mtk02752 +** remove u4SysTime, MSDN 10-second will be implemented in FW side +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 20:30:13 GMT mtk02752 +** add u4SysTime field in PARAM_BSSID_EX_T +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-12 19:48:35 GMT mtk02752 +** allow upper layer to set a packet filter with PROMISCUOUS mode +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:12:12 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _WLAN_OID_H +#define _WLAN_OID_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#if DBG +extern UINT_8 aucDebugModule[DBG_MODULE_NUM]; +extern UINT_32 u4DebugModule; +UINT_32 u4DebugModuleTemp; +#endif /* DBG */ +extern int sprintf(char *buf, const char *fmt, ...); + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define PARAM_MAX_LEN_SSID 32 + +#define PARAM_MAC_ADDR_LEN 6 + +#define ETHERNET_HEADER_SZ 14 +#define ETHERNET_MIN_PKT_SZ 60 +#define ETHERNET_MAX_PKT_SZ 1514 + +#define PARAM_MAX_LEN_RATES 8 +#define PARAM_MAX_LEN_RATES_EX 16 + +#define PARAM_AUTH_REQUEST_REAUTH 0x01 +#define PARAM_AUTH_REQUEST_KEYUPDATE 0x02 +#define PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 +#define PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E + +#define PARAM_EEPROM_READ_METHOD_READ 1 +#define PARAM_EEPROM_READ_METHOD_GETSIZE 0 + +#define PARAM_WHQL_RSSI_MAX_DBM (-10) +#define PARAM_WHQL_RSSI_MIN_DBM (-200) + +#define PARAM_DEVICE_WAKE_UP_ENABLE 0x00000001 +#define PARAM_DEVICE_WAKE_ON_PATTERN_MATCH_ENABLE 0x00000002 +#define PARAM_DEVICE_WAKE_ON_MAGIC_PACKET_ENABLE 0x00000004 + +#define PARAM_WAKE_UP_MAGIC_PACKET 0x00000001 +#define PARAM_WAKE_UP_PATTERN_MATCH 0x00000002 +#define PARAM_WAKE_UP_LINK_CHANGE 0x00000004 + +/* Packet filter bit definitioin (UINT_32 bit-wise definition) */ +#define PARAM_PACKET_FILTER_DIRECTED 0x00000001 +#define PARAM_PACKET_FILTER_MULTICAST 0x00000002 +#define PARAM_PACKET_FILTER_ALL_MULTICAST 0x00000004 +#define PARAM_PACKET_FILTER_BROADCAST 0x00000008 +#define PARAM_PACKET_FILTER_PROMISCUOUS 0x00000020 +#define PARAM_PACKET_FILTER_ALL_LOCAL 0x00000080 +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#define PARAM_PACKET_FILTER_P2P_MASK 0xC0000000 +#define PARAM_PACKET_FILTER_PROBE_REQ 0x80000000 +#define PARAM_PACKET_FILTER_ACTION_FRAME 0x40000000 +#endif + +#if CFG_SLT_SUPPORT +#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ + PARAM_PACKET_FILTER_MULTICAST | \ + PARAM_PACKET_FILTER_BROADCAST | \ + PARAM_PACKET_FILTER_ALL_MULTICAST) +#else +#define PARAM_PACKET_FILTER_SUPPORTED (PARAM_PACKET_FILTER_DIRECTED | \ + PARAM_PACKET_FILTER_MULTICAST | \ + PARAM_PACKET_FILTER_BROADCAST) +#endif + +#define PARAM_MEM_DUMP_MAX_SIZE 2048 + +#define BT_PROFILE_PARAM_LEN 8 +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Parameters of User Configuration which match to NDIS5.1 */ +/*----------------------------------------------------------------------------*/ +/* NDIS_802_11_AUTHENTICATION_MODE */ +typedef enum _ENUM_PARAM_AUTH_MODE_T { + AUTH_MODE_OPEN, /*!< Open system */ + AUTH_MODE_SHARED, /*!< Shared key */ + AUTH_MODE_AUTO_SWITCH, /*!< Either open system or shared key */ + AUTH_MODE_WPA, + AUTH_MODE_WPA_PSK, + AUTH_MODE_WPA_NONE, /*!< For Ad hoc */ + AUTH_MODE_WPA2, + AUTH_MODE_WPA2_PSK, + AUTH_MODE_NUM /*!< Upper bound, not real case */ +} ENUM_PARAM_AUTH_MODE_T, *P_ENUM_PARAM_AUTH_MODE_T; + +/* NDIS_802_11_ENCRYPTION_STATUS *//* Encryption types */ +typedef enum _ENUM_WEP_STATUS_T { + ENUM_WEP_ENABLED, + ENUM_ENCRYPTION1_ENABLED = ENUM_WEP_ENABLED, + ENUM_WEP_DISABLED, + ENUM_ENCRYPTION_DISABLED = ENUM_WEP_DISABLED, + ENUM_WEP_KEY_ABSENT, + ENUM_ENCRYPTION1_KEY_ABSENT = ENUM_WEP_KEY_ABSENT, + ENUM_WEP_NOT_SUPPORTED, + ENUM_ENCRYPTION_NOT_SUPPORTED = ENUM_WEP_NOT_SUPPORTED, + ENUM_ENCRYPTION2_ENABLED, + ENUM_ENCRYPTION2_KEY_ABSENT, + ENUM_ENCRYPTION3_ENABLED, + ENUM_ENCRYPTION3_KEY_ABSENT +} ENUM_PARAM_ENCRYPTION_STATUS_T, *P_ENUM_PARAM_ENCRYPTION_STATUS_T; + +typedef UINT_8 PARAM_MAC_ADDRESS[PARAM_MAC_ADDR_LEN]; + +typedef UINT_32 PARAM_KEY_INDEX; +typedef UINT_64 PARAM_KEY_RSC; +typedef INT_32 PARAM_RSSI; + +typedef UINT_32 PARAM_FRAGMENTATION_THRESHOLD; +typedef UINT_32 PARAM_RTS_THRESHOLD; + +typedef UINT_8 PARAM_RATES[PARAM_MAX_LEN_RATES]; +typedef UINT_8 PARAM_RATES_EX[PARAM_MAX_LEN_RATES_EX]; + +typedef enum _ENUM_PARAM_PHY_TYPE_T { + PHY_TYPE_802_11ABG = 0, /*!< Can associated with 802.11abg AP, + Scan dual band. */ + PHY_TYPE_802_11BG, /*!< Can associated with 802_11bg AP, + Scan single band and not report 802_11a BSSs. */ + PHY_TYPE_802_11G, /*!< Can associated with 802_11g only AP, + Scan single band and not report 802_11ab BSSs. */ + PHY_TYPE_802_11A, /*!< Can associated with 802_11a only AP, + Scan single band and not report 802_11bg BSSs. */ + PHY_TYPE_802_11B, /*!< Can associated with 802_11b only AP, + Scan single band and not report 802_11ag BSSs. */ + PHY_TYPE_NUM /* 5 */ +} ENUM_PARAM_PHY_TYPE_T, *P_ENUM_PARAM_PHY_TYPE_T; + +typedef enum _ENUM_PARAM_OP_MODE_T { + NET_TYPE_IBSS = 0, /*!< Try to merge/establish an AdHoc, do periodic SCAN for merging. */ + NET_TYPE_INFRA, /*!< Try to join an Infrastructure, do periodic SCAN for joining. */ + NET_TYPE_AUTO_SWITCH, /*!< Try to join an Infrastructure, if fail then try to merge or + establish an AdHoc, do periodic SCAN for joining or merging. */ + NET_TYPE_DEDICATED_IBSS, /*!< Try to merge an AdHoc first, + if fail then establish AdHoc permanently, no more SCAN. */ + NET_TYPE_NUM /* 4 */ +} ENUM_PARAM_OP_MODE_T, *P_ENUM_PARAM_OP_MODE_T; + +typedef struct _PARAM_SSID_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 aucSsid[PARAM_MAX_LEN_SSID]; + UINT_32 u4CenterFreq; +} PARAM_SSID_T, *P_PARAM_SSID_T; + +typedef struct _PARAM_CONNECT_T { + UINT_32 u4SsidLen; /*!< SSID length in bytes. Zero length is broadcast(any) SSID */ + UINT_8 *pucSsid; + UINT_8 *pucBssid; + UINT_32 u4CenterFreq; +} PARAM_CONNECT_T, *P_PARAM_CONNECT_T; + +/* This is enum defined for user to select an AdHoc Mode */ +typedef enum _ENUM_PARAM_AD_HOC_MODE_T { + AD_HOC_MODE_11B = 0, /*!< Create 11b IBSS if we support 802.11abg/802.11bg. */ + AD_HOC_MODE_MIXED_11BG, /*!< Create 11bg mixed IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11G, /*!< Create 11g only IBSS if we support 802.11abg/802.11bg/802.11g. */ + AD_HOC_MODE_11A, /*!< Create 11a only IBSS if we support 802.11abg. */ + AD_HOC_MODE_NUM /* 4 */ +} ENUM_PARAM_AD_HOC_MODE_T, *P_ENUM_PARAM_AD_HOC_MODE_T; + +typedef enum _ENUM_PARAM_MEDIA_STATE_T { + PARAM_MEDIA_STATE_CONNECTED, + PARAM_MEDIA_STATE_DISCONNECTED, + PARAM_MEDIA_STATE_TO_BE_INDICATED /* for following MSDN re-association behavior */ +} ENUM_PARAM_MEDIA_STATE_T, *P_ENUM_PARAM_MEDIA_STATE_T; + +typedef enum _ENUM_PARAM_NETWORK_TYPE_T { + PARAM_NETWORK_TYPE_FH, + PARAM_NETWORK_TYPE_DS, + PARAM_NETWORK_TYPE_OFDM5, + PARAM_NETWORK_TYPE_OFDM24, + PARAM_NETWORK_TYPE_AUTOMODE, + PARAM_NETWORK_TYPE_NUM /*!< Upper bound, not real case */ +} ENUM_PARAM_NETWORK_TYPE_T, *P_ENUM_PARAM_NETWORK_TYPE_T; + +typedef struct _PARAM_NETWORK_TYPE_LIST { + UINT_32 NumberOfItems; /*!< At least 1 */ + ENUM_PARAM_NETWORK_TYPE_T eNetworkType[1]; +} PARAM_NETWORK_TYPE_LIST, *PPARAM_NETWORK_TYPE_LIST; + +typedef enum _ENUM_PARAM_PRIVACY_FILTER_T { + PRIVACY_FILTER_ACCEPT_ALL, + PRIVACY_FILTER_8021xWEP, + PRIVACY_FILTER_NUM +} ENUM_PARAM_PRIVACY_FILTER_T, *P_ENUM_PARAM_PRIVACY_FILTER_T; + +typedef enum _ENUM_RELOAD_DEFAULTS { + ENUM_RELOAD_WEP_KEYS +} PARAM_RELOAD_DEFAULTS, *P_PARAM_RELOAD_DEFAULTS; + +typedef struct _PARAM_PM_PACKET_PATTERN { + UINT_32 Priority; /* Importance of the given pattern. */ + UINT_32 Reserved; /* Context information for transports. */ + UINT_32 MaskSize; /* Size in bytes of the pattern mask. */ + UINT_32 PatternOffset; /* Offset from beginning of this */ + /* structure to the pattern bytes. */ + UINT_32 PatternSize; /* Size in bytes of the pattern. */ + UINT_32 PatternFlags; /* Flags (TBD). */ +} PARAM_PM_PACKET_PATTERN, *P_PARAM_PM_PACKET_PATTERN; + +/*--------------------------------------------------------------*/ +/*! \brief Struct definition to indicate specific event. */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_STATUS_TYPE_T { + ENUM_STATUS_TYPE_AUTHENTICATION, + ENUM_STATUS_TYPE_MEDIA_STREAM_MODE, + ENUM_STATUS_TYPE_CANDIDATE_LIST, + ENUM_STATUS_TYPE_NUM /*!< Upper bound, not real case */ +} ENUM_STATUS_TYPE_T, *P_ENUM_STATUS_TYPE_T; + +typedef struct _PARAM_802_11_CONFIG_FH_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4HopPattern; /*!< Defined as 802.11 */ + UINT_32 u4HopSet; /*!< to one if non-802.11 */ + UINT_32 u4DwellTime; /*!< In unit of Kusec */ +} PARAM_802_11_CONFIG_FH_T, *P_PARAM_802_11_CONFIG_FH_T; + +typedef struct _PARAM_802_11_CONFIG_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4BeaconPeriod; /*!< In unit of Kusec */ + UINT_32 u4ATIMWindow; /*!< In unit of Kusec */ + UINT_32 u4DSConfig; /*!< Channel frequency in unit of kHz */ + PARAM_802_11_CONFIG_FH_T rFHConfig; +} PARAM_802_11_CONFIG_T, *P_PARAM_802_11_CONFIG_T; + +typedef struct _PARAM_STATUS_INDICATION_T { + ENUM_STATUS_TYPE_T eStatusType; +} PARAM_STATUS_INDICATION_T, *P_PARAM_STATUS_INDICATION_T; + +typedef struct _PARAM_AUTH_REQUEST_T { + UINT_32 u4Length; /*!< Length of this struct */ + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4Flags; /*!< Definitions are as follows */ +} PARAM_AUTH_REQUEST_T, *P_PARAM_AUTH_REQUEST_T; + +typedef struct _PARAM_AUTH_EVENT_T { + PARAM_STATUS_INDICATION_T rStatus; + PARAM_AUTH_REQUEST_T arRequest[1]; +} PARAM_AUTH_EVENT_T, *P_PARAM_AUTH_EVENT_T; + +/*! \brief Capabilities, privacy, rssi and IEs of each BSSID */ +typedef struct _PARAM_BSSID_EX_T { + UINT_32 u4Length; /*!< Length of structure */ + PARAM_MAC_ADDRESS arMacAddress; /*!< BSSID */ + UINT_8 Reserved[2]; + PARAM_SSID_T rSsid; /*!< SSID */ + UINT_32 u4Privacy; /*!< Need WEP encryption */ + PARAM_RSSI rRssi; /*!< in dBm */ + ENUM_PARAM_NETWORK_TYPE_T eNetworkTypeInUse; + PARAM_802_11_CONFIG_T rConfiguration; + ENUM_PARAM_OP_MODE_T eOpMode; + PARAM_RATES_EX rSupportedRates; + UINT_32 u4IELength; + UINT_8 aucIEs[1]; +} PARAM_BSSID_EX_T, *P_PARAM_BSSID_EX_T; + +typedef struct _PARAM_BSSID_LIST_EX { + UINT_32 u4NumberOfItems; /*!< at least 1 */ + PARAM_BSSID_EX_T arBssid[1]; +} PARAM_BSSID_LIST_EX_T, *P_PARAM_BSSID_LIST_EX_T; + +typedef struct _PARAM_WEP_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< 0: pairwise key, others group keys */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} PARAM_WEP_T, *P_PARAM_WEP_T; + +/*! \brief Key mapping of BSSID */ +typedef struct _PARAM_KEY_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ + PARAM_KEY_RSC rKeyRSC; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} PARAM_KEY_T, *P_PARAM_KEY_T; + +typedef struct _PARAM_REMOVE_KEY_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ +} PARAM_REMOVE_KEY_T, *P_PARAM_REMOVE_KEY_T; + +#if CFG_SUPPORT_WAPI +typedef enum _ENUM_KEY_TYPE { + ENUM_WPI_PAIRWISE_KEY = 0, + ENUM_WPI_GROUP_KEY +} ENUM_KEY_TYPE; + +typedef enum _ENUM_WPI_PROTECT_TYPE { + ENUM_WPI_NONE, + ENUM_WPI_RX, + ENUM_WPI_TX, + ENUM_WPI_RX_TX +} ENUM_WPI_PROTECT_TYPE; + +typedef struct _PARAM_WPI_KEY_T { + ENUM_KEY_TYPE eKeyType; + ENUM_WPI_PROTECT_TYPE eDirection; + UINT_8 ucKeyID; + UINT_8 aucRsv[3]; + UINT_8 aucAddrIndex[12]; + UINT_32 u4LenWPIEK; + UINT_8 aucWPIEK[256]; + UINT_32 u4LenWPICK; + UINT_8 aucWPICK[256]; + UINT_8 aucPN[16]; +} PARAM_WPI_KEY_T, *P_PARAM_WPI_KEY_T; +#endif + +typedef enum _PARAM_POWER_MODE { + Param_PowerModeCAM, + Param_PowerModeMAX_PSP, + Param_PowerModeFast_PSP, +#if CFG_SUPPORT_DBG_POWERMODE + Param_PowerModeKeepActiveOn, /* privilege mode, always active */ + Param_PowerModeKeepActiveOff, /* to leave privilege mode */ +#endif + Param_PowerModeMax /* Upper bound, not real case */ +} PARAM_POWER_MODE, *PPARAM_POWER_MODE; + +typedef enum _PARAM_DEVICE_POWER_STATE { + ParamDeviceStateUnspecified = 0, + ParamDeviceStateD0, + ParamDeviceStateD1, + ParamDeviceStateD2, + ParamDeviceStateD3, + ParamDeviceStateMaximum +} PARAM_DEVICE_POWER_STATE, *PPARAM_DEVICE_POWER_STATE; + +#if CFG_SUPPORT_802_11D + +/*! \brief The enumeration definitions for OID_IPN_MULTI_DOMAIN_CAPABILITY */ +typedef enum _PARAM_MULTI_DOMAIN_CAPABILITY { + ParamMultiDomainCapDisabled, + ParamMultiDomainCapEnabled +} PARAM_MULTI_DOMAIN_CAPABILITY, *P_PARAM_MULTI_DOMAIN_CAPABILITY; +#endif + +typedef struct _COUNTRY_STRING_ENTRY { + UINT_8 aucCountryCode[2]; + UINT_8 aucEnvironmentCode[2]; +} COUNTRY_STRING_ENTRY, *P_COUNTRY_STRING_ENTRY; + +/* Power management related definition and enumerations */ +#define UAPSD_NONE 0 +#define UAPSD_AC0 (BIT(0) | BIT(4)) +#define UAPSD_AC1 (BIT(1) | BIT(5)) +#define UAPSD_AC2 (BIT(2) | BIT(6)) +#define UAPSD_AC3 (BIT(3) | BIT(7)) +#define UAPSD_ALL (UAPSD_AC0 | UAPSD_AC1 | UAPSD_AC2 | UAPSD_AC3) + +typedef enum _ENUM_POWER_SAVE_PROFILE_T { + ENUM_PSP_CONTINUOUS_ACTIVE = 0, + ENUM_PSP_CONTINUOUS_POWER_SAVE, + ENUM_PSP_FAST_SWITCH, + ENUM_PSP_NUM +} ENUM_POWER_SAVE_PROFILE_T, *PENUM_POWER_SAVE_PROFILE_T; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query testing type. */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_802_11_TEST_T { + UINT_32 u4Length; + UINT_32 u4Type; + union { + PARAM_AUTH_EVENT_T AuthenticationEvent; + PARAM_RSSI RssiTrigger; + } u; +} PARAM_802_11_TEST_T, *P_PARAM_802_11_TEST_T; + +/*--------------------------------------------------------------*/ +/*! \brief Set/Query authentication and encryption capability. */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_AUTH_ENCRYPTION_T { + ENUM_PARAM_AUTH_MODE_T eAuthModeSupported; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncryptStatusSupported; +} PARAM_AUTH_ENCRYPTION_T, *P_PARAM_AUTH_ENCRYPTION_T; + +typedef struct _PARAM_CAPABILITY_T { + UINT_32 u4Length; + UINT_32 u4Version; + UINT_32 u4NoOfPMKIDs; + UINT_32 u4NoOfAuthEncryptPairsSupported; + PARAM_AUTH_ENCRYPTION_T arAuthenticationEncryptionSupported[1]; +} PARAM_CAPABILITY_T, *P_PARAM_CAPABILITY_T; + +typedef UINT_8 PARAM_PMKID_VALUE[16]; + +typedef struct _PARAM_BSSID_INFO_T { + PARAM_MAC_ADDRESS arBSSID; + PARAM_PMKID_VALUE arPMKID; +} PARAM_BSSID_INFO_T, *P_PARAM_BSSID_INFO_T; + +typedef struct _PARAM_PMKID_T { + UINT_32 u4Length; + UINT_32 u4BSSIDInfoCount; + PARAM_BSSID_INFO_T arBSSIDInfo[1]; +} PARAM_PMKID_T, *P_PARAM_PMKID_T; + +/*! \brief PMKID candidate lists. */ +typedef struct _PARAM_PMKID_CANDIDATE_T { + PARAM_MAC_ADDRESS arBSSID; + UINT_32 u4Flags; +} PARAM_PMKID_CANDIDATE_T, *P_PARAM_PMKID_CANDIDATE_T; + +/* #ifdef LINUX */ +typedef struct _PARAM_PMKID_CANDIDATE_LIST_T { + UINT_32 u4Version; /*!< Version */ + UINT_32 u4NumCandidates; /*!< How many candidates follow */ + PARAM_PMKID_CANDIDATE_T arCandidateList[1]; +} PARAM_PMKID_CANDIDATE_LIST_T, *P_PARAM_PMKID_CANDIDATE_LIST_T; +/* #endif */ + +typedef struct _PARAM_CUSTOM_MCR_RW_STRUCT_T { + UINT_32 u4McrOffset; + UINT_32 u4McrData; +} PARAM_CUSTOM_MCR_RW_STRUCT_T, *P_PARAM_CUSTOM_MCR_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_MEM_DUMP_STRUCT_T { + UINT_32 u4Address; + UINT_32 u4Length; + UINT_32 u4RemainLength; + UINT_8 ucFragNum; +} PARAM_CUSTOM_MEM_DUMP_STRUCT_T, *P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T; + +typedef struct _PARAM_CUSTOM_SW_CTRL_STRUCT_T { + UINT_32 u4Id; + UINT_32 u4Data; +} PARAM_CUSTOM_SW_CTRL_STRUCT_T, *P_PARAM_CUSTOM_SW_CTRL_STRUCT_T; + +typedef struct _CMD_CHIP_CONFIG_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} CMD_CHIP_CONFIG_T, *P_CMD_CHIP_CONFIG_T; + +typedef struct _PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T { + UINT_16 u2Id; + UINT_8 ucType; + UINT_8 ucRespType; + UINT_16 u2MsgSize; + UINT_8 aucReserved0[2]; + UINT_8 aucCmd[CHIP_CONFIG_RESP_SIZE]; +} PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T, *P_PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_KEY_CFG_STRUCT_T { + UINT_8 aucKey[WLAN_CFG_KEY_LEN_MAX]; + UINT_8 aucValue[WLAN_CFG_VALUE_LEN_MAX]; +} PARAM_CUSTOM_KEY_CFG_STRUCT_T, *P_PARAM_CUSTOM_KEY_CFG_STRUCT_T; + +typedef struct _PARAM_CUSTOM_EEPROM_RW_STRUCT_T { + UINT_8 ucEepromMethod; /* For read only read: 1, query size: 0 */ + UINT_8 ucEepromIndex; + UINT_8 reserved; + UINT_16 u2EepromData; +} PARAM_CUSTOM_EEPROM_RW_STRUCT_T, *P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T, +PARAM_CUSTOM_NVRAM_RW_STRUCT_T, *P_PARAM_CUSTOM_NVRAM_RW_STRUCT_T; + +typedef struct _PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T { + UINT_8 bmfgApsdEnAc; /* b0~3: trigger-en AC0~3. b4~7: delivery-en AC0~3 */ + UINT_8 ucIsEnterPsAtOnce; /* enter PS immediately without 5 second guard after connected */ + UINT_8 ucIsDisableUcTrigger; /* not to trigger UC on beacon TIM is matched (under U-APSD) */ + UINT_8 reserved; +} PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T, *P_PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T; + +typedef struct _PARAM_CUSTOM_NOA_PARAM_STRUCT_T { + UINT_32 u4NoaDurationMs; + UINT_32 u4NoaIntervalMs; + UINT_32 u4NoaCount; +} PARAM_CUSTOM_NOA_PARAM_STRUCT_T, *P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T { + UINT_32 u4CTwindowMs; +} PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T, *P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T { + UINT_8 fgEnAPSD; + UINT_8 fgEnAPSD_AcBe; + UINT_8 fgEnAPSD_AcBk; + UINT_8 fgEnAPSD_AcVo; + UINT_8 fgEnAPSD_AcVi; + UINT_8 ucMaxSpLen; + UINT_8 aucResv[2]; +} PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T, *P_PARAM_CUSTOM_UAPSD_PARAM_STRUCT_T; + +typedef struct _PARAM_CUSTOM_P2P_SET_STRUCT_T { + UINT_32 u4Enable; + UINT_32 u4Mode; +} PARAM_CUSTOM_P2P_SET_STRUCT_T, *P_PARAM_CUSTOM_P2P_SET_STRUCT_T; + +typedef enum _ENUM_CFG_SRC_TYPE_T { + CFG_SRC_TYPE_EEPROM, + CFG_SRC_TYPE_NVRAM, + CFG_SRC_TYPE_UNKNOWN, + CFG_SRC_TYPE_NUM +} ENUM_CFG_SRC_TYPE_T, *P_ENUM_CFG_SRC_TYPE_T; + +typedef enum _ENUM_EEPROM_TYPE_T { + EEPROM_TYPE_NO, + EEPROM_TYPE_PRESENT, + EEPROM_TYPE_NUM +} ENUM_EEPROM_TYPE_T, *P_ENUM_EEPROM_TYPE_T; + +typedef struct _PARAM_QOS_TSINFO { + UINT_8 ucTrafficType; /* Traffic Type: 1 for isochronous 0 for asynchronous */ + UINT_8 ucTid; /* TSID: must be between 8 ~ 15 */ + UINT_8 ucDirection; /* direction */ + UINT_8 ucAccessPolicy; /* access policy */ + UINT_8 ucAggregation; /* aggregation */ + UINT_8 ucApsd; /* APSD */ + UINT_8 ucuserPriority; /* user priority */ + UINT_8 ucTsInfoAckPolicy; /* TSINFO ACK policy */ + UINT_8 ucSchedule; /* Schedule */ +} PARAM_QOS_TSINFO, *P_PARAM_QOS_TSINFO; + +typedef struct _PARAM_QOS_TSPEC { + PARAM_QOS_TSINFO rTsInfo; /* TS info field */ + UINT_16 u2NominalMSDUSize; /* nominal MSDU size */ + UINT_16 u2MaxMSDUsize; /* maximum MSDU size */ + UINT_32 u4MinSvcIntv; /* minimum service interval */ + UINT_32 u4MaxSvcIntv; /* maximum service interval */ + UINT_32 u4InactIntv; /* inactivity interval */ + UINT_32 u4SpsIntv; /* suspension interval */ + UINT_32 u4SvcStartTime; /* service start time */ + UINT_32 u4MinDataRate; /* minimum Data rate */ + UINT_32 u4MeanDataRate; /* mean data rate */ + UINT_32 u4PeakDataRate; /* peak data rate */ + UINT_32 u4MaxBurstSize; /* maximum burst size */ + UINT_32 u4DelayBound; /* delay bound */ + UINT_32 u4MinPHYRate; /* minimum PHY rate */ + UINT_16 u2Sba; /* surplus bandwidth allowance */ + UINT_16 u2MediumTime; /* medium time */ +} PARAM_QOS_TSPEC, *P_PARAM_QOS_TSPEC; + +typedef struct _PARAM_QOS_ADDTS_REQ_INFO { + PARAM_QOS_TSPEC rTspec; +} PARAM_QOS_ADDTS_REQ_INFO, *P_PARAM_QOS_ADDTS_REQ_INFO; + +typedef struct _PARAM_VOIP_CONFIG { + UINT_32 u4VoipTrafficInterval; /* 0: disable VOIP configuration */ +} PARAM_VOIP_CONFIG, *P_PARAM_VOIP_CONFIG; + +/*802.11 Statistics Struct*/ +typedef struct _PARAM_802_11_STATISTICS_STRUCT_T { + UINT_32 u4Length; /* Length of structure */ + LARGE_INTEGER rTransmittedFragmentCount; + LARGE_INTEGER rMulticastTransmittedFrameCount; + LARGE_INTEGER rFailedCount; + LARGE_INTEGER rRetryCount; + LARGE_INTEGER rMultipleRetryCount; + LARGE_INTEGER rRTSSuccessCount; + LARGE_INTEGER rRTSFailureCount; + LARGE_INTEGER rACKFailureCount; + LARGE_INTEGER rFrameDuplicateCount; + LARGE_INTEGER rReceivedFragmentCount; + LARGE_INTEGER rMulticastReceivedFrameCount; + LARGE_INTEGER rFCSErrorCount; + LARGE_INTEGER rTKIPLocalMICFailures; + LARGE_INTEGER rTKIPICVErrors; + LARGE_INTEGER rTKIPCounterMeasuresInvoked; + LARGE_INTEGER rTKIPReplays; + LARGE_INTEGER rCCMPFormatErrors; + LARGE_INTEGER rCCMPReplays; + LARGE_INTEGER rCCMPDecryptErrors; + LARGE_INTEGER rFourWayHandshakeFailures; + LARGE_INTEGER rWEPUndecryptableCount; + LARGE_INTEGER rWEPICVErrorCount; + LARGE_INTEGER rDecryptSuccessCount; + LARGE_INTEGER rDecryptFailureCount; +} PARAM_802_11_STATISTICS_STRUCT_T, *P_PARAM_802_11_STATISTICS_STRUCT_T; + +/* Linux Network Device Statistics Struct */ +typedef struct _PARAM_LINUX_NETDEV_STATISTICS_T { + UINT_32 u4RxPackets; + UINT_32 u4TxPackets; + UINT_32 u4RxBytes; + UINT_32 u4TxBytes; + UINT_32 u4RxErrors; + UINT_32 u4TxErrors; + UINT_32 u4Multicast; +} PARAM_LINUX_NETDEV_STATISTICS_T, *P_PARAM_LINUX_NETDEV_STATISTICS_T; + +typedef struct _PARAM_MTK_WIFI_TEST_STRUCT_T { + UINT_32 u4FuncIndex; + UINT_32 u4FuncData; +} PARAM_MTK_WIFI_TEST_STRUCT_T, *P_PARAM_MTK_WIFI_TEST_STRUCT_T; + +/* 802.11 Media stream constraints */ +typedef enum _ENUM_MEDIA_STREAM_MODE { + ENUM_MEDIA_STREAM_OFF, + ENUM_MEDIA_STREAM_ON +} ENUM_MEDIA_STREAM_MODE, *P_ENUM_MEDIA_STREAM_MODE; + +/* for NDIS 5.1 Media Streaming Change */ +typedef struct _PARAM_MEDIA_STREAMING_INDICATION { + PARAM_STATUS_INDICATION_T rStatus; + ENUM_MEDIA_STREAM_MODE eMediaStreamMode; +} PARAM_MEDIA_STREAMING_INDICATION, *P_PARAM_MEDIA_STREAMING_INDICATION; + +#define PARAM_PROTOCOL_ID_DEFAULT 0x00 +#define PARAM_PROTOCOL_ID_TCP_IP 0x02 +#define PARAM_PROTOCOL_ID_IPX 0x06 +#define PARAM_PROTOCOL_ID_NBF 0x07 +#define PARAM_PROTOCOL_ID_MAX 0x0F +#define PARAM_PROTOCOL_ID_MASK 0x0F + +/* for NDIS OID_GEN_NETWORK_LAYER_ADDRESSES */ +typedef struct _PARAM_NETWORK_ADDRESS_IP { + UINT_16 sin_port; + UINT_32 in_addr; + UINT_8 sin_zero[8]; +} PARAM_NETWORK_ADDRESS_IP, *P_PARAM_NETWORK_ADDRESS_IP; + +typedef struct _PARAM_NETWORK_ADDRESS { + UINT_16 u2AddressLength; /* length in bytes of Address[] in this */ + UINT_16 u2AddressType; /* type of this address (PARAM_PROTOCOL_ID_XXX above) */ + UINT_8 aucAddress[1]; /* actually AddressLength bytes long */ +} PARAM_NETWORK_ADDRESS, *P_PARAM_NETWORK_ADDRESS; + +/* The following is used with OID_GEN_NETWORK_LAYER_ADDRESSES to set network layer addresses on an interface */ + +typedef struct _PARAM_NETWORK_ADDRESS_LIST { + UINT_32 u4AddressCount; /* number of addresses following */ + UINT_16 u2AddressType; /* type of this address (NDIS_PROTOCOL_ID_XXX above) */ + PARAM_NETWORK_ADDRESS arAddress[1]; /* actually AddressCount elements long */ +} PARAM_NETWORK_ADDRESS_LIST, *P_PARAM_NETWORK_ADDRESS_LIST; + +#if CFG_SLT_SUPPORT + +#define FIXED_BW_LG20 0x0000 +#define FIXED_BW_UL20 0x2000 +#define FIXED_BW_DL40 0x3000 + +#define FIXED_EXT_CHNL_U20 0x4000 /* For AGG register. */ +#define FIXED_EXT_CHNL_L20 0xC000 /* For AGG regsiter. */ + +typedef enum _ENUM_MTK_LP_TEST_MODE_T { + ENUM_MTK_LP_TEST_NORMAL, + ENUM_MTK_LP_TEST_GOLDEN_SAMPLE, + ENUM_MTK_LP_TEST_DUT, + ENUM_MTK_LP_TEST_MODE_NUM +} ENUM_MTK_LP_TEST_MODE_T, *P_ENUM_MTK_LP_TEST_MODE_T; + +typedef enum _ENUM_MTK_SLT_FUNC_IDX_T { + ENUM_MTK_SLT_FUNC_DO_NOTHING, + ENUM_MTK_SLT_FUNC_INITIAL, + ENUM_MTK_SLT_FUNC_RATE_SET, + ENUM_MTK_SLT_FUNC_LP_SET, + ENUM_MTK_SLT_FUNC_NUM +} ENUM_MTK_SLT_FUNC_IDX_T, *P_ENUM_MTK_SLT_FUNC_IDX_T; + +typedef struct _PARAM_MTK_SLT_LP_TEST_STRUCT_T { + ENUM_MTK_LP_TEST_MODE_T rLpTestMode; + UINT_32 u4BcnRcvNum; +} PARAM_MTK_SLT_LP_TEST_STRUCT_T, *P_PARAM_MTK_SLT_LP_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TR_TEST_STRUCT_T { + ENUM_PARAM_NETWORK_TYPE_T rNetworkType; /* Network Type OFDM5G or OFDM2.4G */ + UINT_32 u4FixedRate; /* Fixed Rate including BW */ +} PARAM_MTK_SLT_TR_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TR_TEST_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_INITIAL_STRUCT_T { + UINT_8 aucTargetMacAddr[PARAM_MAC_ADDR_LEN]; + UINT_16 u2SiteID; +} PARAM_MTK_SLT_INITIAL_STRUCT_T, *P_PARAM_MTK_SLT_INITIAL_STRUCT_T; + +typedef struct _PARAM_MTK_SLT_TEST_STRUCT_T { + ENUM_MTK_SLT_FUNC_IDX_T rSltFuncIdx; + UINT_32 u4Length; /* Length of structure, + including myself */ + UINT_32 u4FuncInfoLen; /* Include following content + field and myself */ + union { + PARAM_MTK_SLT_INITIAL_STRUCT_T rMtkInitTest; + PARAM_MTK_SLT_LP_TEST_STRUCT_T rMtkLpTest; + PARAM_MTK_SLT_TR_TEST_STRUCT_T rMtkTRTest; + } unFuncInfoContent; + +} PARAM_MTK_SLT_TEST_STRUCT_T, *P_PARAM_MTK_SLT_TEST_STRUCT_T; + +#endif + +/*--------------------------------------------------------------*/ +/*! \brief For Fixed Rate Configuration (Registry) */ +/*--------------------------------------------------------------*/ +typedef enum _ENUM_REGISTRY_FIXED_RATE_T { + FIXED_RATE_NONE, + FIXED_RATE_1M, + FIXED_RATE_2M, + FIXED_RATE_5_5M, + FIXED_RATE_11M, + FIXED_RATE_6M, + FIXED_RATE_9M, + FIXED_RATE_12M, + FIXED_RATE_18M, + FIXED_RATE_24M, + FIXED_RATE_36M, + FIXED_RATE_48M, + FIXED_RATE_54M, + FIXED_RATE_MCS0_20M_800NS, + FIXED_RATE_MCS1_20M_800NS, + FIXED_RATE_MCS2_20M_800NS, + FIXED_RATE_MCS3_20M_800NS, + FIXED_RATE_MCS4_20M_800NS, + FIXED_RATE_MCS5_20M_800NS, + FIXED_RATE_MCS6_20M_800NS, + FIXED_RATE_MCS7_20M_800NS, + FIXED_RATE_MCS0_20M_400NS, + FIXED_RATE_MCS1_20M_400NS, + FIXED_RATE_MCS2_20M_400NS, + FIXED_RATE_MCS3_20M_400NS, + FIXED_RATE_MCS4_20M_400NS, + FIXED_RATE_MCS5_20M_400NS, + FIXED_RATE_MCS6_20M_400NS, + FIXED_RATE_MCS7_20M_400NS, + FIXED_RATE_MCS0_40M_800NS, + FIXED_RATE_MCS1_40M_800NS, + FIXED_RATE_MCS2_40M_800NS, + FIXED_RATE_MCS3_40M_800NS, + FIXED_RATE_MCS4_40M_800NS, + FIXED_RATE_MCS5_40M_800NS, + FIXED_RATE_MCS6_40M_800NS, + FIXED_RATE_MCS7_40M_800NS, + FIXED_RATE_MCS32_800NS, + FIXED_RATE_MCS0_40M_400NS, + FIXED_RATE_MCS1_40M_400NS, + FIXED_RATE_MCS2_40M_400NS, + FIXED_RATE_MCS3_40M_400NS, + FIXED_RATE_MCS4_40M_400NS, + FIXED_RATE_MCS5_40M_400NS, + FIXED_RATE_MCS6_40M_400NS, + FIXED_RATE_MCS7_40M_400NS, + FIXED_RATE_MCS32_400NS, + FIXED_RATE_NUM +} ENUM_REGISTRY_FIXED_RATE_T, *P_ENUM_REGISTRY_FIXED_RATE_T; + +typedef enum _ENUM_BT_CMD_T { + BT_CMD_PROFILE = 0, + BT_CMD_UPDATE, + BT_CMD_NUM +} ENUM_BT_CMD_T; + +typedef enum _ENUM_BT_PROFILE_T { + BT_PROFILE_CUSTOM = 0, + BT_PROFILE_SCO, + BT_PROFILE_ACL, + BT_PROFILE_MIXED, + BT_PROFILE_NO_CONNECTION, + BT_PROFILE_NUM +} ENUM_BT_PROFILE_T; + +typedef struct _PTA_PROFILE_T { + ENUM_BT_PROFILE_T eBtProfile; + union { + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + /* 0: sco reserved slot time, + 1: sco idle slot time, + 2: acl throughput, + 3: bt tx power, + 4: bt rssi + 5: VoIP interval + 6: BIT(0) Use this field, BIT(1) 0 apply single/ 1 dual PTA setting. + */ + UINT_32 au4Btcr[4]; + } u; +} PTA_PROFILE_T, *P_PTA_PROFILE_T; + +typedef struct _PTA_IPC_T { + UINT_8 ucCmd; + UINT_8 ucLen; + union { + PTA_PROFILE_T rProfile; + UINT_8 aucBTPParams[BT_PROFILE_PARAM_LEN]; + } u; +} PARAM_PTA_IPC_T, *P_PARAM_PTA_IPC_T, PTA_IPC_T, *P_PTA_IPC_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scan Request Container */ +/*--------------------------------------------------------------*/ + +typedef struct _PARAM_SCAN_REQUEST_EXT_T { + PARAM_SSID_T rSsid; + UINT_32 u4IELength; + PUINT_8 pucIE; +} PARAM_SCAN_REQUEST_EXT_T, *P_PARAM_SCAN_REQUEST_EXT_T; + +/*--------------------------------------------------------------*/ +/*! \brief CFG80211 Scheduled Scan Request Container */ +/*--------------------------------------------------------------*/ +typedef struct _PARAM_SCHED_SCAN_REQUEST_T { + UINT_32 u4SsidNum; + PARAM_SSID_T arSsid[CFG_SCAN_SSID_MATCH_MAX_NUM]; + UINT_32 u4IELength; + PUINT_8 pucIE; + UINT_16 u2ScanInterval; /* in milliseconds */ +} PARAM_SCHED_SCAN_REQUEST, *P_PARAM_SCHED_SCAN_REQUEST; + +#if CFG_SUPPORT_HOTSPOT_2_0 +typedef struct _PARAM_HS20_SET_BSSID_POOL { + BOOLEAN fgIsEnable; + UINT_8 ucNumBssidPool; + PARAM_MAC_ADDRESS arBSSID[8]; +} PARAM_HS20_SET_BSSID_POOL, *P_PARAM_HS20_SET_BSSID_POOL; + +#endif + +typedef struct _PARAM_CUSTOM_WFD_DEBUG_STRUCT_T { + UINT_8 ucWFDDebugMode; /* 0: Disable + 1:Enable but only show inqueue skb ether SN + 2.show skb ether SN and the statistics of skb inqueue time */ + UINT_16 u2SNPeriod; /* The Ether SN Period */ + + UINT_8 reserved; +} PARAM_CUSTOM_WFD_DEBUG_STRUCT_T, *P_PARAM_CUSTOM_WFD_DEBUG_STRUCT_T; + +typedef struct _CMD_GET_PSCAN_CAPABILITY { +/* TBD */ +} CMD_GET_GSCAN_CAPABILITY, *P_CMD_GET_GSCAN_CAPABILITY; + +typedef struct _CMD_SET_PSCAN_ENABLE { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} CMD_SET_PSCAN_ENABLE, *P_CMD_SET_PSCAN_ENABLE; + +typedef enum _ENUM_PSCAN_ACT_T { + ENABLE, + DISABLE, + SUSPEND, + CLEAR +} ENUM_PSCAN_ACT_T, *P_ENUM_PSCAN_ACT_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*--------------------------------------------------------------*/ +/* Routines to set parameters or query information. */ +/*--------------------------------------------------------------*/ +/***** Routines in wlan_oid.c *****/ +WLAN_STATUS +wlanoidQueryNetworkTypesSupported(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNetworkTypeInUse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBssid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetBssidListScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetBssidListScanExt(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBssidList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetBssid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetSsid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetConnect(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySsid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryInfrastructureMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetInfrastructureMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAuthMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAuthMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if 0 +WLAN_STATUS +wlanoidQueryPrivacyFilter(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetPrivacyFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEncryptionStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAddWep(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveWep(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +_wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, IN BOOLEAN fgIsOid, IN UINT_8 ucAlgorithmId, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetAddKey(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetReloadDefaults(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetTest(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCapability(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryFrequency(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetFrequency(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAtimWindow(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAtimWindow(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRssi(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRssiTrigger(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetRssiTrigger(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRtsThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetRtsThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuery802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSet802dot11PowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID prSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryPmkid(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetPmkid(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySupportedRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryDesiredRates(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetDesiredRates(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryPermanentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuf, IN UINT_32 u4QueryBufLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryLinkSpeed(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMcrRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMemDump(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMcrWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetSwCtrlWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEepromRead(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetEepromWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestRxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRfTestTxStatus(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryOidInterfaceVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryVendorId(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMulticastList(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRcvError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvNoBuffer(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryRcvCrcError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryStatistics(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +WLAN_STATUS +wlanoidQueryStatisticsPL(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#ifdef LINUX + +WLAN_STATUS +wlanoidQueryStatisticsForLinux(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#endif + +WLAN_STATUS +wlanoidQueryMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetMediaStreamMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryRcvOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitOk(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitError(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCurrentPacketFilter(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAcpiDevicePowerState(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetDisassociate(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryFragThreshold(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetFragThreshold(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryAdHocMode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetAdHocMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBeaconInterval(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetBeaconInterval(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetCurrentAddr(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +WLAN_STATUS +wlanoidSetCSUMOffload(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryMaxFrameSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryMaxTotalSize(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCurrentLookahead(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/* RF Test related APIs */ +WLAN_STATUS +wlanoidRftestSetTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidRftestSetAbortTestMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidRftestQueryAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidRftestSetAutoTest(IN P_ADAPTER_T prAdapter, + OUT PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_WAPI +WLAN_STATUS +wlanoidSetWapiMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWapiAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetWapiKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_WPS2 +WLAN_STATUS +wlanoidSetWSCAssocInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_ENABLE_WAKEUP_ON_LAN +WLAN_STATUS +wlanoidSetAddWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveWakeupPattern(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryEnableWakeup(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 u4QueryInfoLen); + +WLAN_STATUS +wlanoidSetEnableWakeup(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetWiFiWmmPsTest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetTxAmpdu(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBSSInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetAddbaReject(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryNvramRead(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetNvramWrite(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryCfgSrcType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryEepromType(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetCountryCode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS wlanSendMemDumpCmd(IN P_ADAPTER_T prAdapter, IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen); + +#if CFG_SLT_SUPPORT + +WLAN_STATUS +wlanoidQuerySLTStatus(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidUpdateSLTMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#endif + +#if 0 +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetBT(IN P_ADAPTER_T prAdapter, IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBT(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetTxPower(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +#if CFG_SUPPORT_BUILD_DATE_CODE +WLAN_STATUS +wlanoidQueryBuildDateCode(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#endif + +/* +WLAN_STATUS +wlanoidQueryBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); + +WLAN_STATUS +wlanoidSetBtSingleAntenna ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidSetPta ( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +WLAN_STATUS +wlanoidQueryPta ( + IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, + IN UINT_32 u4QueryBufferLen, + OUT PUINT_32 pu4QueryInfoLen + ); +*/ + +#if CFG_ENABLE_WIFI_DIRECT +WLAN_STATUS +wlanoidSetP2pMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +#if CFG_SUPPORT_BATCH_SCAN +WLAN_STATUS +wlanoidSetBatchScanReq(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryBatchScanResult(IN P_ADAPTER_T prAdapter, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +WLAN_STATUS +wlanoidSetHS20Info(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetInterworkingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRoamingConsortiumIEInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetHS20BssidPool(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +WLAN_STATUS +wlanoidSetRoamingInfo(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetWfdDebugMode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetStartSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetStopSchedScan(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNAction(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNAParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetGSCNAConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetGSCNResult(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetTxRateInfo( + IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen + ); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +WLAN_STATUS +wlanoidSetChipConfig(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +WLAN_STATUS +wlanoidNotifyFwSuspend(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, + IN UINT_32 u4SetBufferLen, + OUT PUINT_32 pu4SetInfoLen); + +#endif /* _WLAN_OID_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h new file mode 100644 index 0000000000000..0b558d64034d4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/include/wlan_p2p.h @@ -0,0 +1,307 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/include/wlan_p2p.h#3 +*/ + +/*! \file "wlan_p2p.h" + \brief This file contains the declairations of Wi-Fi Direct command + processing routines for MediaTek Inc. 802.11 Wireless LAN Adapters. +*/ + +/* +** Log: wlan_p2p.h + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version + * query & set support for service discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channel Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface + * for supporting Wi-Fi Direct Service Discovery + * ioctl implementations for P2P Service Discovery + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface + * for supporting Wi-Fi Direct Service Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * support wlanoidSetP2pPowerSaveProfile() in P2P + * + * 08 16 2010 george.huang + * NULL + * Support wlanoidSetNetworkAddress() for P2P + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * MT6620 is not supporting NDIS_PACKET_TYPE_PROMISCUOUS. + * + + * +** +*/ + +#ifndef _WLAN_P2P_H +#define _WLAN_P2P_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* Service Discovery */ +typedef struct _PARAM_P2P_SEND_SD_RESPONSE { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucChannelNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_SEND_SD_RESPONSE, *P_PARAM_P2P_SEND_SD_RESPONSE; + +typedef struct _PARAM_P2P_GET_SD_REQUEST { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_GET_SD_REQUEST, *P_PARAM_P2P_GET_SD_REQUEST; + +typedef struct _PARAM_P2P_GET_SD_REQUEST_EX { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 ucChannelNum; /* Channel Number Where SD Request is received. */ + UINT_8 ucSeqNum; /* Get SD Request by sequence number. */ + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_GET_SD_REQUEST_EX, *P_PARAM_P2P_GET_SD_REQUEST_EX; + +typedef struct _PARAM_P2P_SEND_SD_REQUEST { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucVersionNum; /* Indicate the Service Discovery Supplicant Version. */ + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_SEND_SD_REQUEST, *P_PARAM_P2P_SEND_SD_REQUEST; + +/* Service Discovery 1.0. */ +typedef struct _PARAM_P2P_GET_SD_RESPONSE { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_GET_SD_RESPONSE, *P_PARAM_P2P_GET_SD_RESPONSE; + +/* Service Discovery 2.0. */ +typedef struct _PARAM_P2P_GET_SD_RESPONSE_EX { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 ucSeqNum; /* Get SD Response by sequence number. */ + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} PARAM_P2P_GET_SD_RESPONSE_EX, *P_PARAM_P2P_GET_SD_RESPONSE_EX; + +typedef struct _PARAM_P2P_TERMINATE_SD_PHASE { + PARAM_MAC_ADDRESS rPeerAddr; +} PARAM_P2P_TERMINATE_SD_PHASE, *P_PARAM_P2P_TERMINATE_SD_PHASE; + +/*! \brief Key mapping of BSSID */ +typedef struct _P2P_PARAM_KEY_T { + UINT_32 u4Length; /*!< Length of structure */ + UINT_32 u4KeyIndex; /*!< KeyID */ + UINT_32 u4KeyLength; /*!< Key length in bytes */ + PARAM_MAC_ADDRESS arBSSID; /*!< MAC address */ + PARAM_KEY_RSC rKeyRSC; + UINT_8 aucKeyMaterial[32]; /*!< Key content by above setting */ +} P2P_PARAM_KEY_T, *P_P2P_PARAM_KEY_T; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/*--------------------------------------------------------------*/ +/* Routines to handle command */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSetAddP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetRemoveP2PKey(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2PMulticastList(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/*--------------------------------------------------------------*/ +/* Service Discovery Subroutines */ +/*--------------------------------------------------------------*/ +WLAN_STATUS +wlanoidSendP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSendP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetP2PSDResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 puQueryInfoLen); + +WLAN_STATUS +wlanoidSetP2PTerminateSDPhase(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_ANTI_PIRACY +WLAN_STATUS +wlanoidSetSecCheckRequest(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidGetSecCheckResponse(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +WLAN_STATUS +wlanoidSetNoaParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetOppPsParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetUApsdParam(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pPowerSaveProfile(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pSetNetworkAddress(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidQueryP2pOpChannel(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidQueryP2pVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +WLAN_STATUS +wlanoidSetP2pSupplicantVersion(IN P_ADAPTER_T prAdapter, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +WLAN_STATUS +wlanoidSetP2pWPSmode(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +WLAN_STATUS +wlanoidQueryP2pRssi(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); +#endif + +/*--------------------------------------------------------------*/ +/* Callbacks for event indication */ +/*--------------------------------------------------------------*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif +#endif /* _WLAN_P2P_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c new file mode 100644 index 0000000000000..f2324f13280e3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/aaa_fsm.c @@ -0,0 +1,1303 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/aaa_fsm.c#2 +*/ + +/*! \file "aaa_fsm.c" + \brief This file defines the FSM for AAA MODULE. + + This file defines the FSM for AAA MODULE. +*/ + +/* +** Log: aaa_fsm.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 22 2012 yuche.tsai + * NULL + * Solve sigma test 5.1.3 issue, assoc response should have P2P IE. + * + * 12 02 2011 yuche.tsai + * NULL + * Resolve inorder issue under AP mode. + * + * data frame may TX before assoc response frame. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 06 17 2011 terry.wu + * NULL + * Add BoW 11N support. + * + * 06 02 2011 eddie.chen + * [WCXRP00000759] [MT6620 Wi-Fi][DRV] Update RCPI in AAA + * Update RCPI when receiving Assoc request. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 09 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * Skip to call p2pRunEventAAAComplete to avoid indicate STA connect twice. + * + * 03 04 2011 terry.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * Remove unused variable. + * + * 02 16 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Add more check after RX assoc frame under Hot-Spot mode. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 15 2011 puff.wen + * NULL + * [On behalf of Frog] Add CFG_ENABLE_WIFI_DIRECT to p2pRunEventAAAComplete + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify AAA flow according to CM's comment. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 29 2010 yuche.tsai + * NULL + * Fix Compile warning, type cast from UINT_32 to UINT_16. + * + * 08 26 2010 yuche.tsai + * NULL + * In P2P AT GO test mode under WinXP, we would not indicate connected event to host. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 17 2010 yuche.tsai + * NULL + * Fix bug while enabling P2P GO. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * modify due to P2P functino call prototype change. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 04 02 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify CFG flags + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * add support of Driver STA_RECORD_T activation + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS aaaFsmSendEventJoinComplete(WLAN_STATUS rJoinStatus, P_STA_RECORD_T prStaRec, P_SW_RFB_T prSwRfb) +{ + P_MSG_SAA_JOIN_COMP_T prJoinCompMsg; + + ASSERT(prStaRec); + + prJoinCompMsg = cnmMemAlloc(RAM_TYPE_TCM, sizeof(MSG_SAA_JOIN_COMP_T)); + if (!prJoinCompMsg) + return WLAN_STATUS_RESOURCES; + + if (IS_STA_IN_AIS(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + else if (IS_STA_IN_P2P(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + else if (IS_STA_IN_BOW(prStaRec)) + prJoinCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + else + ASSERT(0); + + prJoinCompMsg->rJoinStatus = rJoinStatus; + prJoinCompMsg->prStaRec = prStaRec; + prJoinCompMsg->prSwRfb = prSwRfb; + + mboxSendMsg(MBOX_ID_0, (P_MSG_HDR_T) prJoinCompMsg, MSG_SEND_METHOD_BUF); + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmSendEventJoinComplete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to AAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventStart(IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_JOIN_REQ_T prJoinReqMsg; + P_STA_RECORD_T prStaRec; + P_AIS_BSS_INFO_T prAisBssInfo; + + ASSERT(prMsgHdr); + + prJoinReqMsg = (P_MSG_SAA_JOIN_REQ_T) prMsgHdr; + prStaRec = prJoinReqMsg->prStaRec; + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM\n"); + + cnmMemFree(prMsgHdr); + + /* 4 <1> Validation of SAA Start Event */ + if (!IS_AP_STA(prStaRec->eStaType)) { + + DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + /* 4 <2> The previous JOIN process is not completed ? */ + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + /* 4 <3> Reset Status Code and Time */ + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + cnmTimerStopTimer(&prStaRec->rTxReqDoneOrRxRespTimer); + + prStaRec->ucStaState = STA_STATE_1; + + /* Trigger SAA MODULE */ + saaFsmSteps(prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventStart() */ +#endif + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Request Frame and then +* trigger AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aaaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + UINT_16 u2StatusCode; + BOOLEAN fgReplyAuth = FALSE; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + + ASSERT(prAdapter); + + do { + + /* 4 <1> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prBssInfo->fgIsNetActive) { + + /* 4 <1.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ + if (WLAN_STATUS_SUCCESS == + authProcessRxAuth1Frame(prAdapter, + prSwRfb, + prBssInfo->aucBSSID, + AUTH_ALGORITHM_NUM_OPEN_SYSTEM, + AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + /* 4 <1.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAuth = p2pFuncValidateAuth(prAdapter, + prSwRfb, &prStaRec, &u2StatusCode); + } else { + fgReplyAuth = TRUE; + } + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + break; + } + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* 4 <2> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { + + /* 4 <2.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + authProcessRxAuth1Frame(prAdapter, + prSwRfb, + prBssInfo->aucBSSID, + AUTH_ALGORITHM_NUM_OPEN_SYSTEM, + AUTH_TRANSACTION_SEQ_1, &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + + /* 4 <2.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAuth = + bowValidateAuth(prAdapter, prSwRfb, &prStaRec, &u2StatusCode); + + } else { + + fgReplyAuth = TRUE; + } + eNetTypeIndex = NETWORK_TYPE_BOW_INDEX; + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return; + } while (FALSE); + + if (prStaRec) { + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + } + /* 4 <3> Update STA_RECORD_T and reply Auth_2(Response to Auth_1) Frame */ + if (fgReplyAuth) { + + if (prStaRec) { + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(AAA, WARN, "Previous AuthAssocState (%d) != IDLE.\n", + prStaRec->eAuthAssocState); + } + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + } else { + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = u2StatusCode; + + prStaRec->ucAuthAlgNum = AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else { + /* NOTE(Kevin): We should have STA_RECORD_T if the status code was successful */ + ASSERT(!(u2StatusCode == STATUS_CODE_SUCCESSFUL)); + } + + /* NOTE: Ignore the return status for AAA */ + /* 4 <4> Reply Auth */ + authSendAuthFrame(prAdapter, prStaRec, eNetTypeIndex, prSwRfb, AUTH_TRANSACTION_SEQ_2, u2StatusCode); + + } + +} /* end of aaaFsmRunEventRxAuth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx (Re)Association Request Frame and then +* trigger AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS aaaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + UINT_16 u2StatusCode = STATUS_CODE_RESERVED; + BOOLEAN fgReplyAssocResp = FALSE; + + ASSERT(prAdapter); + + do { + + /* 4 <1> Check if we have the STA_RECORD_T for incoming Assoc Req */ + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + ASSERT(0); /* Only for debug phase */ + break; + } + + if (!IS_CLIENT_STA(prStaRec)) + break; + + if (prStaRec->ucStaState == STA_STATE_3) { + /* Do Reassocation */ + } else if ((prStaRec->ucStaState == STA_STATE_2) && + (prStaRec->eAuthAssocState == AAA_STATE_SEND_AUTH2)) { + /* Normal case */ + } else { + DBGLOG(AAA, INFO, "Previous AuthAssocState (%d) != SEND_AUTH2, ucStaState:%d.\n", + prStaRec->eAuthAssocState, + prStaRec->ucStaState); + /* TODO: Why assoc req event is faster than tx done of auth */ + if (prStaRec->eAuthAssocState != AAA_STATE_SEND_AUTH2) + break; + } + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + /* 4 <2> Check P2P network conditions */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prBssInfo->fgIsNetActive) { + + /* 4 <2.1> Validate Assoc Req Frame and get Status Code */ + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + /* 4 <2.2> Validate Assoc Req Frame for Network Specific Conditions */ + fgReplyAssocResp = p2pFuncValidateAssocReq(prAdapter, + prSwRfb, + (PUINT_16)&u2StatusCode); + } else { + fgReplyAssocResp = TRUE; + } + + break; + } + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* 4 <3> Check BOW network conditions */ +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]); + + if ((prBssInfo->fgIsNetActive) && (OP_MODE_BOW == prBssInfo->eCurrentOPMode)) { + + /* 4 <3.1> Validate Auth Frame by Auth Algorithm/Transation Seq */ + /* Check if for this BSSID */ + if (WLAN_STATUS_SUCCESS == + assocProcessRxAssocReqFrame(prAdapter, prSwRfb, &u2StatusCode)) { + + if (STATUS_CODE_SUCCESSFUL == u2StatusCode) { + + /* 4 <3.2> Validate Auth Frame for Network Specific Conditions */ + fgReplyAssocResp = + bowValidateAssocReq(prAdapter, prSwRfb, &u2StatusCode); + + } else { + + fgReplyAssocResp = TRUE; + } + + /* TODO(Kevin): Allocate a STA_RECORD_T for new client */ + break; + } + } + } +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + return WLAN_STATUS_SUCCESS; /* To release the SW_RFB_T */ + } while (FALSE); + + /* 4 <4> Update STA_RECORD_T and reply Assoc Resp Frame */ + if (fgReplyAssocResp) { + UINT_16 u2IELength; + PUINT_8 pucIE; + + if ((((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->u2FrameCtrl & MASK_FRAME_TYPE) == + MAC_FRAME_REASSOC_REQ) { + + u2IELength = prSwRfb->u2PacketLen - + (UINT_16) OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } else { + u2IELength = prSwRfb->u2PacketLen - (UINT_16) OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]); + + pucIE = ((P_WLAN_ASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } + + rlmProcessAssocReq(prAdapter, prSwRfb, pucIE, u2IELength); + + /* 4 <4.1> Assign Association ID */ + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + if (p2pRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + /* prStaRec->eAuthAssocState = AA_STATE_IDLE; */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2;/* NOTE(Kevin): for TX done */ + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + } else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, the peer can try Association w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if ((IS_STA_IN_BOW(prStaRec))) { + /* if (bowRunEventAAAComplete(prAdapter, prStaRec) == WLAN_STATUS_SUCCESS) { */ + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + prStaRec->eAuthAssocState = AAA_STATE_SEND_ASSOC2; /* NOTE(Kevin): for TX done */ + + /* NOTE(Kevin): Method A: Change to STATE_3 before handle TX Done */ + /* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + } +#if 0 + else { + /* Client List FULL. */ + u2StatusCode = STATUS_CODE_REQ_DECLINED; + + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, the peer can try Association w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + } +#endif +#endif + } else { + prStaRec->u2AssocId = 0; /* Invalid Association ID */ + + /* If (Re)association fail, the peer can try Association w/o Auth immediately */ + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = u2StatusCode; + + /* NOTE: Ignore the return status for AAA */ + /* 4 <4.2> Reply Assoc Resp */ + assocSendReAssocRespFrame(prAdapter, prStaRec); + +} + +return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventRxAssoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth2/AssocReq) Event of AAA FSM. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aaaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(AAA, LOUD, "EVENT-TX DONE: Current Time = %lu\n", (unsigned long)kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) { + DBGLOG(AAA, INFO, "EVENT-TX DONE: Invalid StaRec"); + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + } + + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + DBGLOG(AAA, INFO, "TX DONE status: %d, AuthAssocState: %d, SeqNo: %d\n", + rTxDoneStatus, prStaRec->eAuthAssocState, + prMsduInfo->ucTxSeqNum); + + switch (prStaRec->eAuthAssocState) { + case AAA_STATE_SEND_AUTH2: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_2) != WLAN_STATUS_SUCCESS) + break; + + if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { + if (TX_RESULT_SUCCESS == rTxDoneStatus) { + + /* NOTE(Kevin): Change to STATE_2 at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + } else { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_1 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + p2pRunEventAAATxFail(prAdapter, prStaRec); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) + bowRunEventAAATxFail(prAdapter, prStaRec); +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + } + + } + /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ + + } + break; + + case AAA_STATE_SEND_ASSOC2: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocRespFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) + break; + + if (STATUS_CODE_SUCCESSFUL == prStaRec->u2StatusCode) { + if (TX_RESULT_SUCCESS == rTxDoneStatus) { + + prStaRec->eAuthAssocState = AA_STATE_IDLE; + + /* NOTE(Kevin): Change to STATE_3 at TX Done */ +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + p2pRunEventAAASuccess(prAdapter, prStaRec); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + + if (IS_STA_IN_BOW(prStaRec)) + bowRunEventAAAComplete(prAdapter, prStaRec); +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + } else { + + prStaRec->eAuthAssocState = AAA_STATE_SEND_AUTH2; + + /* NOTE(Kevin): Change to STATE_2 */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + p2pRunEventAAATxFail(prAdapter, prStaRec); +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_STA_IN_BOW(prStaRec)) + bowRunEventAAATxFail(prAdapter, prStaRec); +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + + } + } + /* NOTE(Kevin): Ignore the TX Done Event of Auth Frame with Error Status Code */ + } + break; + + default: + break; /* Ignore other cases */ + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aaaFsmRunEventTxDone() */ +#endif /* CFG_SUPPORT_AAA */ + +#if 0 /* TODO(Kevin): for abort event, just reset the STA_RECORD_T. */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send ABORT Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventAbort(IN P_MSG_HDR_T prMsgHdr) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventAbort"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: ABORT\n"); + + /* NOTE(Kevin): when reach here, the ARB_STATE should be in ARB_STATE_JOIN. */ + ASSERT(prJoinInfo->prBssDesc); + + /* 4 <1> Update Flags and Elements of JOIN Module. */ + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel all JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rJoinTimer); + + /* 4 <2> Update the associated STA_RECORD_T during JOIN. */ + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + if (prStaRec) + prStaRec->ucStaState = STA_STATE_1; /* Update Station Record - Class 1 Flag */ +#if DBG + else + ASSERT(0); /* Shouldn't happened, because we already add this STA_RECORD_T at JOIN_STATE_INIT */ +#endif /* DBG */ + + /* 4 <3> Pull back to IDLE. */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + /* 4 <4> If we are in Roaming, recover the settings of previous BSS. */ + /* NOTE: JOIN FAIL - + * Restore original setting from current BSS_INFO_T. + */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + +} /* end of joinFsmRunEventAbort() */ +#endif + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); + +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; +#if DBG + else + ASSERT(0); +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); + + /* 4 <2.D> SSID */ + COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + /* 4 <2.E> Channel / Band information. */ + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + /* 4 <2.F> RSN/WPA information. */ + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + else + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + + /* 4 <2.G> Beacon interval. */ + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + /* 4 <2.H> DTIM period. */ + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + /* 4 <2.I> ERP Information */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + /* 4 <2.J> Country inforamtion of the associated AP */ + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, + * use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, + * and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); + +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c new file mode 100644 index 0000000000000..7b5a49a5ba631 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/ais_fsm.c @@ -0,0 +1,5039 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/ais_fsm.c#1 +*/ + +/*! \file "aa_fsm.c" + \brief This file defines the FSM for SAA and AAA MODULE. + + This file defines the FSM for SAA and AAA MODULE. +*/ + +/* +** Log: ais_fsm.c +** +** 09 06 2013 cp.wu +** always paste SSID information to SAA-FSM +** +** 09 06 2013 cp.wu +** add error handling when reassociation request failed to locate bss descriptor +** +** 09 05 2013 cp.wu +** isolate logic regarding roaming & reassociation +** +** 09 04 2013 cp.wu +** fix typo +** +** 09 03 2013 cp.wu +** add path for reassociation + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration with + * corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred band configuration + * corresponding to network type. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous + * to asynchronous approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state + * without join timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED + * cases as an explicit trigger for Android framework + * correct reference to BSSID field in Association-Response frame. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT for REASSOCIATED + * cases as an explicit trigger for Android framework + * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. + * 2. (Android only) when reassociation-and-non-roaming cases happened, indicate an extra DISCONNECT + * indication to Android Wi-Fi framework + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 10 26 2011 tsaiyuan.hsu + * [WCXRP00001064] [MT6620 Wi-Fi][DRV]] add code with roaming awareness when disconnecting AIS network + * be aware roaming when disconnecting AIS network. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * STA_REC shall be NULL for Beacon's MSDU + * + * 10 13 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Reduce join failure count limit to 2 for faster re-join for other BSS + * 1. short join failure count limit to 2 + * 2. treat join timeout as kind of join failure as well + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 20 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * change window registry of driver for roaming. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Handle client mode about preamble type and slot time + * + * 09 08 2011 tsaiyuan.hsu + * [WCXRP00000972] [MT6620 Wi-Fi][DRV]] check if roaming occurs after join failure to avoid state incosistence. + * check if roaming occurs after join failure to avoid deactivation of network. + * + * 08 24 2011 chinghwa.yu + * [WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Update RDD test mode cases. + * + * 08 16 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * EnableRoaming in registry is deprecated. + * + * 08 16 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * use registry to enable or disable roaming. + * + * 07 07 2011 cp.wu + * [WCXRP00000840] [MT6620 Wi-Fi][Driver][AIS] Stop timer for joining when channel is released + * due to join failure count exceeding limit + * stop timer when joining operation is failed due to try count exceeds limitation + * + * 06 28 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work + * around some tricky AP which use space character as hidden SSID + * do not handle SCAN request immediately after connected to increase the probability of receiving 1st beacon frame. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * ensure DEAUTH is always sent before establish a new connection + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * typo fix: a right brace is missed. + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * When RECONNECT request is identified as disconnected, it is necessary to check for pending scan request. + * + * 06 16 2011 cp.wu + * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels + * mark fgIsTransition as TRUE for state rolling. + * + * 06 16 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * always check for pending scan after switched into NORMAL_TR state. + * + * 06 14 2011 cp.wu + * [WCXRP00000782] [MT6620 Wi-Fi][AIS] Treat connection at higher priority over scanning to avoid WZC connection timeout + * always treat connection request at higher priority over scanning request + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 05 18 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state + * when DEAUTH frame is dropped due to bss disconnection + * change SCAN handling behavior when followed by a CONNECT/DISCONNECT requests by pending instead of dropping. + * + * 05 17 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state + * when DEAUTH frame is dropped due to bss disconnection + * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 13 2011 george.huang + * [WCXRP00000628] [MT6620 Wi-Fi][FW][Driver] Modify U-APSD setting to default OFF + * remove assert + * + * 03 18 2011 cp.wu + * [WCXRP00000575] [MT6620 Wi-Fi][Driver][AIS] reduce memory usage when generating mailbox message for scan request + * when there is no IE needed for probe request, then request a smaller memory for mailbox message + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 03 11 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel + * + * 03 09 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * avoid clearing fgIsScanReqIssued so as to add scan results. + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 04 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * reset retry conter of attemp to connect to ap after completion of join. + * + * 03 04 2011 cp.wu + * [WCXRP00000515] [MT6620 Wi-Fi][Driver] Surpress compiler warning which is identified by GNU compiler collection + * surpress compile warning occurred when compiled by GNU compiler collection. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right + * after connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 02 23 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach to + * improve response time for scanning request + * when handling reconnect request, set fgTryScan as TRUE + * + * 02 22 2011 cp.wu + * [WCXRP00000487] [MT6620 Wi-Fi][Driver][AIS] Serve scan and connect request with a queue-based approach + * to improve response time for scanning request + * handle SCAN and RECONNECT with a FIFO approach. + * + * 02 09 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * Check if prRegInfo is null or not before initializing roaming parameters. + * + * 02 01 2011 cp.wu + * [WCXRP00000416] [MT6620 Wi-Fi][Driver] treat "unable to find BSS" as connection trial + * to prevent infinite reconnection trials + * treat "unable to find BSS" as connection trial to prevent infinite reconnection trials. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 14 2011 cp.wu + * [WCXRP00000359] [MT6620 Wi-Fi][Driver] add an extra state to ensure DEAUTH frame is always sent + * Add an extra state to guarantee DEAUTH frame is sent then connect to new BSS. + * This change is due to WAPI AP needs DEAUTH frame as a necessary step in handshaking protocol. + * + * 01 11 2011 cp.wu + * [WCXRP00000307] [MT6620 Wi-Fi][SQA]WHQL test .2c_wlan_adhoc case fail. + * [IBSS] when merged in, the bss state should be updated to firmware to pass WHQL adhoc failed item + * + * 01 10 2011 cp.wu + * [WCXRP00000351] [MT6620 Wi-Fi][Driver] remove from scanning result in OID handling layer + * when the corresponding BSS is disconnected due to beacon timeout + * remove from scanning result when the BSS is disconnected due to beacon timeout. + * + * 01 03 2011 cp.wu + * [WCXRP00000337] [MT6620 Wi-FI][Driver] AIS-FSM not to invoke cnmStaRecResetStatus + * directly 'cause it frees all belonging STA-RECs + * do not invoke cnmStaRecResetStatus() directly, nicUpdateBss will do the things after bss is disconnected + * + * 12 30 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * do not need to manipulate prStaRec after indicating BSS disconnection to firmware, + * 'cause all STA-RECs belongs to BSS has been freed already + * + * 12 27 2010 cp.wu + * [WCXRP00000269] [MT6620 Wi-Fi][Driver][Firmware] Prepare for v1.1 branch release + * add DEBUGFUNC() macro invoking for more detailed debugging information + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 12 17 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 25 2010 yuche.tsai + * NULL + * Update SLT Function for QoS Support and not be affected by fixed rate function. + * + * 11 25 2010 cp.wu + * [WCXRP00000208] [MT6620 Wi-Fi][Driver] Add scanning with specified SSID to AIS FSM + * add scanning with specified SSID facility to AIS-FSM + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with + * Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] Add implementation for querying current TX rate + * from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] + * Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 14 2010 wh.su + * [WCXRP00000097] [MT6620 Wi-Fi] [Driver] Fixed the P2P not setting the fgIsChannelExt value make scan not abort + * initial the fgIsChannelExt value. + * + * 10 08 2010 cp.wu + * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. + * correct erroneous logic: specifying eBand with incompatible eSco + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T + * and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 23 2010 cp.wu + * [WCXRP00000049] [MT6620 Wi-Fi][Driver] Adhoc cannot be created successfully. + * keep IBSS-ALONE state retrying until further instruction is received + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD + * when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 09 2010 yuche.tsai + * NULL + * Fix NULL IE Beacon issue. Sync Beacon Content to FW before enable beacon. + * Both in IBSS Create & IBSS Merge + * + * 09 09 2010 cp.wu + * NULL + * frequency is in unit of KHz thus no need to divide 1000 once more. + * + * 09 06 2010 cp.wu + * NULL + * 1) initialize for correct parameter even for disassociation. + * 2) AIS-FSM should have a limit on trials to build connection + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 25 2010 cp.wu + * NULL + * add option for enabling AIS 5GHz scan + * + * 08 25 2010 cp.wu + * NULL + * [AIS-FSM] IBSS no longer needs to acquire channel for beaconing, + * RLM/CNM will handle the channel switching when BSS information is updated + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 12 2010 cp.wu + * NULL + * check-in missed files. + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 09 2010 cp.wu + * NULL + * reset fgIsScanReqIssued when abort request is received right after join completion. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 cp.wu + * NULL + * comment out deprecated members in BSS_INFO, which are only used by firmware rather than driver. + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 29 2010 cp.wu + * NULL + * eliminate u4FreqInKHz usage, combined into rConnections.ucAdHoc* + * + * 07 29 2010 cp.wu + * NULL + * allocate on MGMT packet for IBSS beaconing. + * + * 07 29 2010 cp.wu + * NULL + * [AIS-FSM] fix: when join failed, release channel privilege as well + * + * 07 28 2010 cp.wu + * NULL + * reuse join-abort sub-procedure to reduce code size. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 26 2010 cp.wu + * + * AIS-FSM: when scan request is coming in the 1st 5 seconds of channel privilege period, + * just pend it til 5-sec. period finishes + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 26 2010 cp.wu + * + * re-commit code logic being overwriten. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 cp.wu + * + * 1) enable Ad-Hoc + * 2) disable beacon timeout handling temporally due to unexpected beacon timeout event. + * + * 07 23 2010 cp.wu + * + * indicate scan done for linux wireless extension + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 21 2010 cp.wu + * + * separate AIS-FSM states into different cases of channel request. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 20 2010 cp.wu + * + * 1) [AIS] when new scan is issued, clear currently available scanning result except the connected one + * 2) refine disconnection behaviour when issued during BG-SCAN process + * + * 07 20 2010 cp.wu + * + * 1) bugfix: do not stop timer for join after switched into normal_tr state, + * for providing chance for DHCP handshasking + * 2) modify rsnPerformPolicySelection() invoking + * + * 07 19 2010 cp.wu + * + * 1) init AIS_BSS_INFO as channel number = 1 with band = 2.4GHz + * 2) correct typo + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * for AIS scanning, driver specifies no extra IE for probe request + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 yarco.yang + * + * Remove CFG_MQM_MIGRATION + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Refine AIS-FSM by divided into more states + * + * 07 13 2010 cm.chang + * + * Rename MSG_CH_RELEASE_T to MSG_CH_ABORT_T + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, + * other request will be directly dropped by returning BUSY + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * for first connection, if connecting failed do not enter into scan state. + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * once STA-REC is allocated and updated, invoke cnmStaRecChangeState() to sync. with firmware. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * remove unused definitions. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * RSN/PRIVACY compilation flag awareness correction + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change to enqueue TX frame infinitely. + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 01 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add conditionial compiling flag to choose default available bandwidth + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile error if CFG_CMD_EVENT_VER_009 == 0 for prEventConnStatus->ucNetworkType. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 17 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Call pmAbort() and add ucNetworkType field in EVENT_CONNECTION_STATUS + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile warning - define of MQM_WMM_PARSING was removed + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed the use of compiling flag MQM_WMM_PARSING + * + * 04 27 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * + * Fix typo + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the protected bit at cap info for ad-hoc. + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add new HW CH macro support + * + * 04 07 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Add TX Power Control RCPI function. + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * move the wlan table alloc / free to change state function. + * + * 03 25 2010 wh.su + * [BORA00000676][MT6620] Support the frequency setting and query at build connection / connection event + * modify the build connection and status event structure bu CMD_EVENT doc 0.09 draft, default is disable. + * + * 03 24 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * fixed some WHQL testing error. + * + * 03 24 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Set / Unset POWER STATE in AIS Network + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 03 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add PHY_CONFIG to change Phy Type + * + * 03 03 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Use bcmWiFiNotify to replace wifi_send_msg to pass information to BCM module. + * + * 03 03 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Remove wmt_task definition and add PTA function. + * + * 03 02 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Init TXM and MQM testing procedures in aisFsmRunEventJoinComplete() + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Modified aisUpdateBssInfo() to call TXM's functions for setting WTBL TX parameters + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * clear the pmkid cache while indicate media disconnect. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * . + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Enabled MQM parsing WMM IEs for non-AP mode + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Remove CFG_TEST_VIRTUAL_CMD and add support of Driver STA_RECORD_T activation + * + * 02 25 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * use the Rx0 dor event indicate. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Support dynamic channel selection + * + * 02 23 2010 wh.su + * [BORA00000621][MT6620 Wi-Fi] Add the RSSI indicate to avoid XP stalled for query rssi value + * Adding the RSSI event support, + * using the HAL function to get the rcpi value and tranlsate to RSSI and indicate to driver + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Set max AMDPU size supported by the peer to 64 KB, + * removed mqmInit() and mqmTxSendAddBaReq() function calls in aisUpdateBssInfo() + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 20 2010 kevin.huang + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags + * + * 01 15 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Configured the AMPDU factor to 3 for the APu1rwduu`wvpghlqg|q`mpdkb+ilp + * + * 01 14 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Add WiFi BCM module for the 1st time. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Refine JOIN Complete and separate the function of Media State indication + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the sample code to update the wlan table rate, + * + * Dec 10 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Different function prototype of wifi_send_msg() + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call rlm related function to process HT info when join complete + * + * Dec 9 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * default the acquired wlan table entry code off + * + * Dec 9 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to acquired the wlan table entry, and a sample code to update the BA bit at table + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix the problem of prSwRfb overwrited by event packet in aisFsmRunEventJoinComplete() + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to integrate the security related code + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove redundant declaration + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add code for JOIN init and JOIN complete + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename u4RSSI to i4RSSI + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise ENUM_MEDIA_STATE to ENUM_PARAM_MEDIA_STATE + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add fgIsScanReqIssued to CONNECTION_SETTINGS_T + * + * Nov 26 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise Virtual CMD handler due to structure changed + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Virtual CMD & RESP for testing CMD PATH + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmInitializeConnectionSettings() + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add CFG_TEST_MGMT_FSM flag for aisFsmTest() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define AIS_ROAMING_CONNECTION_TRIAL_LIMIT 2 +#define AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME 80 + +#define CTIA_MAGIC_SSID "ctia_test_only_*#*#3646633#*#*" +#define CTIA_MAGIC_SSID_LEN 30 + +#define AIS_JOIN_TIMEOUT 7 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugAisState[AIS_STATE_NUM] = { + (PUINT_8) DISP_STRING("AIS_STATE_IDLE"), + (PUINT_8) DISP_STRING("AIS_STATE_SEARCH"), + (PUINT_8) DISP_STRING("AIS_STATE_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_ONLINE_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_LOOKING_FOR"), + (PUINT_8) DISP_STRING("AIS_STATE_WAIT_FOR_NEXT_SCAN"), + (PUINT_8) DISP_STRING("AIS_STATE_REQ_CHANNEL_JOIN"), + (PUINT_8) DISP_STRING("AIS_STATE_JOIN"), + (PUINT_8) DISP_STRING("AIS_STATE_IBSS_ALONE"), + (PUINT_8) DISP_STRING("AIS_STATE_IBSS_MERGE"), + (PUINT_8) DISP_STRING("AIS_STATE_NORMAL_TR"), + (PUINT_8) DISP_STRING("AIS_STATE_DISCONNECTING"), + (PUINT_8) DISP_STRING("AIS_STATE_REQ_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("AIS_STATE_REMAIN_ON_CHANNEL") +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value of the connection settings for +* AIS network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisInitializeConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucAnyBSSID[] = BC_BSSID; + UINT_8 aucZeroMacAddr[] = NULL_MAC_ADDR; + int i = 0; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Setup default values for operation */ + COPY_MAC_ADDR(prConnSettings->aucMacAddress, aucZeroMacAddr); + + if (prRegInfo) + prConnSettings->ucDelayTimeOfDisconnectEvent = + (!prAdapter->fgIsHw5GBandDisabled && prRegInfo->ucSupport5GBand) ? + AIS_DELAY_TIME_OF_DISC_SEC_DUALBAND : AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; + else + prConnSettings->ucDelayTimeOfDisconnectEvent = AIS_DELAY_TIME_OF_DISC_SEC_ONLY_2G4; + + COPY_MAC_ADDR(prConnSettings->aucBSSID, aucAnyBSSID); + prConnSettings->fgIsConnByBssidIssued = FALSE; + + prConnSettings->fgIsConnReqIssued = FALSE; + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + + prConnSettings->ucSSIDLen = 0; + + prConnSettings->eOPMode = NET_TYPE_INFRA; + + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + + if (prRegInfo) { + prConnSettings->ucAdHocChannelNum = (UINT_8) nicFreq2ChannelNum(prRegInfo->u4StartFreq); + prConnSettings->eAdHocBand = prRegInfo->u4StartFreq < 5000000 ? BAND_2G4 : BAND_5G; + prConnSettings->eAdHocMode = (ENUM_PARAM_AD_HOC_MODE_T) (prRegInfo->u4AdhocMode); + } + + prConnSettings->eAuthMode = AUTH_MODE_OPEN; + + prConnSettings->eEncStatus = ENUM_ENCRYPTION_DISABLED; + + prConnSettings->fgIsScanReqIssued = FALSE; + + /* MIB attributes */ + prConnSettings->u2BeaconPeriod = DOT11_BEACON_PERIOD_DEFAULT; + + prConnSettings->u2RTSThreshold = DOT11_RTS_THRESHOLD_DEFAULT; + + prConnSettings->u2DesiredNonHTRateSet = RATE_SET_ALL_ABG; + + /* prConnSettings->u4FreqInKHz; */ /* Center frequency */ + + /* Set U-APSD AC */ + prConnSettings->bmfgApsdEnAc = PM_UAPSD_NONE; + + secInit(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* Features */ + prConnSettings->fgIsEnableRoaming = FALSE; +#if CFG_SUPPORT_ROAMING + if (prRegInfo) + prConnSettings->fgIsEnableRoaming = ((prRegInfo->fgDisRoaming > 0) ? (FALSE) : (TRUE)); +#endif /* CFG_SUPPORT_ROAMING */ + + prConnSettings->fgIsAdHocQoSEnable = FALSE; + + prConnSettings->eDesiredPhyConfig = PHY_CONFIG_802_11ABGN; + + /* Set default bandwidth modes */ + prConnSettings->uc2G4BandwidthMode = CONFIG_BW_20M; + prConnSettings->uc5GBandwidthMode = CONFIG_BW_20_40M; + + prConnSettings->rRsnInfo.ucElemId = 0x30; + prConnSettings->rRsnInfo.u2Version = 0x0001; + prConnSettings->rRsnInfo.u4GroupKeyCipherSuite = 0; + prConnSettings->rRsnInfo.u4PairwiseKeyCipherSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prConnSettings->rRsnInfo.au4PairwiseKeyCipherSuite[i] = 0; + prConnSettings->rRsnInfo.u4AuthKeyMgtSuiteCount = 0; + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) + prConnSettings->rRsnInfo.au4AuthKeyMgtSuite[i] = 0; + prConnSettings->rRsnInfo.u2RsnCap = 0; + prConnSettings->rRsnInfo.fgRsnCapPresent = FALSE; + +} /* end of aisFsmInitializeConnectionSettings() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to initialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 ucScanTimeoutTimes = 0; +VOID aisFsmInit(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmInit()"); + DBGLOG(SW1, TRACE, "->aisFsmInit()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Initiate FSM */ + prAisFsmInfo->ePreviousState = AIS_STATE_IDLE; + prAisFsmInfo->eCurrentState = AIS_STATE_IDLE; + + prAisFsmInfo->ucAvailableAuthTypes = 0; + + prAisFsmInfo->prTargetBssDesc = (P_BSS_DESC_T) NULL; + + prAisFsmInfo->ucSeqNumOfReqMsg = 0; + prAisFsmInfo->ucSeqNumOfChReq = 0; + prAisFsmInfo->ucSeqNumOfScanReq = 0; + + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 4 <1.1> Initiate FSM - Timer INIT */ + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventBGSleepTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIbssAloneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventIbssAloneTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisPostponedEventOfDisconnTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventJoinTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rScanDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventScanDoneTimeOut, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rChannelTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventChannelTimeout, (ULONG) NULL); + + cnmTimerInitTimer(prAdapter, + &prAisFsmInfo->rDeauthDoneTimer, + (PFN_MGMT_TIMEOUT_FUNC) aisFsmRunEventDeauthTimeout, (ULONG) NULL); + + /* 4 <1.2> Initiate PWR STATE */ + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_AIS_INDEX); + COPY_MAC_ADDR(prAisBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Initiate BSS_INFO_T - private part */ + /* TODO */ + prAisBssInfo->eBand = BAND_2G4; + prAisBssInfo->ucPrimaryChannel = 1; + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prAisBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prAisBssInfo->prBeacon) { + prAisBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prAisBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + } else { + ASSERT(0); + } + +#if 0 + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + if (prAdapter->u4UapsdAcBmp == 0) { + prAdapter->u4UapsdAcBmp = CFG_INIT_UAPSD_AC_BMP; + /* ASSERT(prAdapter->u4UapsdAcBmp); */ + } + prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prAisBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; +#endif + + /* request list initialization */ + LINK_INITIALIZE(&prAisFsmInfo->rPendingReqList); + + /* DBGPRINTF("[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, */ + /* prAisBssInfo->rPmProfSetupInfo.ucUapsdSp); */ + + /*reset ucScanTimeoutTimes value*/ + ucScanTimeoutTimes = 0; + +} /* end of aisFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief the function is used to uninitialize the value in AIS_FSM_INFO_T for +* AIS FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + + DEBUGFUNC("aisFsmUninit()"); + DBGLOG(SW1, INFO, "->aisFsmUninit()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + /* 4 <1> Stop all timers */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); /* Add by Enlai */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + /* 4 <2> flush pending request */ + aisFsmFlushRequest(prAdapter); + + /* 4 <3> Reset driver-domain BSS-INFO */ + if (prAisBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prAisBssInfo->prBeacon); + prAisBssInfo->prBeacon = NULL; + } +#if CFG_SUPPORT_802_11W + rsnStopSaQuery(prAdapter); +#endif + +} /* end of aisFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialization of JOIN STATE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the BSS we will try to join with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_JOIN(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_JOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisSpecificBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + ASSERT(prBssDesc); + + /* 4 <1> We are going to connect to this BSS. */ + prBssDesc->fgIsConnecting = TRUE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_LEGACY_AP, NETWORK_TYPE_AIS_INDEX, prBssDesc); + if (prStaRec == NULL) { + DBGLOG(AIS, WARN, "Create station record fail\n"); + return; + } + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + if (prStaRec->ucStaState == STA_STATE_1) + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + /* 4 <3> Update ucAvailableAuthTypes which we can choice during SAA */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + prStaRec->fgIsReAssoc = FALSE; + + switch (prConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: /* Note: Omit break here. */ + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + break; + + case AUTH_MODE_SHARED: + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; + break; + + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(AIS, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); + prAisFsmInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | AUTH_TYPE_SHARED_KEY); + break; + + default: + ASSERT(!(prConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); + DBGLOG(AIS, ERROR, "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", + prConnSettings->eAuthMode); + /* TODO(Kevin): error handling ? */ + return; + } + + /* TODO(tyhsu): Assume that Roaming Auth Type is equal to ConnSettings eAuthMode */ + prAisSpecificBssInfo->ucRoamingAuthTypes = prAisFsmInfo->ucAvailableAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + + } else { + ASSERT(prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE); + ASSERT(!prBssDesc->fgIsConnected); + + DBGLOG(AIS, LOUD, "JOIN INIT: AUTH TYPE = %d for Roaming\n", + prAisSpecificBssInfo->ucRoamingAuthTypes); + + prStaRec->fgIsReAssoc = TRUE; /* We do roaming while the medium is connected */ + + /* TODO(Kevin): We may call a sub function to acquire the Roaming Auth Type */ + prAisFsmInfo->ucAvailableAuthTypes = prAisSpecificBssInfo->ucRoamingAuthTypes; + + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT_FOR_ROAMING; + } + + /* 4 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes */ + if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(AIS, LOUD, "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } else { + ASSERT(0); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + if (prBssDesc->ucSSIDLen) + COPY_SSID(prConnSettings->aucSSID, prConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + /* 4 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + if (1) { + int j; + P_FRAG_INFO_T prFragInfo; + + for (j = 0; j < MAX_NUM_CONCURRENT_FRAGMENTED_MSDUS; j++) { + prFragInfo = &prStaRec->rFragInfo[j]; + + if (prFragInfo->pr1stFrag) { + /* nicRxReturnRFB(prAdapter, prFragInfo->pr1stFrag); */ + prFragInfo->pr1stFrag = (P_SW_RFB_T) NULL; + } + } + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + +} /* end of aisFsmInit_JOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmStateInit_RetryJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_REQ_T prJoinReqMsg; + + DEBUGFUNC("aisFsmStateInit_RetryJOIN()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Retry other AuthType if possible */ + if (!prAisFsmInfo->ucAvailableAuthTypes) + return FALSE; + + if (prAisFsmInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(AIS, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); + + prAisFsmInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else { + DBGLOG(AIS, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + } + + prAisFsmInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + + ASSERT(0); /* Can't trigger SAA FSM */ + return FALSE; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + return TRUE; + +} /* end of aisFsmRetryJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_ALONE +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_IBSS_ALONE(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> Check if IBSS was created before ? */ + if (prAisBssInfo->fgIsBeaconActivated) { + + /* 4 <2> Start IBSS Alone Timer for periodic SCAN and then SEARCH */ +#if !CFG_SLT_SUPPORT + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); +#endif + } + + aisFsmCreateIBSS(prAdapter); + +} /* end of aisFsmStateInit_IBSS_ALONE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief State Initialization of AIS_STATE_IBSS_MERGE +* +* @param[in] prBssDesc The pointer of BSS_DESC_T which is the IBSS we will try to merge with. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateInit_IBSS_MERGE(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + ASSERT(prBssDesc); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> We will merge with to this BSS immediately. */ + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); + if (prStaRec == NULL) { + DBGLOG(AIS, WARN, "Create station record fail\n"); + return; + } + + prStaRec->fgIsMerging = TRUE; + + prAisFsmInfo->prTargetStaRec = prStaRec; + + /* 4 <2.1> sync. to firmware domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* 4 <3> IBSS-Merge */ + aisFsmMergeIBSS(prAdapter, prStaRec); + +} /* end of aisFsmStateInit_IBSS_MERGE() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_JOIN(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_JOIN_ABORT_T prJoinAbortMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* 1. Abort JOIN process */ + prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + + ASSERT(0); /* Can't abort SAA FSM */ + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_AIS_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prAisFsmInfo->prTargetStaRec; + + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); + + /* 2. Return channel privilege */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + +} /* end of aisFsmAbortJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of SCAN Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_SCAN(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* Abort JOIN process. */ + prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + + ASSERT(0); /* Can't abort SCN FSM */ + return; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prAisFsmInfo->ucSeqNumOfScanReq; + prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + prScanCancelMsg->fgIsChannelExt = FALSE; +#endif + + /* unbuffered message to guarantee scan is cancelled in sequence */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_UNBUF); + +} /* end of aisFsmAbortSCAN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_NORMAL_TR(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + DBGLOG(AIS, TRACE, "aisFsmStateAbort_NORMAL_TR\n"); + + /* TODO(Kevin): Do abort other MGMT func */ + + /* 1. Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* 2.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 2.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + +} /* end of aisFsmAbortNORMAL_TR() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of NORMAL_TR Abort +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort_IBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_DESC_T prBssDesc; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* reset BSS-DESC */ + if (prAisFsmInfo->prTargetStaRec) { + prBssDesc = scanSearchBssDescByTA(prAdapter, prAisFsmInfo->prTargetStaRec->aucMacAddr); + + if (prBssDesc) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + } + } + /* release channel privilege */ + aisFsmReleaseCh(prAdapter); + +} +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of AIS(Ad-hoc, Infra STA) +* +* @param[in] eNextState Enum value of next AIS STATE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmSteps(IN P_ADAPTER_T prAdapter, ENUM_AIS_STATE_T eNextState) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + P_MSG_CH_REQ_T prMsgChReq; + P_MSG_SCN_SCAN_REQ prScanReqMsg; + P_AIS_REQ_HDR_T prAisReq; + ENUM_BAND_T eBand; + UINT_8 ucChannel; + UINT_16 u2ScanIELen; + ENUM_AIS_STATE_T eOriPreState; + + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("aisFsmSteps()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + eOriPreState = prAisFsmInfo->ePreviousState; + + do { + + /* Do entering Next State */ + prAisFsmInfo->ePreviousState = prAisFsmInfo->eCurrentState; + +#if DBG + DBGLOG(AIS, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], apucDebugAisState[eNextState]); +#else + DBGLOG(AIS, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_AIS_IDX, prAisFsmInfo->eCurrentState, eNextState); +#endif + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prAisFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + + /* Do tasks of the State that we just entered */ + switch (prAisFsmInfo->eCurrentState) { + /* NOTE(Kevin): we don't have to rearrange the sequence of following + * switch case. Instead I would like to use a common lookup table of array + * of function pointer to speed up state search. + */ + case AIS_STATE_IDLE: + + prAisReq = aisFsmGetNextRequest(prAdapter); + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + + if (prAisReq == NULL || prAisReq->eReqType == AIS_REQUEST_RECONNECT) { + if (prConnSettings->fgIsConnReqIssued == TRUE && + prConnSettings->fgIsDisconnectedByNonRequest == FALSE) { + + prAisFsmInfo->fgTryScan = TRUE; + + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* reset trial count */ + prAisFsmInfo->ucConnTrialCount = 0; + + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else { + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* sync with firmware */ + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* check for other pending request */ + if (prAisReq && + (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE)) { + + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_SCAN; + + fgIsTransition = TRUE; + } + } + + if (prAisReq) { + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + } else if (prAisReq->eReqType == AIS_REQUEST_SCAN) { +#if CFG_SUPPORT_ROAMING + prAisFsmInfo->fgIsRoamingScanPending = FALSE; +#endif /* CFG_SUPPORT_ROAMING */ + wlanClearScanningResult(prAdapter); + + eNextState = AIS_STATE_SCAN; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_ROAMING_CONNECT + || prAisReq->eReqType == AIS_REQUEST_ROAMING_SEARCH) { + /* ignore */ + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } else if (prAisReq->eReqType == AIS_REQUEST_REMAIN_ON_CHANNEL) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + + /* free the message */ + cnmMemFree(prAdapter, prAisReq); + } + + prAisFsmInfo->u4SleepInterval = AIS_BG_SCAN_INTERVAL_MIN_SEC; + + break; + + case AIS_STATE_SEARCH: + /* 4 <1> Search for a matched candidate and save it to prTargetBssDesc. */ +#if CFG_SLT_SUPPORT + prBssDesc = prAdapter->rWifiVar.rSltInfo.prPseudoBssDesc; +#else + prBssDesc = scanSearchBssDescByPolicy(prAdapter, NETWORK_TYPE_AIS_INDEX); +#endif + /* every time BSS join failure count is integral multiples of SCN_BSS_JOIN_FAIL_THRESOLD, + we need to scan again to find if a new BSS is here in the ESS, + this can also avoid too frequency to retry the rejected AP */ + if (prAisFsmInfo->ePreviousState == AIS_STATE_LOOKING_FOR || + ((eOriPreState == AIS_STATE_ONLINE_SCAN || + eOriPreState == AIS_STATE_SCAN) && prAisFsmInfo->ePreviousState != eOriPreState)) { + /* if previous state is scan/online scan/looking for, don't try to scan again */ + } else if (prBssDesc && prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD && + ((prBssDesc->ucJoinFailureCount - SCN_BSS_JOIN_FAIL_THRESOLD) % + SCN_BSS_JOIN_FAIL_THRESOLD) == 0) + prBssDesc = NULL; + + /* we are under Roaming Condition. */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (prAisFsmInfo->ucConnTrialCount > AIS_ROAMING_CONNECTION_TRIAL_LIMIT) { +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_CONNLIMIT); +#endif /* CFG_SUPPORT_ROAMING */ + /* reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + /* abort connection trial */ + prConnSettings->fgIsConnReqIssued = FALSE; + + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + + break; + } + } + /* 4 <2> We are not under Roaming Condition. */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + + /* 4 <2.a> If we have the matched one */ + if (prBssDesc) { + + /* 4 Stored the Selected BSS security cipher. + For later asoc req compose IE */ + prAisBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prAisBssInfo->u4RsnSelectedPairwiseCipher = + prBssDesc->u4RsnSelectedPairwiseCipher; + prAisBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + /* 4 Do STATE transition and update current Operation Mode. */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + + /* increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + } +#if CFG_SUPPORT_ADHOC + else if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + eNextState = AIS_STATE_IBSS_MERGE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + /* 4 <2.b> If we don't have the matched one */ + else { + + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + break; + } + /* 4 We've do SCAN already, now wait in some STATE. */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* issue reconnect request, + * and retreat to idle state for scheduling */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } +#if CFG_SUPPORT_ADHOC + else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) + || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) + || (prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS)) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = NULL; + + eNextState = AIS_STATE_IBSS_ALONE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } + } + /* 4 <3> We are under Roaming Condition. */ + else { /* prAdapter->eConnectionState == MEDIA_STATE_CONNECTED. */ + + /* 4 <3.a> This BSS_DESC_T is our AP. */ + /* NOTE(Kevin 2008/05/16): Following cases will go back to NORMAL_TR. + * CASE I: During Roaming, APP(WZC/NDISTEST) change the connection + * settings. That make we can NOT match the original AP, so the + * prBssDesc is NULL. + * CASE II: The same reason as CASE I. Because APP change the + * eOPMode to other network type in connection setting + * (e.g. NET_TYPE_IBSS), so the BssDesc become the IBSS node. + * (For CASE I/II, before WZC/NDISTEST set the OID_SSID, it will change + * other parameters in connection setting first. So if we do roaming + * at the same time, it will hit these cases.) + * + * CASE III: Normal case, we can't find other candidate to roam + * out, so only the current AP will be matched. + * + * CASE IV: Timestamp of the current AP might be reset + */ + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION && + ((!prBssDesc) || /* CASE I */ + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) || /* CASE II */ + (prBssDesc->fgIsConnected) || /* CASE III */ + (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID))) /* CASE IV */) { +#if DBG + if ((prBssDesc) && (prBssDesc->fgIsConnected)) + ASSERT(EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); +#endif /* DBG */ + /* We already associated with it, go back to NORMAL_TR */ + /* TODO(Kevin): Roaming Fail */ +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* Retreat to NORMAL_TR state */ + eNextState = AIS_STATE_NORMAL_TR; + fgIsTransition = TRUE; + break; + } + + /* 4 <3.b> Try to roam out for JOIN this BSS_DESC_T. */ + if (prBssDesc == NULL) { + /* increase connection trial count for infrastructure connection */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) + prAisFsmInfo->ucConnTrialCount++; + /* 4 Try to SCAN */ + if (prAisFsmInfo->fgTryScan) { + eNextState = AIS_STATE_LOOKING_FOR; + + fgIsTransition = TRUE; + break; + } + + /* 4 We've do SCAN already, now wait in some STATE. */ + if (prConnSettings->eOPMode == NET_TYPE_INFRA) { + + /* issue reconnect request, and retreat to idle state + * for scheduling */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + fgIsTransition = TRUE; + } +#if CFG_SUPPORT_ADHOC + else if ((prConnSettings->eOPMode == NET_TYPE_IBSS) + || (prConnSettings->eOPMode == NET_TYPE_AUTO_SWITCH) + || (prConnSettings->eOPMode == + NET_TYPE_DEDICATED_IBSS)) { + + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + prAisFsmInfo->prTargetBssDesc = NULL; + + eNextState = AIS_STATE_IBSS_ALONE; + fgIsTransition = TRUE; + } +#endif /* CFG_SUPPORT_ADHOC */ + else { + ASSERT(0); + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + fgIsTransition = TRUE; + } + } else { +#if DBG + if (prAisBssInfo->ucReasonOfDisconnect != + DISCONNECT_REASON_CODE_REASSOCIATION) { + ASSERT(UNEQUAL_MAC_ADDR + (prBssDesc->aucBSSID, prAisBssInfo->aucBSSID)); + } +#endif /* DBG */ + + /* 4 Record the target BSS_DESC_T for next STATE. */ + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* tyhsu: increase connection trial count */ + prAisFsmInfo->ucConnTrialCount++; + + /* Transit to channel acquire */ + eNextState = AIS_STATE_REQ_CHANNEL_JOIN; + fgIsTransition = TRUE; + } + } + + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + + DBGLOG(AIS, LOUD, "SCAN: Idle Begin - Current Time = %u\n", kalGetTimeTick()); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rBGScanTimer, SEC_TO_MSEC(prAisFsmInfo->u4SleepInterval)); + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prAisFsmInfo->u4SleepInterval < AIS_BG_SCAN_INTERVAL_MAX_SEC) + prAisFsmInfo->u4SleepInterval <<= 1; + break; + + case AIS_STATE_SCAN: + case AIS_STATE_ONLINE_SCAN: + case AIS_STATE_LOOKING_FOR: + + if (!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) { + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + + /* IE length decision */ + if (prAisFsmInfo->u4ScanIELength > 0) { + u2ScanIELen = (UINT_16) prAisFsmInfo->u4ScanIELength; + } else { +#if CFG_SUPPORT_WPS2 + u2ScanIELen = prAdapter->prGlueInfo->u2WSCIELen; +#else + u2ScanIELen = 0; +#endif + } + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + OFFSET_OF(MSG_SCN_SCAN_REQ, + aucIE) + u2ScanIELen); + if (!prScanReqMsg) { + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prScanReqMsg->rMsgHdr.eMsgId = MID_AIS_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = ++prAisFsmInfo->ucSeqNumOfScanReq; + prScanReqMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; + +#if CFG_SUPPORT_RDD_TEST_MODE + prScanReqMsg->eScanType = SCAN_TYPE_PASSIVE_SCAN; +#else + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; +#endif + +#if CFG_SUPPORT_ROAMING_ENC + if (prAdapter->fgIsRoamingEncEnabled == TRUE) { + if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR && + prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + prScanReqMsg->u2ChannelDwellTime = AIS_ROAMING_SCAN_CHANNEL_DWELL_TIME; + } + } +#endif /* CFG_SUPPORT_ROAMING_ENC */ + + if (prAisFsmInfo->eCurrentState == AIS_STATE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + if (prAisFsmInfo->ucScanSSIDLen == 0) { + /* Scan for all available SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + } else { + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + COPY_SSID(prScanReqMsg->aucSSID, + prScanReqMsg->ucSSIDLength, + prAisFsmInfo->aucScanSSID, prAisFsmInfo->ucScanSSIDLen); + } + } else { + /* Scan for determined SSID */ + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + COPY_SSID(prScanReqMsg->aucSSID, + prScanReqMsg->ucSSIDLength, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + } + + /* check if tethering is running and need to fix on specific channel */ + if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + prScanReqMsg->ucChannelListNum = 1; + prScanReqMsg->arChnlInfoList[0].eBand = eBand; + prScanReqMsg->arChnlInfoList[0].ucChannelNum = ucChannel; + } else { +#if 0 + aisFsmSetChannelInfo(prAdapter, prScanReqMsg, prAisFsmInfo->eCurrentState); +#endif + if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_NULL) { + if (prAdapter->fgEnable5GBand == TRUE) + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + else + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_2G4) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_5G) { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } else { + prScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + } + + if (prAisFsmInfo->u4ScanIELength > 0) { + kalMemCopy(prScanReqMsg->aucIE, prAisFsmInfo->aucScanIEBuf, + prAisFsmInfo->u4ScanIELength); + } else { +#if CFG_SUPPORT_WPS2 + if (prAdapter->prGlueInfo->u2WSCIELen > 0) { + kalMemCopy(prScanReqMsg->aucIE, &prAdapter->prGlueInfo->aucWSCIE, + prAdapter->prGlueInfo->u2WSCIELen); + } + } +#endif + + prScanReqMsg->u2IELen = u2ScanIELen; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + DBGLOG(AIS, TRACE, "SendSR%d\n", prScanReqMsg->ucSeqNum); + prAisFsmInfo->fgTryScan = FALSE; /* Will enable background sleep for infrastructure */ + + prAdapter->ucScanTime++; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + + if (prAisFsmInfo->prTargetBssDesc != NULL) { + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->prTargetBssDesc->eSco; + prMsgChReq->eRfBand = prAisFsmInfo->prTargetBssDesc->eBand; + COPY_MAC_ADDR(prMsgChReq->aucBSSID, prAisFsmInfo->prTargetBssDesc->aucBSSID); + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + break; + + case AIS_STATE_JOIN: + aisFsmStateInit_JOIN(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + aisFsmStateInit_IBSS_ALONE(prAdapter); + break; + + case AIS_STATE_IBSS_MERGE: + aisFsmStateInit_IBSS_MERGE(prAdapter, prAisFsmInfo->prTargetBssDesc); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_NORMAL_TR: + if (prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* Don't do anything when rJoinTimeoutTimer is still ticking */ + } else { + /* 1. Process for pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + fgIsTransition = TRUE; + } + /* 2. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE) == TRUE) { + eNextState = AIS_STATE_LOOKING_FOR; + fgIsTransition = TRUE; + } + /* 3. Process for pending roaming scan */ + else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE) == TRUE) { + eNextState = AIS_STATE_SEARCH; + fgIsTransition = TRUE; + } else if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE) == + TRUE) { + eNextState = AIS_STATE_REQ_REMAIN_ON_CHANNEL; + fgIsTransition = TRUE; + } + } + + break; + + case AIS_STATE_DISCONNECTING: + /* send for deauth frame for disconnection */ + authSendDeauthFrame(prAdapter, + prAisBssInfo->prStaRecOfAP, + (P_SW_RFB_T) NULL, REASON_CODE_DEAUTH_LEAVING_BSS, aisDeauthXmitComplete); + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer, 100); + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + return; + } + + /* zero-ize */ + kalMemZero(prMsgChReq, sizeof(MSG_CH_REQ_T)); + + /* filling */ + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChReq->ucTokenID = ++prAisFsmInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + prMsgChReq->u4MaxInterval = prAisFsmInfo->rChReqInfo.u4DurationMs; + prMsgChReq->ucPrimaryChannel = prAisFsmInfo->rChReqInfo.ucChannelNum; + prMsgChReq->eRfSco = prAisFsmInfo->rChReqInfo.eSco; + prMsgChReq->eRfBand = prAisFsmInfo->rChReqInfo.eBand; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prAisFsmInfo->fgIsChannelRequested = TRUE; + + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + /* sync with firmware */ + nicActivateNetwork(prAdapter, NETWORK_TYPE_AIS_INDEX); + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + + } + } while (fgIsTransition); + + return; + +} /* end of aisFsmSteps() */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmSetChannelInfo(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ ScanReqMsg, IN ENUM_AIS_STATE_T CurrentState) +{ + /*get scan channel infro from prAdapter->prGlueInfo->prScanRequest*/ + struct cfg80211_scan_request *scan_req_t = NULL; + struct ieee80211_channel *channel_tmp = NULL; + int i = 0; + int j = 0; + UINT_8 channel_num = 0; + UINT_8 channel_counts = 0; + + if ((prAdapter == NULL) || (ScanReqMsg == NULL)) + return; + if ((CurrentState == AIS_STATE_SCAN) || (CurrentState == AIS_STATE_ONLINE_SCAN)) { + if (prAdapter->prGlueInfo->prScanRequest != NULL) { + scan_req_t = prAdapter->prGlueInfo->prScanRequest; + if ((scan_req_t != NULL) && (scan_req_t->n_channels != 0) && + (scan_req_t->channels != NULL)) { + channel_counts = scan_req_t->n_channels; + DBGLOG(AIS, TRACE, "channel_counts=%d\n", channel_counts); + + while (j < channel_counts) { + channel_tmp = scan_req_t->channels[j]; + if (channel_tmp == NULL) + break; + + DBGLOG(AIS, TRACE, "set channel band=%d\n", channel_tmp->band); + if (channel_tmp->band >= IEEE80211_BAND_60GHZ) { + j++; + continue; + } + if (i >= MAXIMUM_OPERATION_CHANNEL_LIST) + break; + if (channel_tmp->band == IEEE80211_BAND_2GHZ) + ScanReqMsg->arChnlInfoList[i].eBand = BAND_2G4; + else if (channel_tmp->band == IEEE80211_BAND_5GHZ) + ScanReqMsg->arChnlInfoList[i].eBand = BAND_5G; + + DBGLOG(AIS, TRACE, "set channel channel_rer =%d\n", + channel_tmp->center_freq); + + channel_num = (UINT_8)nicFreq2ChannelNum( + channel_tmp->center_freq * 1000); + + DBGLOG(AIS, TRACE, "set channel channel_num=%d\n", + channel_num); + ScanReqMsg->arChnlInfoList[i].ucChannelNum = channel_num; + + j++; + i++; + } + } + } + } + + DBGLOG(AIS, INFO, "set channel i=%d\n", i); + if (i > 0) { + ScanReqMsg->ucChannelListNum = i; + ScanReqMsg->eScanChannel = SCAN_CHANNEL_SPECIFIED; + + return; + } + + if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_NULL) { + if (prAdapter->fgEnable5GBand == TRUE) + ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + else + ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_2G4) { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + } else if (prAdapter->aePreferBand[NETWORK_TYPE_AIS_INDEX] + == BAND_5G) { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_5G; + } else { + ScanReqMsg->eScanChannel = SCAN_CHANNEL_FULL; + ASSERT(0); + } + + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID aisFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + UINT_8 ucSeqNumOfCompMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventScanDone()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + ucScanTimeoutTimes = 0; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + ASSERT(prScanDoneMsg->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX); + + ucSeqNumOfCompMsg = prScanDoneMsg->ucSeqNum; + cnmMemFree(prAdapter, prMsgHdr); + + eNextState = prAisFsmInfo->eCurrentState; + + if (ucSeqNumOfCompMsg != prAisFsmInfo->ucSeqNumOfScanReq) { + DBGLOG(AIS, WARN, "SEQ NO of AIS SCN DONE MSG is not matched %d %d.\n", + ucSeqNumOfCompMsg, prAisFsmInfo->ucSeqNumOfScanReq); + } else { + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = AIS_STATE_IDLE; +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + case AIS_STATE_ONLINE_SCAN: + prConnSettings->fgIsScanReqIssued = FALSE; + + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; + + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ +#if CFG_SUPPORT_AGPS_ASSIST + scanReportScanResultToAgps(prAdapter); +#endif + break; + + case AIS_STATE_LOOKING_FOR: + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + scanReportBss2Cfg80211(prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_SEARCH; +#endif /* CFG_SUPPORT_ROAMING */ + break; + + default: + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rScanDoneTimer); + break; + + } + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmRunEventScanDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + UINT_8 ucReasonOfDisconnect; + BOOLEAN fgDelayIndication; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventAbort()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Extract information of Abort Message and then free memory. */ + prAisAbortMsg = (P_MSG_AIS_ABORT_T) prMsgHdr; + ucReasonOfDisconnect = prAisAbortMsg->ucReasonOfDisconnect; + fgDelayIndication = prAisAbortMsg->fgDelayIndication; + + cnmMemFree(prAdapter, prMsgHdr); + +#if DBG + DBGLOG(AIS, STATE, "EVENT-ABORT: Current State %s %d\n", + apucDebugAisState[prAisFsmInfo->eCurrentState], ucReasonOfDisconnect); +#else + DBGLOG(AIS, STATE, "[%d] EVENT-ABORT: Current State [%d %d]\n", + DBG_AIS_IDX, prAisFsmInfo->eCurrentState, ucReasonOfDisconnect); +#endif + + GET_CURRENT_SYSTIME(&(prAisFsmInfo->rJoinReqTime)); + + /* 4 <2> clear previous pending connection request and insert new one */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DEAUTHENTICATED + || ucReasonOfDisconnect == DISCONNECT_REASON_CODE_DISASSOCIATED) { + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + } else { + prConnSettings->fgIsDisconnectedByNonRequest = FALSE; + } + /* to support user space triggered roaming */ + if (ucReasonOfDisconnect == DISCONNECT_REASON_CODE_ROAMING && + prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && + prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_ROAMING_CONNECT); + } + return; + } + + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + if (prAisFsmInfo->eCurrentState != AIS_STATE_DISCONNECTING) { + /* 4 <3> invoke abort handler */ + aisFsmStateAbort(prAdapter, ucReasonOfDisconnect, fgDelayIndication); + } + +} /* end of aisFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handles AIS-FSM abort event/command +* +* \param[in] prAdapter Pointer of ADAPTER_T +* ucReasonOfDisconnect Reason for disonnection +* fgDelayIndication Option to delay disconnection indication +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmStateAbort(IN P_ADAPTER_T prAdapter, UINT_8 ucReasonOfDisconnect, BOOLEAN fgDelayIndication) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + BOOLEAN fgIsCheckConnected; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + fgIsCheckConnected = FALSE; + + /* 4 <1> Save information of Abort Message and then free memory. */ + prAisBssInfo->ucReasonOfDisconnect = ucReasonOfDisconnect; + + /* 4 <2> Abort current job. */ + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IDLE: + case AIS_STATE_SEARCH: + break; + + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + /* Do cancel timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rBGScanTimer); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* queue for later handling */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + + break; + + case AIS_STATE_LOOKING_FOR: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_REQ_CHANNEL_JOIN: + /* Release channel to CNM */ + aisFsmReleaseCh(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_JOIN: + /* Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* in case roaming is triggered */ + fgIsCheckConnected = TRUE; + break; + +#if CFG_SUPPORT_ADHOC + case AIS_STATE_IBSS_ALONE: + case AIS_STATE_IBSS_MERGE: + aisFsmStateAbort_IBSS(prAdapter); + break; +#endif /* CFG_SUPPORT_ADHOC */ + + case AIS_STATE_ONLINE_SCAN: + /* Do abort SCAN */ + aisFsmStateAbort_SCAN(prAdapter); + + /* queue for later handling */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, FALSE) == FALSE) + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_NORMAL_TR: + fgIsCheckConnected = TRUE; + break; + + case AIS_STATE_DISCONNECTING: + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + break; + + case AIS_STATE_REQ_REMAIN_ON_CHANNEL: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + case AIS_STATE_REMAIN_ON_CHANNEL: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + break; + + default: + break; + } + + if (fgIsCheckConnected && (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState)) { + + /* switch into DISCONNECTING state for sending DEAUTH if necessary */ + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_NEW_CONNECTION && + prAisBssInfo->prStaRecOfAP && prAisBssInfo->prStaRecOfAP->fgIsInUse) { + aisFsmSteps(prAdapter, AIS_STATE_DISCONNECTING); + + return; + } + /* Do abort NORMAL_TR */ + aisFsmStateAbort_NORMAL_TR(prAdapter); + + } + + aisFsmDisconnect(prAdapter, fgDelayIndication); + + +} /* end of aisFsmStateAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Join Complete Event from SAA FSM for AIS FSM +* +* @param[in] prMsgHdr Message of Join Complete of SAA FSM. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_JOIN_COMP_T prJoinCompMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prAssocRspSwRfb; + P_BSS_INFO_T prAisBssInfo; + UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; + OS_SYSTIME rCurrentTime; + + DEBUGFUNC("aisFsmRunEventJoinComplete()"); + + ASSERT(prMsgHdr); + + GET_CURRENT_SYSTIME(&rCurrentTime); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prStaRec = prJoinCompMsg->prStaRec; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + + eNextState = prAisFsmInfo->eCurrentState; + + DBGLOG(AIS, TRACE, "AISOK\n"); + + /* Check State and SEQ NUM */ + do { + if (prAisFsmInfo->eCurrentState != AIS_STATE_JOIN) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prAisFsmInfo->ucSeqNumOfReqMsg) { + + /* 4 <1> JOIN was successful */ + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + + /* 1. Reset retry count */ + prAisFsmInfo->ucConnTrialCount = 0; + + /* Completion of roaming */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + +#if CFG_SUPPORT_ROAMING + /* 2. Deactivate previous BSS */ + aisFsmRoamingDisconnectPrevAP(prAdapter, prStaRec); + + /* 3. Update bss based on roaming staRec */ + aisUpdateBssInfoForRoamingAP(prAdapter, prStaRec, prAssocRspSwRfb); +#endif /* CFG_SUPPORT_ROAMING */ + } else { + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if ((prAisBssInfo->prStaRecOfAP) && + (prAisBssInfo->prStaRecOfAP != prStaRec) && + (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { + + cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, + STA_STATE_1); + } + /* 4 <1.3> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, NETWORK_TYPE_AIS_INDEX, + (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. */ + /* from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, + FALSE); + + /* add for ctia mode */ + if (EQUAL_SSID + (aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen)) { + nicEnterCtiaMode(prAdapter, TRUE, FALSE); + } + } + +#if CFG_SUPPORT_ROAMING + /* if bssid is given, it means we no need fw roaming */ + if (prAdapter->rWifiVar.rConnSettings.eConnectionPolicy != CONNECT_BY_BSSID) + roamingFsmRunEventStart(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <1.7> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + } + /* 4 <2> JOIN was not successful */ + else { + /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ + if (aisFsmStateInit_RetryJOIN(prAdapter, prStaRec) == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* 1. Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* 2. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 3.1 stop join timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rJoinTimeoutTimer); + + /* 3.2 reset local variable */ + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + prBssDesc = scanSearchBssDescByBssid(prAdapter, prStaRec->aucMacAddr); + + if (prBssDesc == NULL) { + /* it maybe NULL when wlanRemove */ + /* + (1) UI does wifi off during SAA does auth/assoc procedure. + (2) We will do LINK_INITIALIZE(&prScanInfo->rBSSDescList); + in nicUninitMGMT(). + (3) We will handle prMsduInfo->pfTxDoneHandler + in nicTxRelease(). + (4) prMsduInfo->pfTxDoneHandler will point to + saaFsmRunEventTxDone(). + (5) Then jump to saaFsmSteps() -> saaFsmSendEventJoinComplete() + (6) Finally mboxSendMsg() -> aisFsmRunEventJoinComplete(). + (7) In aisFsmRunEventJoinComplete(), we will check + "prBssDesc = scanSearchBssDescByBssid(prAdapter, + prStaRec->aucMacAddr);" + (8) And prBssDesc will be NULL and hangs in + "ASSERT(prBssDesc->fgIsConnecting);" when DBG=0. + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + */ + break; + } + /* ASSERT(prBssDesc); */ + /* ASSERT(prBssDesc->fgIsConnecting); */ + prBssDesc->ucJoinFailureCount++; + if (prBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { + GET_CURRENT_SYSTIME(&prBssDesc->rJoinFailTime); + DBGLOG(AIS, INFO, + "Bss %pM join fail %d times,temp disable it at time:%u\n", + prBssDesc->aucBSSID, + SCN_BSS_JOIN_FAIL_THRESOLD, prBssDesc->rJoinFailTime); + } + + if (prBssDesc) + prBssDesc->fgIsConnecting = FALSE; + + /* 3.3 Free STA-REC */ + if (prStaRec != prAisBssInfo->prStaRecOfAP) + cnmStaRecFree(prAdapter, prStaRec, FALSE); + + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { +#if CFG_SUPPORT_ROAMING + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; +#endif /* CFG_SUPPORT_ROAMING */ + } else if (CHECK_FOR_TIMEOUT(rCurrentTime, prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* abort connection trial */ + prAdapter->rWifiVar.rConnSettings.fgIsConnReqIssued = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_CONNECT_INDICATION, NULL, 0); + + eNextState = AIS_STATE_IDLE; + } else { + /* 4.b send reconnect request */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + + eNextState = AIS_STATE_IDLE; + } + } + } + } +#if DBG + else + DBGLOG(AIS, WARN, "SEQ NO of AIS JOIN COMP MSG is not matched.\n"); +#endif /* DBG */ + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + } while (FALSE); + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of aisFsmRunEventJoinComplete() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Create which was sent by +* CNM to indicate that channel was changed for creating IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + do { + /* Check State */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_IBSS_ALONE) + aisUpdateBssInfoForCreateIBSS(prAdapter); + } while (FALSE); + +} /* end of aisFsmCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Grant Msg of IBSS Merge which was sent by +* CNM to indicate that channel was changed for merging IBSS. +* +* @param[in] prAdapter Pointer of ADAPTER_T +* @param[in] prStaRec Pointer of STA_RECORD_T for merge +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + do { + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_MERGE: + { + P_BSS_DESC_T prBssDesc; + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous Peers' STA_RECORD_T in Driver if have. */ + bssClearClientList(prAdapter, prAisBssInfo); + + /* 4 <1.3> Unmark connection flag of previous BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = FALSE; + } + /* 4 <1.4> Update BSS_INFO_T */ + aisUpdateBssInfoForMergeIBSS(prAdapter, prStaRec); + + /* 4 <1.5> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + + /* 4 <1.6> Activate current Peer's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.7> Enable other features */ + + /* 4 <1.8> Indicate Connected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + +#if CFG_SLT_SUPPORT + prAdapter->rWifiVar.rSltInfo.prPseudoStaRec = prStaRec; +#endif + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + + } while (FALSE); + +} /* end of aisFsmMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Notification of existing IBSS was found +* from SCN. +* +* @param[in] prMsgHdr Message of Notification of an IBSS was present. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventFoundIBSSPeer(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + BOOLEAN fgIsMergeIn; + + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) prMsgHdr; + + ASSERT(prAisIbssPeerFoundMsg->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX); + + prStaRec = prAisIbssPeerFoundMsg->prStaRec; + ASSERT(prStaRec); + + fgIsMergeIn = prAisIbssPeerFoundMsg->fgIsMergeIn; + + cnmMemFree(prAdapter, prMsgHdr); + + eNextState = prAisFsmInfo->eCurrentState; + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + { + /* 4 <1> An IBSS Peer 'merged in'. */ + if (fgIsMergeIn) { + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <1.3> Mark connection flag of BSS_DESC_T. */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc != NULL) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + } else { + ASSERT(0); /* Should be able to find a BSS_DESC_T here. */ + } + + /* 4 <1.4> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ + +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + /* 4 <1.6> sync. to firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <1.7> Indicate Connected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + + /* 4 <1.8> indicate PM for connected */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <1.9> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_NORMAL_TR; + + /* 4 <1.10> Release channel privilege */ + aisFsmReleaseCh(prAdapter); + } + /* 4 <2> We need 'merge out' to this IBSS */ + else { + + /* 4 <2.1> Get corresponding BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <2.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + } + } + break; + + case AIS_STATE_NORMAL_TR: + { + + /* 4 <3> An IBSS Peer 'merged in'. */ + if (fgIsMergeIn) { + + /* 4 <3.1> Add Peers' STA_RECORD_T to Client List */ + bssAddStaRecToClientList(prAdapter, prAisBssInfo, prStaRec); + +#if CFG_SLT_SUPPORT + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = TRUE; /* TODO(Kevin): TBD */ +#else + /* 4 <3.2> Activate current Peer's STA_RECORD_T in Driver. */ + prStaRec->fgIsQoS = FALSE; /* TODO(Kevin): TBD */ +#endif + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + prStaRec->fgIsMerging = FALSE; + + } + /* 4 <4> We need 'merge out' to this IBSS */ + else { + + /* 4 <4.1> Get corresponding BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + + prAisFsmInfo->prTargetBssDesc = prBssDesc; + + /* 4 <4.2> Set the Next State of AIS FSM */ + eNextState = AIS_STATE_IBSS_MERGE; + + } + } + break; + + default: + break; + } + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmRunEventFoundIBSSPeer() */ +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Media State to HOST +* +* @param[in] eConnectionState Current Media State +* @param[in] fgDelayIndication Set TRUE for postponing the Disconnect Indication. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +aisIndicationOfMediaStateToHost(IN P_ADAPTER_T prAdapter, + ENUM_PARAM_MEDIA_STATE_T eConnectionState, BOOLEAN fgDelayIndication) +{ + EVENT_CONNECTION_STATUS rEventConnStatus; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisIndicationOfMediaStateToHost()"); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* NOTE(Kevin): Move following line to aisChangeMediaState() macro per CM's request. */ + /* prAisBssInfo->eConnectionState = eConnectionState; */ + + /* For indicating the Disconnect Event only if current media state is + * disconnected and we didn't do indication yet. + */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + if (prAisBssInfo->eConnectionStateIndicated == eConnectionState) + return; + } + + if (!fgDelayIndication) { + /* 4 <0> Cancel Delay Timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIndicationOfDisconnectTimer); + + /* 4 <1> Fill EVENT_CONNECTION_STATUS */ + rEventConnStatus.ucMediaStatus = (UINT_8) eConnectionState; + + if (eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + rEventConnStatus.ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_INFRA; + rEventConnStatus.u2AID = prAisBssInfo->u2AssocId; + rEventConnStatus.u2ATIMWindow = 0; + } else if (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + rEventConnStatus.ucInfraMode = (UINT_8) NET_TYPE_IBSS; + rEventConnStatus.u2AID = 0; + rEventConnStatus.u2ATIMWindow = prAisBssInfo->u2ATIMWindow; + } else { + ASSERT(0); + } + + COPY_SSID(rEventConnStatus.aucSsid, + rEventConnStatus.ucSsidLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + COPY_MAC_ADDR(rEventConnStatus.aucBssid, prAisBssInfo->aucBSSID); + + rEventConnStatus.u2BeaconPeriod = prAisBssInfo->u2BeaconInterval; + rEventConnStatus.u4FreqInKHz = nicChannelNum2Freq(prAisBssInfo->ucPrimaryChannel); + + switch (prAisBssInfo->ucNonHTBasicPhyType) { + case PHY_TYPE_HR_DSSS_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + + case PHY_TYPE_ERP_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM24; + break; + + case PHY_TYPE_OFDM_INDEX: + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_OFDM5; + break; + + default: + ASSERT(0); + rEventConnStatus.ucNetworkType = (UINT_8) PARAM_NETWORK_TYPE_DS; + break; + } + } else { + /* Deactivate previous Peers' STA_RECORD_T in Driver if have. */ + bssClearClientList(prAdapter, prAisBssInfo); + +#if CFG_PRIVACY_MIGRATION + /* Clear the pmkid cache while media disconnect */ + secClearPmkid(prAdapter); +#endif + + rEventConnStatus.ucReasonOfDisconnect = prAisBssInfo->ucReasonOfDisconnect; + } + + /* 4 <2> Indication */ + nicMediaStateChange(prAdapter, NETWORK_TYPE_AIS_INDEX, &rEventConnStatus); + prAisBssInfo->eConnectionStateIndicated = eConnectionState; + } else { + /* NOTE: Only delay the Indication of Disconnect Event */ + ASSERT(eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED); + + DBGLOG(AIS, INFO, "Postpone the indication of Disconnect for %d seconds\n", + prConnSettings->ucDelayTimeOfDisconnectEvent); + + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rIndicationOfDisconnectTimer, + SEC_TO_MSEC(prConnSettings->ucDelayTimeOfDisconnectEvent)); + } + +} /* end of aisIndicationOfMediaStateToHost() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Media Disconnect" to HOST +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisPostponedEventOfDisconnTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if (prAisBssInfo->prStaRecOfAP) { + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + } + /* 4 <2> Remove pending connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BEACON_TIMEOUT; + /* 4 <3> Indicate Disconnected Event to Host immediately. */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, FALSE); + +} /* end of aisPostponedEventOfDisconnTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, P_SW_RFB_T prAssocRspSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_BSS_DESC_T prBssDesc; + UINT_16 u2IELength; + PUINT_8 pucIE; + + DEBUGFUNC("aisUpdateBssInfoForJOIN()"); + + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + DBGLOG(AIS, TRACE, "Update AIS_BSS_INFO_T and apply settings to MAC\n"); + + /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Setup Channel, Band */ + prAisBssInfo->ucPrimaryChannel = prAisFsmInfo->prTargetBssDesc->ucChannelNum; + prAisBssInfo->eBand = prAisFsmInfo->prTargetBssDesc->eBand; + + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = prStaRec; + prAisBssInfo->u2AssocId = prStaRec->u2AssocId; + + /* 4 <2.2> Setup Capability */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + else + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + +#if (CFG_SUPPORT_TDLS == 1) + /* init the TDLS flags */ + prAisBssInfo->fgTdlsIsProhibited = prStaRec->fgTdlsIsProhibited; + prAisBssInfo->fgTdlsIsChSwProhibited = prStaRec->fgTdlsIsChSwProhibited; +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + /* 4 <3.1> Setup BSSID */ + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + /* 4 <3.2> Parse WMM and setup QBSS flag */ + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prAisBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAssocRspFrame->aucBSSID); + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + prBssDesc->ucJoinFailureCount = 0; + + /* 4 <4.1> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + } else { + /* should never happen */ + ASSERT(0); + } + + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + + /* 4 <4.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ + +} /* end of aisUpdateBssInfoForJOIN() */ + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create an Ad-Hoc network and start sending Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForCreateIBSS(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prAisBssInfo->fgIsBeaconActivated) + return; + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prAisBssInfo->u2AssocId = 0; + + /* 4 <1.4> Setup Channel, Band and Phy Attributes */ + prAisBssInfo->ucPrimaryChannel = prConnSettings->ucAdHocChannelNum; + prAisBssInfo->eBand = prConnSettings->eAdHocBand; + + if (prAisBssInfo->eBand == BAND_2G4) { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prAisBssInfo->ucPhyTypeSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN; + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prAisBssInfo->ucConfigAdHocAPMode = AD_HOC_MODE_11A; + } + + /* 4 <1.5> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prConnSettings->u2BeaconPeriod; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = prConnSettings->u2AtimWindow; + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + +#if CFG_PRIVACY_MIGRATION + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION1_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION2_ENABLED || + prConnSettings->eEncStatus == ENUM_ENCRYPTION3_ENABLED) { + prAisBssInfo->fgIsProtection = TRUE; + } else { + prAisBssInfo->fgIsProtection = FALSE; + } +#else + prAisBssInfo->fgIsProtection = FALSE; +#endif + + /* 3 <2> Update BSS_INFO_T common part */ + ibssInitForAdHoc(prAdapter, prAisBssInfo); + + /* 3 <3> Set MAC HW */ + /* 4 <3.1> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <3.2> use command packets to inform firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <3.3> enable beaconing */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <3.4> Update AdHoc PM parameter */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 3 <4> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + + /* 3 <5> Start IBSS Alone Timer */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer, SEC_TO_MSEC(AIS_IBSS_ALONE_TIMEOUT_SEC)); + + return; + +} /* end of aisCreateIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the existing IBSS was found. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForMergeIBSS(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc; + /* UINT_16 u2IELength; */ + /* PUINT_8 pucIE; */ + + ASSERT(prStaRec); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rIbssAloneTimer); + + if (!prAisBssInfo->fgIsBeaconActivated) { + + /* 3 <1> Update BSS_INFO_T per Network Basis */ + /* 4 <1.1> Setup Operation Mode */ + prAisBssInfo->eCurrentOPMode = OP_MODE_IBSS; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + /* 4 <1.3> Clear current AP's STA_RECORD_T and current AID */ + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prAisBssInfo->u2AssocId = 0; + } + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Setup Capability */ + prAisBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use Peer's Cap Info as IBSS Cap Info */ + + if (prAisBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) { + prAisBssInfo->fgIsShortPreambleAllowed = TRUE; + prAisBssInfo->fgUseShortPreamble = TRUE; + } else { + prAisBssInfo->fgIsShortPreambleAllowed = FALSE; + prAisBssInfo->fgUseShortPreamble = FALSE; + } + + /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ + prAisBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + prAisBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + + if (prAisBssInfo->u2CapInfo & CAP_INFO_PRIVACY) + prAisBssInfo->fgIsProtection = TRUE; + else + prAisBssInfo->fgIsProtection = FALSE; + + /* 4 <2.2> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prAisBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prAisBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prAisBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prAisBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + rateGetDataRatesFromRateSet(prAisBssInfo->u2OperationalRateSet, + prAisBssInfo->u2BSSBasicRateSet, + prAisBssInfo->aucAllSupportedRates, &prAisBssInfo->ucAllSupportedRatesLen); + + /* 3 <3> X Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + prBssDesc = scanSearchBssDescByTA(prAdapter, prStaRec->aucMacAddr); + if (prBssDesc) { + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <4.1> Setup BSSID */ + COPY_MAC_ADDR(prAisBssInfo->aucBSSID, prBssDesc->aucBSSID); + + /* 4 <4.2> Setup Channel, Band */ + prAisBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + prAisBssInfo->eBand = prBssDesc->eBand; + + /* 4 <4.3> Setup MIB for current BSS */ + prAisBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + prAisBssInfo->ucDTIMPeriod = 0; + prAisBssInfo->u2ATIMWindow = 0; /* TBD(Kevin) */ + + prAisBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_ADHOC; + } else { + /* should never happen */ + ASSERT(0); + } + + /* 3 <5> Set MAC HW */ + /* 4 <5.1> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + { + UINT_8 ucLowestBasicRateIndex; + + if (!rateGetLowestRateIndexFromRateSet(prAisBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex)) { + + if (prAisBssInfo->ucPhyTypeSet & PHY_TYPE_BIT_OFDM) + ucLowestBasicRateIndex = RATE_6M_INDEX; + else + ucLowestBasicRateIndex = RATE_1M_INDEX; + } + + prAisBssInfo->ucHwDefaultFixedRateCode = + aucRateIndex2RateCode[prAisBssInfo->fgUseShortPreamble][ucLowestBasicRateIndex]; + } + + /* 4 <5.2> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prAisBssInfo); + + /* 4 <5.3> use command packets to inform firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <5.4> enable beaconing */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 4 <5.5> Update AdHoc PM parameter */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* 3 <6> Set ACTIVE flag. */ + prAisBssInfo->fgIsBeaconActivated = TRUE; + prAisBssInfo->fgHoldSameBssidForIBSS = TRUE; + +} /* end of aisUpdateBssInfoForMergeIBSS() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + BOOLEAN fgReplyProbeResp = FALSE; + + ASSERT(prSwRfb); + ASSERT(pu4ControlFlags); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> Parse Probe Req IE and Get IE ptr (SSID, Supported Rate IE, ...) */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) prSwRfb->pvHeader + prSwRfb->u2HeaderLen; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_SSID == IE_ID(pucIE)) { + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (P_IE_SSID_T) pucIE; + break; + } + } /* end of IE_FOR_EACH */ + + /* 4 <2> Check network conditions */ + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + if ((prIeSsid) && ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, /* CURRENT SSID */ + prIeSsid->aucSSID, prIeSsid->ucLength))) { + fgReplyProbeResp = TRUE; + } + } + + return fgReplyProbeResp; + +} /* end of aisValidateProbeReq() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will modify and update necessary information to firmware +* for disconnection handling +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmDisconnect(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgDelayIndication) +{ + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); + +#if CFG_SUPPORT_ADHOC + if (prAisBssInfo->fgIsBeaconActivated) { + nicUpdateBeaconIETemplate(prAdapter, IE_UPD_METHOD_DELETE_ALL, NETWORK_TYPE_AIS_INDEX, 0, NULL, 0); + + prAisBssInfo->fgIsBeaconActivated = FALSE; + } +#endif + + rlmBssAborted(prAdapter, prAisBssInfo); + + /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { + /* add for ctia mode */ + { + UINT_8 aucP2pSsid[] = CTIA_MAGIC_SSID; + + if (EQUAL_SSID(aucP2pSsid, CTIA_MAGIC_SSID_LEN, prAisBssInfo->aucSSID, prAisBssInfo->ucSSIDLen)) + nicEnterCtiaMode(prAdapter, FALSE, FALSE); + } + + if (prAisBssInfo->ucReasonOfDisconnect == DISCONNECT_REASON_CODE_RADIO_LOST) { + scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* remove from scanning results as well */ + wlanClearBssInScanningResult(prAdapter, prAisBssInfo->aucBSSID); + + /* trials for re-association */ + if (fgDelayIndication) { + DBGLOG(AIS, INFO, "try to do re-association due to radio lost!\n"); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_RECONNECT, TRUE); + aisFsmInsertRequest(prAdapter, AIS_REQUEST_RECONNECT); + } + } else { + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + } + + if (fgDelayIndication) { + if (OP_MODE_IBSS != prAisBssInfo->eCurrentOPMode) + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + } else { + prAisBssInfo->fgHoldSameBssidForIBSS = FALSE; + } + + /* 4 <4> Change Media State immediately. */ + if (prAisBssInfo->ucReasonOfDisconnect != DISCONNECT_REASON_CODE_REASSOCIATION) { + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + + if (!fgDelayIndication) { + /* 4 <5> Deactivate previous AP's STA_RECORD_T or all Clients in Driver if have. */ + if (prAisBssInfo->prStaRecOfAP) { + /* cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); */ + + prAisBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + } + } +#if CFG_SUPPORT_ROAMING + roamingFsmRunEventAbort(prAdapter); + + /* clear pending roaming connection request */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); +#endif /* CFG_SUPPORT_ROAMING */ + + /* 4 <6> Indicate Disconnected Event to Host */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, fgDelayIndication); + + /* 4 <7> Trigger AIS FSM */ + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + +} /* end of aisFsmDisconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of Scan done Time-Out to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 IsrCnt = 0, IsrPassCnt = 0, TaskIsrCnt = 0; +VOID aisFsmRunEventScanDoneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ +#define SCAN_DONE_TIMEOUT_TIMES_LIMIT 20 + + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + P_CONNECTION_SETTINGS_T prConnSettings; + GL_HIF_INFO_T *HifInfo; + UINT_32 u4FwCnt; + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("aisFsmRunEventScanDoneTimeOut()"); + + prGlueInfo = prAdapter->prGlueInfo; + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + + DBGLOG(AIS, WARN, "aisFsmRunEventScanDoneTimeOut Current[%d], ucScanTimeoutTimes=%d\n", + prAisFsmInfo->eCurrentState, ucScanTimeoutTimes); + DBGLOG(AIS, WARN, "Isr/task %u %u %u (0x%x)\n", prGlueInfo->IsrCnt, prGlueInfo->IsrPassCnt, + prGlueInfo->TaskIsrCnt, prAdapter->fgIsIntEnable); + + /* dump firmware program counter */ + DBGLOG(AIS, WARN, "CONNSYS FW CPUINFO:\n"); + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(AIS, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + + ucScanTimeoutTimes++; + if (ucScanTimeoutTimes > SCAN_DONE_TIMEOUT_TIMES_LIMIT) { + kalSendAeeWarning("[Scan done timeout more than 20 times!]", __func__); + glDoChipReset(); + } +#if 0 /* ALPS02018734: remove trigger assert */ + if (prAdapter->fgTestMode == FALSE) { + /* Titus - xxx */ + /* assert if and only if in normal mode */ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 40); + } +#endif + /* report all scanned frames to upper layer to avoid scanned frame is timeout */ + /* must be put before kalScanDone */ +/* scanReportBss2Cfg80211(prAdapter,BSS_TYPE_INFRASTRUCTURE,NULL); */ + + prConnSettings->fgIsScanReqIssued = FALSE; + kalScanDone(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_AIS_INDEX, WLAN_STATUS_SUCCESS); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_SCAN: + prAisFsmInfo->u4ScanIELength = 0; + eNextState = AIS_STATE_IDLE; + break; + case AIS_STATE_ONLINE_SCAN: + /* reset scan IE buffer */ + prAisFsmInfo->u4ScanIELength = 0; +#if CFG_SUPPORT_ROAMING + eNextState = aisFsmRoamingScanResultsUpdate(prAdapter); +#else + eNextState = AIS_STATE_NORMAL_TR; +#endif /* CFG_SUPPORT_ROAMING */ + break; + default: + break; + } + + /* try to stop scan in CONNSYS */ + aisFsmStateAbort_SCAN(prAdapter); + + /* wlanQueryDebugCode(prAdapter); */ /* display current SCAN FSM in FW, debug use */ + + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Background Scan Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventBGSleepTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventBGSleepTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_WAIT_FOR_NEXT_SCAN: + DBGLOG(AIS, LOUD, "EVENT - SCAN TIMER: Idle End - Current Time = %u\n", kalGetTimeTick()); + + eNextState = AIS_STATE_LOOKING_FOR; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX); + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmBGSleepTimeout() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "IBSS ALONE Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventIbssAloneTimeOut(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DEBUGFUNC("aisFsmRunEventIbssAloneTimeOut()"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_IBSS_ALONE: + + /* There is no one participate in our AdHoc during this TIMEOUT Interval + * so go back to search for a valid IBSS again. + */ + + DBGLOG(AIS, LOUD, "EVENT-IBSS ALONE TIMER: Start pairing\n"); + + prAisFsmInfo->fgTryScan = TRUE; + + /* abort timer */ + aisFsmReleaseCh(prAdapter); + + /* Pull back to SEARCH to find candidate again */ + eNextState = AIS_STATE_SEARCH; + + break; + + default: + break; + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisIbssAloneTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Join Time-Out" to AIS FSM. +* +* @param[in] u4Param Unused timer parameter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventJoinTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + ENUM_AIS_STATE_T eNextState; + OS_SYSTIME rCurrentTime; + + DEBUGFUNC("aisFsmRunEventJoinTimeout()"); + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + eNextState = prAisFsmInfo->eCurrentState; + + GET_CURRENT_SYSTIME(&rCurrentTime); + switch (prAisFsmInfo->eCurrentState) { + case AIS_STATE_JOIN: + DBGLOG(AIS, LOUD, "EVENT- JOIN TIMEOUT\n"); + + /* 1. Do abort JOIN */ + aisFsmStateAbort_JOIN(prAdapter); + + /* 2. Increase Join Failure Count */ + prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount++; +/* For JB nl802.11 */ + if (prAisFsmInfo->prTargetBssDesc->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) { + /* 3.1 Retreat to AIS_STATE_SEARCH state for next try */ + eNextState = AIS_STATE_SEARCH; + } else if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* 3.2 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else if (!CHECK_FOR_TIMEOUT(rCurrentTime, prAisFsmInfo->rJoinReqTime, + SEC_TO_SYSTIME(AIS_JOIN_TIMEOUT))) { + /* 3.3 Retreat to AIS_STATE_WAIT_FOR_NEXT_SCAN state for next try */ + eNextState = AIS_STATE_WAIT_FOR_NEXT_SCAN; + } else { + /* 3.4 Retreat to AIS_STATE_JOIN_FAILURE to terminate join operation */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_CONNECT_INDICATION, NULL, 0); + eNextState = AIS_STATE_IDLE; + } + break; + + case AIS_STATE_NORMAL_TR: + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + prAisFsmInfo->fgIsInfraChannelFinished = TRUE; + + /* 2. process if there is pending scan */ + if (aisFsmIsRequestPending(prAdapter, AIS_REQUEST_SCAN, TRUE) == TRUE) { + wlanClearScanningResult(prAdapter); + eNextState = AIS_STATE_ONLINE_SCAN; + } + + break; + + default: + /* release channel */ + aisFsmReleaseCh(prAdapter); + break; + + } + + /* Call aisFsmSteps() when we are going to change AIS STATE */ + if (eNextState != prAisFsmInfo->eCurrentState) + aisFsmSteps(prAdapter, eNextState); + +} /* end of aisFsmRunEventJoinTimeout() */ + +VOID aisFsmRunEventDeauthTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + aisDeauthXmitComplete(prAdapter, NULL, TX_RESULT_LIFE_TIMEOUT); +} + +#if defined(CFG_TEST_MGMT_FSM) && (CFG_TEST_MGMT_FSM != 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisTest(VOID) +{ + P_MSG_AIS_ABORT_T prAisAbortMsg; + P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucSSID[] = "pci-11n"; + UINT_8 ucSSIDLen = 7; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* Set Connection Request Issued Flag */ + prConnSettings->fgIsConnReqIssued = TRUE; + prConnSettings->ucSSIDLen = ucSSIDLen; + kalMemCopy(prConnSettings->aucSSID, aucSSID, ucSSIDLen); + + prAisAbortMsg = (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) { + + ASSERT(0); /* Can't trigger SCAN FSM */ + return; + } + + prAisAbortMsg->rMsgHdr.eMsgId = MID_HEM_AIS_FSM_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + + wifi_send_msg(INDX_WIFI, MSG_ID_WIFI_IST, 0); + +} +#endif /* CFG_TEST_MGMT_FSM */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle OID_802_11_BSSID_LIST_SCAN +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prSsid Pointer of SSID_T if specified +* \param[in] pucIe Pointer to buffer of extra information elements to be attached +* \param[in] u4IeLength Length of information elements +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmScanRequest(IN P_ADAPTER_T prAdapter, IN P_PARAM_SSID_T prSsid, IN PUINT_8 pucIe, IN UINT_32 u4IeLength) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + + DEBUGFUNC("aisFsmScanRequest()"); + + ASSERT(prAdapter); + ASSERT(u4IeLength <= MAX_IE_LENGTH); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (!prConnSettings->fgIsScanReqIssued) { + prConnSettings->fgIsScanReqIssued = TRUE; + + if (prSsid == NULL) { + prAisFsmInfo->ucScanSSIDLen = 0; + } else { + COPY_SSID(prAisFsmInfo->aucScanSSID, + prAisFsmInfo->ucScanSSIDLen, prSsid->aucSsid, (UINT_8) prSsid->u4SsidLen); + } + + if (u4IeLength > 0 && u4IeLength <= MAX_IE_LENGTH) { + prAisFsmInfo->u4ScanIELength = u4IeLength; + kalMemCopy(prAisFsmInfo->aucScanIEBuf, pucIe, u4IeLength); + } else { + prAisFsmInfo->u4ScanIELength = 0; + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + if (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE + && prAisFsmInfo->fgIsInfraChannelFinished == FALSE) { + /* 802.1x might not finished yet, pend it for later handling .. */ + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } else { + if (prAisFsmInfo->fgIsChannelGranted == TRUE) { + DBGLOG(AIS, WARN, + "Scan Request with channel granted for join operation: %d, %d", + prAisFsmInfo->fgIsChannelGranted, prAisFsmInfo->fgIsChannelRequested); + } + + /* start online scan */ + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_ONLINE_SCAN); + } + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE) { + wlanClearScanningResult(prAdapter); + aisFsmSteps(prAdapter, AIS_STATE_SCAN); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_SCAN); + } + } else { + DBGLOG(AIS, WARN, "Scan Request dropped. (state: %d)\n", prAisFsmInfo->eCurrentState); + } + +} /* end of aisFsmScanRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is invoked when CNM granted channel privilege +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prAisBssInfo; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_GRANT_T prMsgChGrant; + UINT_8 ucTokenID; + UINT_32 u4GrantInterval; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + + ucTokenID = prMsgChGrant->ucTokenID; + u4GrantInterval = prMsgChGrant->u4GrantInterval; + + /* 1. free message */ + cnmMemFree(prAdapter, prMsgHdr); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_CHANNEL_JOIN && prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + + /* 3. state transition to join/ibss-alone/ibss-merge */ + /* 3.1 set timeout timer in cases join could not be completed */ + cnmTimerStartTimer(prAdapter, + &prAisFsmInfo->rJoinTimeoutTimer, + prAisFsmInfo->u4ChGrantedInterval - AIS_JOIN_CH_GRANT_THRESHOLD); + /* 3.2 set local variable to indicate join timer is ticking */ + prAisFsmInfo->fgIsInfraChannelFinished = FALSE; + + /* 3.3 switch to join state */ + aisFsmSteps(prAdapter, AIS_STATE_JOIN); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL && + prAisFsmInfo->ucSeqNumOfChReq == ucTokenID) { + /* 2. channel privilege has been approved */ + prAisFsmInfo->u4ChGrantedInterval = u4GrantInterval; + + /* 3.1 set timeout timer in cases upper layer cancel_remain_on_channel never comes */ + cnmTimerStartTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer, prAisFsmInfo->u4ChGrantedInterval); + + /* 3.2 switch to remain_on_channel state */ + aisFsmSteps(prAdapter, AIS_STATE_REMAIN_ON_CHANNEL); + + /* 3.3. indicate upper layer for channel ready */ + kalReadyOnChannel(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, + prAisFsmInfo->rChReqInfo.ucChannelNum, prAisFsmInfo->rChReqInfo.u4DurationMs); + + prAisFsmInfo->fgIsChannelGranted = TRUE; + } else { /* mismatched grant */ + /* 2. return channel privilege to CNM immediately */ + aisFsmReleaseCh(prAdapter); + } + +} /* end of aisFsmRunEventChGrant() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmReleaseCh(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_CH_ABORT_T prMsgChAbort; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (prAisFsmInfo->fgIsChannelGranted == TRUE || prAisFsmInfo->fgIsChannelRequested == TRUE) { + + prAisFsmInfo->fgIsChannelRequested = FALSE; + prAisFsmInfo->fgIsChannelGranted = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChAbort = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChAbort) { + ASSERT(0); /* Can't release Channel to CNM */ + return; + } + + prMsgChAbort->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChAbort->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prMsgChAbort->ucTokenID = prAisFsmInfo->ucSeqNumOfChReq; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChAbort, MSG_SEND_METHOD_BUF); + } + +} /* end of aisFsmReleaseCh() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that corresponding beacon has not +* been received for a while and probing is not successful +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisBssBeaconTimeout(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo; + BOOLEAN fgDoAbortIndication = FALSE; + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1> Diagnose Connection for Beacon Timeout Event */ + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) { + if (OP_MODE_INFRASTRUCTURE == prAisBssInfo->eCurrentOPMode) { + P_STA_RECORD_T prStaRec = prAisBssInfo->prStaRecOfAP; + + if (prStaRec) + fgDoAbortIndication = TRUE; + } else if (OP_MODE_IBSS == prAisBssInfo->eCurrentOPMode) { + fgDoAbortIndication = TRUE; + } + } + /* 4 <2> invoke abort handler */ + if (fgDoAbortIndication) { +#if 0 + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsDisconnectedByNonRequest = TRUE; +#endif + + DBGLOG(AIS, INFO, "Beacon Timeout, Remove BSS [%pM]\n", prAisBssInfo->aucBSSID); + scanRemoveBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + + /* + Note: Cannot change TRUE to FALSE; or you will suffer the problem in + ALPS01270257/ ALPS01804173 + */ + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, TRUE); + } + +} /* end of aisBssBeaconTimeout() */ + +VOID aisBssSecurityChanged(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prAdapter->rWifiVar.rConnSettings.fgIsDisconnectedByNonRequest = TRUE; + prAisBssInfo->u2DeauthReason = REASON_CODE_BSS_SECURITY_CHANGE; + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_DEAUTHENTICATED, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform AIS that DEAUTH frame has been +* sent and thus state machine could go ahead +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] prMsduInfo Pointer of MSDU_INFO_T for DEAUTH frame +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +aisDeauthXmitComplete(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (rTxDoneStatus == TX_RESULT_SUCCESS) + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rDeauthDoneTimer); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_DISCONNECTING) { + if (rTxDoneStatus != TX_RESULT_DROPPED_IN_DRIVER) + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_NEW_CONNECTION, FALSE); + } else { + DBGLOG(AIS, WARN, "DEAUTH frame transmitted without further handling"); + } + + return WLAN_STATUS_SUCCESS; + +} /* end of aisDeauthXmitComplete() */ + +#if CFG_SUPPORT_ROAMING +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate an Event of "Looking for a candidate due to weak signal" to AIS FSM. +* +* @param[in] u4ReqScan Requesting Scan or not +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRunEventRoamingDiscovery(IN P_ADAPTER_T prAdapter, UINT_32 u4ReqScan) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + ENUM_AIS_REQUEST_TYPE_T eAisRequest; + + DBGLOG(AIS, LOUD, "aisFsmRunEventRoamingDiscovery()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* search candidates by best rssi */ + prConnSettings->eConnectionPolicy = CONNECT_BY_SSID_BEST_RSSI; + +#if CFG_SUPPORT_WFD +#if CFG_ENABLE_WIFI_DIRECT + { + /* Check WFD is running */ + P_BSS_INFO_T prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered && + IS_BSS_ACTIVE(prP2pBssInfo) && + (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || + prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)) { + DBGLOG(ROAMING, INFO, "Handle roaming when P2P is GC or GO.\n"); + if (prAdapter->rWifiVar.prP2pFsmInfo) { + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + if ((prWfdCfgSettings->ucWfdEnable == 1) && + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + DBGLOG(ROAMING, INFO, "WFD is running. Stop roaming.\n"); + roamingFsmRunEventRoam(prAdapter); + roamingFsmRunEventFail(prAdapter, ROAMING_FAIL_REASON_NOCANDIDATE); + return; + } + } else { + ASSERT(0); + } + } /* fgIsP2PRegistered */ + } +#endif +#endif + + /* results are still new */ + if (!u4ReqScan) { + roamingFsmRunEventRoam(prAdapter); + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN + || prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eAisRequest = AIS_REQUEST_ROAMING_CONNECT; + } else { + eAisRequest = AIS_REQUEST_ROAMING_SEARCH; + } + } + + if (prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR && prAisFsmInfo->fgIsInfraChannelFinished == TRUE) { + if (eAisRequest == AIS_REQUEST_ROAMING_SEARCH) + aisFsmSteps(prAdapter, AIS_STATE_LOOKING_FOR); + else + aisFsmSteps(prAdapter, AIS_STATE_SEARCH); + } else { + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_SEARCH, TRUE); + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_ROAMING_CONNECT, TRUE); + + aisFsmInsertRequest(prAdapter, eAisRequest); + } + +} /* end of aisFsmRunEventRoamingDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the time of ScanDone for roaming and transit to Roam state. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +ENUM_AIS_STATE_T aisFsmRoamingScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_AIS_STATE_T eNextState; + + DBGLOG(AIS, LOUD, "->aisFsmRoamingScanResultsUpdate()\n"); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + roamingFsmScanResultsUpdate(prAdapter); + + eNextState = prAisFsmInfo->eCurrentState; + if (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) { + roamingFsmRunEventRoam(prAdapter); + eNextState = AIS_STATE_SEARCH; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_LOOKING_FOR) { + eNextState = AIS_STATE_SEARCH; + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_ONLINE_SCAN) { + eNextState = AIS_STATE_NORMAL_TR; + } + + return eNextState; +} /* end of aisFsmRoamingScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will modify and update necessary information to firmware +* for disconnection of last AP before switching to roaming bss. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prTargetStaRec Target of StaRec of roaming +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmRoamingDisconnectPrevAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prTargetStaRec) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, LOUD, "aisFsmRoamingDisconnectPrevAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_AIS_INDEX); + + /* Not invoke rlmBssAborted() here to avoid prAisBssInfo->fg40mBwAllowed + * to be reset. RLM related parameters will be reset again when handling + * association response in rlmProcessAssocRsp(). 20110413 + */ + /* rlmBssAborted(prAdapter, prAisBssInfo); */ + + /* 4 <3> Unset the fgIsConnected flag of BSS_DESC_T and send Deauth if needed. */ + if (PARAM_MEDIA_STATE_CONNECTED == prAisBssInfo->eConnectionState) + scanRemoveConnFlagOfBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + /* 4 <4> Change Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + /* 4 <4.1> sync. with firmware */ + prTargetStaRec->ucNetTypeIndex = 0xff; /* Virtial NetType */ + nicUpdateBss(prAdapter, NETWORK_TYPE_AIS_INDEX); + prTargetStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; /* Virtial NetType */ + +#if (CFG_SUPPORT_TDLS == 1) + TdlsexLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, prAisBssInfo->aucBSSID, + TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_ROAMING); +#endif /* CFG_SUPPORT_TDLS */ + +} /* end of aisFsmRoamingDisconnectPrevAP() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the roaming was completed. +* +* @param IN prAdapter Pointer to the Adapter structure. +* prStaRec StaRec of roaming AP +* prAssocRspSwRfb +* +* @retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID aisUpdateBssInfoForRoamingAP(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) +{ + P_BSS_INFO_T prAisBssInfo; + + DBGLOG(AIS, LOUD, "aisUpdateBssInfoForRoamingAP()"); + + ASSERT(prAdapter); + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* 4 <1.1> Change FW's Media State immediately. */ + aisChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if ((prAisBssInfo->prStaRecOfAP) && + (prAisBssInfo->prStaRecOfAP != prStaRec) && (prAisBssInfo->prStaRecOfAP->fgIsInUse)) { + cnmStaRecChangeState(prAdapter, prAisBssInfo->prStaRecOfAP, STA_STATE_1); + } + /* 4 <1.3> Update BSS_INFO_T */ + aisUpdateBssInfoForJOIN(prAdapter, prStaRec, prAssocRspSwRfb); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + aisIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, FALSE); + +} /* end of aisFsmRoamingUpdateBss() */ + +#endif /* CFG_SUPPORT_ROAMING */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Check if there is any pending request and remove it (optional) +* +* @param prAdapter +* eReqType +* bRemove +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmIsRequestPending(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType, IN BOOLEAN bRemove) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr, prPendingReqHdrNext; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + /* traverse through pending request list */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingReqHdr, + prPendingReqHdrNext, &(prAisFsmInfo->rPendingReqList), rLinkEntry, AIS_REQ_HDR_T) { + /* check for specified type */ + if (prPendingReqHdr->eReqType == eReqType) { + /* check if need to remove */ + if (bRemove == TRUE) { + LINK_REMOVE_KNOWN_ENTRY(&(prAisFsmInfo->rPendingReqList), + &(prPendingReqHdr->rLinkEntry)); + + cnmMemFree(prAdapter, prPendingReqHdr); + } + + return TRUE; + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get next pending request +* +* @param prAdapter +* +* @return P_AIS_REQ_HDR_T +*/ +/*----------------------------------------------------------------------------*/ +P_AIS_REQ_HDR_T aisFsmGetNextRequest(IN P_ADAPTER_T prAdapter) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_REQ_HDR_T prPendingReqHdr; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + LINK_REMOVE_HEAD(&(prAisFsmInfo->rPendingReqList), prPendingReqHdr, P_AIS_REQ_HDR_T); + + return prPendingReqHdr; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Insert a new request +* +* @param prAdapter +* eReqType +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN aisFsmInsertRequest(IN P_ADAPTER_T prAdapter, IN ENUM_AIS_REQUEST_TYPE_T eReqType) +{ + P_AIS_REQ_HDR_T prAisReq; + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + prAisReq = (P_AIS_REQ_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(AIS_REQ_HDR_T)); + + if (!prAisReq) { + ASSERT(0); /* Can't generate new message */ + return FALSE; + } + + prAisReq->eReqType = eReqType; + + /* attach request into pending request list */ + LINK_INSERT_TAIL(&prAisFsmInfo->rPendingReqList, &prAisReq->rLinkEntry); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Flush all pending requests +* +* @param prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFsmFlushRequest(IN P_ADAPTER_T prAdapter) +{ + P_AIS_REQ_HDR_T prAisReq; + + ASSERT(prAdapter); + + while ((prAisReq = aisFsmGetNextRequest(prAdapter)) != NULL) + cnmMemFree(prAdapter, prAisReq); + +} + +VOID aisFsmRunEventRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_REMAIN_ON_CHANNEL_T prRemainOnChannel; + P_AIS_FSM_INFO_T prAisFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prRemainOnChannel = (P_MSG_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* record parameters */ + prAisFsmInfo->rChReqInfo.eBand = prRemainOnChannel->eBand; + prAisFsmInfo->rChReqInfo.eSco = prRemainOnChannel->eSco; + prAisFsmInfo->rChReqInfo.ucChannelNum = prRemainOnChannel->ucChannelNum; + prAisFsmInfo->rChReqInfo.u4DurationMs = prRemainOnChannel->u4DurationMs; + prAisFsmInfo->rChReqInfo.u8Cookie = prRemainOnChannel->u8Cookie; + + if (prAisFsmInfo->eCurrentState == AIS_STATE_IDLE || prAisFsmInfo->eCurrentState == AIS_STATE_NORMAL_TR) { + /* transit to next state */ + aisFsmSteps(prAdapter, AIS_STATE_REQ_REMAIN_ON_CHANNEL); + } else { + aisFsmInsertRequest(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL); + } + + /* free messages */ + cnmMemFree(prAdapter, prMsgHdr); + +} + +VOID aisFsmRunEventCancelRemainOnChannel(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prCancelRemainOnChannel; + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + prCancelRemainOnChannel = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) prMsgHdr; + + /* 1. Check the cookie first */ + if (prCancelRemainOnChannel->u8Cookie == prAisFsmInfo->rChReqInfo.u8Cookie) { + + /* 2. release channel privilege/request */ + if (prAisFsmInfo->eCurrentState == AIS_STATE_REQ_REMAIN_ON_CHANNEL) { + /* 2.1 elease channel */ + aisFsmReleaseCh(prAdapter); + } else if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 2.1 release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2.2 stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + } + + /* 3. clear pending request of remain_on_channel */ + aisFsmIsRequestPending(prAdapter, AIS_REQUEST_REMAIN_ON_CHANNEL, TRUE); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } + + /* 5. free message */ + cnmMemFree(prAdapter, prMsgHdr); + +} + +VOID aisFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_MSG_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + /* prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); */ + + if (prAisFsmInfo == NULL) + break; + prMgmtTxMsg = (P_MSG_MGMT_TX_REQUEST_T) prMsgHdr; + + aisFuncTxMgmtFrame(prAdapter, + &prAisFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* aisFsmRunEventMgmtFrameTx */ + +VOID aisFsmRunEventChannelTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("aisFsmRunEventRemainOnChannel()"); + + ASSERT(prAdapter); + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prAisFsmInfo->eCurrentState == AIS_STATE_REMAIN_ON_CHANNEL) { + /* 1. release channel */ + aisFsmReleaseCh(prAdapter); + + /* 2. stop channel timeout timer */ + cnmTimerStopTimer(prAdapter, &prAisFsmInfo->rChannelTimeoutTimer); + + /* 3. expiration indication to upper layer */ + kalRemainOnChannelExpired(prAdapter->prGlueInfo, + prAisFsmInfo->rChReqInfo.u8Cookie, + prAisFsmInfo->rChReqInfo.eBand, + prAisFsmInfo->rChReqInfo.eSco, prAisFsmInfo->rChReqInfo.ucChannelNum); + + /* 4. decide which state to retreat */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + aisFsmSteps(prAdapter, AIS_STATE_NORMAL_TR); + else + aisFsmSteps(prAdapter, AIS_STATE_IDLE); + } else { + DBGLOG(AIS, WARN, "Unexpected remain_on_channel timeout event\n"); +#if DBG + DBGLOG(AIS, STATE, "CURRENT State: [%s]\n", apucDebugAisState[prAisFsmInfo->eCurrentState]); +#else + DBGLOG(AIS, STATE, "[%d] CURRENT State: [%d]\n", DBG_AIS_IDX, prAisFsmInfo->eCurrentState); +#endif + } + +} + +WLAN_STATUS +aisFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_AIS_MGMT_TX_REQ_INFO_T) NULL; + BOOLEAN fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + prMgmtTxReqInfo = &(prAisFsmInfo->rMgmtTxInfo); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(AIS, ERROR, "Mgmt Frame TX Fail, Status:%d.\n", rTxDoneStatus); + } else { + fgIsSuccess = TRUE; + /* printk("Mgmt Frame TX Done.\n"); */ + } + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* aisFsmRunEventMgmtFrameTxDone */ + +WLAN_STATUS +aisFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_AIS_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, (UINT_32) prTxMsduInfo->u2FrameLength); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanHdr->aucAddr1); + prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_AIS_INDEX; + + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; + prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); + if (prStaRec != NULL) { + /* Do nothing */ + /* printk("Mgmt with station record: %pM .\n", prStaRec->aucMacAddr); */ + } + + prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ + prMgmtTxMsdu->fgIs802_1x = FALSE; + prMgmtTxMsdu->fgIs802_11 = TRUE; + prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMgmtTxMsdu->pfTxDoneHandler = aisFsmRunEventMgmtFrameTxDone; + prMgmtTxMsdu->fgIsBasicRate = TRUE; + DBGLOG(AIS, TRACE, "Mgmt seq NO. %d .\n", prMgmtTxMsdu->ucTxSeqNum); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* aisFuncTxMgmtFrame */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Action Frame and indicate to uppoer layer +* if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID aisFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + + DEBUGFUNC("aisFuncValidateRxActionFrame"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prAisFsmInfo = &(prAdapter->rWifiVar.rAisFsmInfo); + + if (1 /* prAisFsmInfo->u4AisPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME */) { + /* Leave the action frame to wpa_supplicant. */ + kalIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* aisFuncValidateRxActionFrame */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c new file mode 100644 index 0000000000000..f02d7c3bb5b27 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/assoc.c @@ -0,0 +1,1932 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/assoc.c#3 +*/ + +/*! \file "assoc.c" + \brief This file includes the association-related functions. + + This file includes the association-related functions. +*/ + +/*\ +** Log: assoc.c +** +** 07 27 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Fix wifi direct connection issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 06 08 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * add a pair of brace for compilation success. + * + * 06 04 2012 cp.wu + * [WCXRP00001245] [MT6620 Wi-Fi][Driver][Firmware] NPS Software Development + * discussed with WH, privacy bit in associate response is not necessary to be checked, + * and identified as association failure when mismatching with beacon/probe response + * + * 03 14 2012 wh.su + * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting + * Add code from 2.2 + * + * 03 09 2012 terry.wu + * NULL + * Fix build error. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 yuche.tsai + * NULL + * Update Driver for wifi driect gc join IE update issue. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Fix PhyTypeSet in STA_REC in AP mode + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 19 2011 yuche.tsai + * NULL + * Fix KE when enable hot-spot & any one client connect to this hot-spot. + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 07 15 2011 terry.wu + * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment + * Update workaround for Kingnet AP. + * + * 07 15 2011 terry.wu + * [WCXRP00000855] [MT6620 Wi-Fi] [Driver] Workaround for Kingnet 710 AP wrong AID assignment + * Workaround for Kingnet 710 AP wrong AID assignment. + * + * 05 02 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning[WCXRP00000672] [MT6620 Wi-Fi][FW] + * Fix the PS event allocation + * Check STA when rx assoc. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 03 14 2011 wh.su + * [WCXRP00000545] [MT6620 Wi-Fi] [Driver] Fixed the p2p not enable, received a assoc rsp + * cause the rx assoc execute a null function + * Modify file for avoid assert at BOW receive a assoc response frame but no p2p function. + * + * 03 08 2011 terry.wu + * [WCXRP00000524] [MT6620 Wi-Fi][Driver] Fix p2p assoc request containing wrong IE format + * Fix p2p assoc request containing wrong IE format. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix RX disassoc issue under Hot-spot mode. + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Update Phy Type Set. When legacy client is connected, it can use 11b rate, + * but if the P2P device is connected, 11b rate is not allowed. + * + * 01 11 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Update Desired Non-HT Rate Set. + * + * 12 30 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Recover the code that was coverwritted.. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 yuche.tsai + * NULL + * Add SSID IE in assoc req frame which is sent by P2P GC. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RSN IE generation by CFG_RSN_MIGRATION compilation flag. + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * revised. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update assocProcessRxAssocReqFrame() to avoid redundant SSID IE {0,0} for IOT. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix compile warning - macro > 10 line, initial value of an array + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * * * * * * and will send Null frame to diagnose connection + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * adding the wpa-none for ibss beacon. + * + * 03 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 28 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * fixed the compiling warning.u1rwduu`wvpghlqg|rm+vp + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update Assoc ID for PS + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Use new constant definition ELEM_MAX_LEN_EXT_CAP + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Modify assoc req IE talbe for HT cap IE + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * update the assocComposeReAssocReqFrameHeader() and fix the u2EstimatedFrameLen in assocSendReAssocReqFrame() + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * remove some space line + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the sending disassoc frame function + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the txassocReq IE table, adding for WPA/RSN + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix eNetType not init in send AssocReq function + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Integrate the send Assoc with TXM + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code to indicate the assoc request and assoc response (now disable) + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove unused variables + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +APPEND_VAR_IE_ENTRY_T txAssocReqIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmReqGenerateHtCapIE} + , /* 45 */ +#if CFG_SUPPORT_WPS2 + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WSC), NULL, rsnGenerateWSCIE} + , /* 221 */ +#endif +#if CFG_RSN_MIGRATION + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} + , /* 48 */ +#endif +#if CFG_SUPPORT_WAPI + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WAPI), NULL, wapiGenerateWAPIIE} + , /* 68 */ +#endif +#if CFG_SUPPORT_HOTSPOT_2_0 + {(ELEM_HDR_LEN + ELEM_MAX_LEN_INTERWORKING), NULL, hs20GenerateInterworkingIE} + , /* 107 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ROAMING_CONSORTIUM), NULL, hs20GenerateRoamingConsortiumIE} + , /* 111 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmReqGenerateExtCapIE} + , /* 127 */ +#if CFG_SUPPORT_HOTSPOT_2_0 + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HS20_INDICATION), NULL, hs20GenerateHS20IE} + , /* 221 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO), NULL, mqmGenerateWmmInfoIE} + , /* 221 */ +#if CFG_RSN_MIGRATION + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE} + , /* 221 */ +#endif +}; + +#if CFG_SUPPORT_AAA +VERIFY_IE_ENTRY_T rxAssocReqIETable[] = { + {ELEM_ID_RESERVED, NULL} /* 255 */ +}; + +APPEND_VAR_IE_ENTRY_T txAssocRespIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE} + , /* 42 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE} + , /* 45 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE} + , /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE} + , /* 74 */ + {(0), p2pFuncCalculateP2p_IELenForAssocRsp, p2pFuncGenerateP2p_IEForAssocRsp} + , /* 221 */ +#if CFG_SUPPORT_WFD + {(0), wfdFuncCalculateWfdIELenForAssocRsp, wfdFuncGenerateWfdIEForAssocRsp} + , /* 221 */ +#endif +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE} + , /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} + , /* 221 */ + + {(0), p2pFuncCalculateWSC_IELenForAssocRsp, p2pFuncGenerateWSC_IEForAssocRsp} /* 221 */ + +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose the Capability Info Field. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval Capability Info Field +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 +assocBuildCapabilityInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_32 u4NonHTPhyType; + UINT_16 u2CapInfo; + + /* Set up our requested capabilities. */ + u2CapInfo = CAP_INFO_ESS; + u2CapInfo |= CAP_CF_STA_NOT_POLLABLE; + + if (prStaRec == NULL) + u2CapInfo |= CAP_INFO_PRIVACY; + else { + if (prStaRec->u2CapInfo & CAP_INFO_PRIVACY) + u2CapInfo |= CAP_INFO_PRIVACY; + } + + /* 7.3.1.4 */ + if (prStaRec == NULL) { + if ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) ||/* ShortPreambleOptionEnable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO)) + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + if (prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) + u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } else if (prStaRec->fgHasBasicPhyType) { + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + if ((rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortPreambleOptionImplemented) && + /* Short Preamble Option Enable is TRUE */ + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO) && + (prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + /* Case I: Implemented == TRUE and Short Preamble Option Enable == TRUE. + * Case II: Implemented == TRUE and Short Preamble == AUTO (depends on + * BSS_DESC_T's capability) + */ + u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + } +#if CFG_SUPPORT_SPEC_MGMT /*Add by Enlai */ + /* Support 802.11h */ + if (prStaRec->u2CapInfo & CAP_INFO_SPEC_MGT) { + /* + 1. The Power Capability element shall be present if + dot11SpectrumManagementRequired is true. + + 2. A STA shall set dot11SpectrumManagementRequired to TRUE before + associating with a BSS or IBSS in which the Spectrum Management + bit is set to 1 in the Capability Information field in Beacon frames + and Probe Response frames received from the BSS or IBSS. + */ + if (prAdapter->fgEnable5GBand == TRUE) + u2CapInfo |= CAP_INFO_SPEC_MGT; + } +#endif + + if (rNonHTPhyAttributes[u4NonHTPhyType].fgIsShortSlotTimeOptionImplemented && + prAdapter->rWifiVar.fgIsShortSlotTimeOptionEnable) { + u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + } + } + + if (prStaRec) { + DBGLOG(SAA, LOUD, "ASSOC REQ: Compose Capability = 0x%04x for Target BSS [%pM].\n", + u2CapInfo, prStaRec->aucMacAddr); + } + + return u2CapInfo; + +} /* end of assocBuildCapabilityInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID assocBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + PUINT_8 pucBuffer; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (ULONG) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (IS_STA_IN_AIS(prStaRec)) { + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) + pucBuffer = p2pBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo, pucBuffer); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prConnSettings->aucSSID, prConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +#endif + else { + /* Do nothing */ + /* TODO(Kevin): For other network */ + } + + /* NOTE(Kevin 2008/12/19): 16.3.6.3 MLME-ASSOCIATE.indication - + * SupportedRates - The set of data rates that are supported by the STA + * that is requesting association. + * Original(Portable Driver): Only send the Rates that we'll support. + * New: Send the Phy Rates if the result of following & operation == NULL. + */ + /* rateGetDataRatesFromRateSet((prBssDesc->u2OperationalRateSet & */ + /* rPhyAttributes[prBssDesc->ePhyType].u2SupportedRateSet), */ + + if (prStaRec->fgHasBasicPhyType) { + UINT_32 u4NonHTPhyType; + + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + + u2SupportedRateSet = (prStaRec->u2OperationalRateSet & + rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet); + + ASSERT(u2SupportedRateSet); + + if (!u2SupportedRateSet) + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + + /* TODO(Kevin): For P2P, we shouldn't send support rate set which contains 11b rate */ + + rateGetDataRatesFromRateSet(u2SupportedRateSet, 0, aucAllSupportedRates, &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* 7.3.2.19 Supported Channels element */ +#if CFG_SUPPORT_DFS /* Add by Enlai */ + if (prAdapter->fgEnable5GBand == TRUE) { + SUPPORTED_CHANNELS_IE(pucBuffer)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucLength = 8; + + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[0] = 36; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[1] = 4; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[2] = 52; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[3] = 4; +/* Not China --- Start */ + /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 100; */ + /* SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 11; */ +/* Not China --- End */ + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[4] = 149; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[6] = 165; + SUPPORTED_CHANNELS_IE(pucBuffer)->ucChannelNum[7] = 1; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } +#endif + } + +} /* end of assocBuildReAssocReqFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Request frame header and +* its fixed fields +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeReAssocReqFrameHeaderAndFF(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN OUT PUINT_16 pu2PayloadLen) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + UINT_16 u2CapInfo; + UINT_16 u2ListenInterval; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + ASSERT(pu2PayloadLen); + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ + /* Fill the Frame Control field. */ + if (fgIsReAssoc) + u2FrameCtrl = MAC_FRAME_REASSOC_REQ; + else + u2FrameCtrl = MAC_FRAME_ASSOC_REQ; + WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + + /* Fill the Capability Information field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); + + /* Calculate the listen interval for the maximum power mode. Currently, we + set it to the value 2 times DTIM period. */ + if (prStaRec->ucDTIMPeriod) { + u2ListenInterval = prStaRec->ucDTIMPeriod * DEFAULT_LISTEN_INTERVAL_BY_DTIM_PERIOD; + } else { + DBGLOG(SAA, TRACE, "Use default listen interval\n"); + u2ListenInterval = DEFAULT_LISTEN_INTERVAL; + } + prStaRec->u2ListenInterval = u2ListenInterval; + + /* Fill the Listen Interval field. */ + WLAN_SET_FIELD_16(&prAssocFrame->u2ListenInterval, u2ListenInterval); + + /* 4 <3> Compose the Current AP Address field for ReAssociation Request frame. */ + /* Fill the Current AP Address field. */ + if (prStaRec->fgIsReAssoc) { + if (IS_STA_IN_AIS(prStaRec)) { + + P_AIS_BSS_INFO_T prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + P_WLAN_REASSOC_REQ_FRAME_T prReAssocFrame = (P_WLAN_REASSOC_REQ_FRAME_T) prAssocFrame; + + COPY_MAC_ADDR(prReAssocFrame->aucCurrentAPAddr, prAisBssInfo->aucBSSID); + } else { + ASSERT(0); /* We don't support ReAssociation for other network */ + } + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN + CURR_AP_ADDR_FIELD_LEN); + } else { + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN); + } + +} /* end of assocComposeReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Request frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + if (fgIsReAssoc) { + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + CAP_INFO_FIELD_LEN + + LISTEN_INTERVAL_FIELD_LEN + + CURR_AP_ADDR_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + } else { + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + CAP_INFO_FIELD_LEN + + LISTEN_INTERVAL_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + } + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + if ((prAdapter->fgIsP2PRegistered)) { + u2EstimatedExtraIELen = p2pCalculate_IEForAssocReq(prAdapter, + prStaRec->ucNetTypeIndex, prStaRec); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += + (UINT_16) txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + } + } +#else + for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocReqIETable[i].u2EstimatedFixedIELen; + } else { + u2EstimatedExtraIELen += (UINT_16) txAssocReqIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + } +#endif + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and Fixed Field */ + assocComposeReAssocReqFrameHeaderAndFF(prAdapter, + prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucOwnMacAddr, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ + assocBuildReAssocReqFrameCommonIEs(prAdapter, prMsduInfo); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 && CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + if ((prAdapter->fgIsP2PRegistered)) { + p2pGenerate_IEForAssocReq(prAdapter, prMsduInfo); + } else { + DBGLOG(P2P, TRACE, "Function Linker Lost.\n"); + ASSERT(FALSE); + } + } else { + /* Append IE */ + for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + } +#else + /* Append IE */ + for (i = 0; i < sizeof(txAssocReqIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocReqIETable[i].pfnAppendIE) + txAssocReqIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } +#endif + + /* 4 <6> Update the (Re)association request information */ + if (IS_STA_IN_AIS(prStaRec)) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + +#if CFG_RSN_MIGRATION + kalUpdateReAssocReqInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + P_WLAN_ASSOC_REQ_FRAME_T prAssocFrame; + + prAssocFrame = (P_WLAN_ASSOC_REQ_FRAME_T) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocFrame->u2CapInfo, + prMsduInfo->u2FrameLength - offsetof(WLAN_ASSOC_REQ_FRAME_T, u2CapInfo), + fgIsReAssoc); + } +#endif + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ + DBGLOG(SAA, INFO, "Sending (Re)Assoc Request, network: %d seqNo: %d\n", + prMsduInfo->ucNetworkType, prMsduInfo->ucTxSeqNum); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Request frame for +* SAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocCheckTxReAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAssocReqFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_REQ) + return WLAN_STATUS_FAILURE; + } else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_REQ) + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX (Re)Association Response frame for +* AAA event handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocCheckTxReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAssocRspFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAssocFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2TxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + } else { + if (u2TxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckTxReAssocRespFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming (Re)Association Frame and take out +* the status code. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocCheckRxReAssocRspFrameStatus(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + UINT_16 u2RxFrameCtrl; + UINT_16 u2RxCapInfo; + UINT_16 u2RxStatusCode; + UINT_16 u2RxAssocId; + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(SAA, LOUD, "prSwRfb->u2PayloadLength = %d\n", prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* 4 <1> locate the (Re)Association Resp Frame. */ + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of (Re)Association Resp Frame. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocRspFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (prStaRec->fgIsReAssoc) { + if (u2RxFrameCtrl != MAC_FRAME_REASSOC_RSP) + return WLAN_STATUS_FAILURE; + } else { + if (u2RxFrameCtrl != MAC_FRAME_ASSOC_RSP) + return WLAN_STATUS_FAILURE; + } + + /* 4 <3> Parse the Fixed Fields of (Re)Association Resp Frame Body. */ + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2CapInfo, &u2RxCapInfo); */ + u2RxCapInfo = prAssocRspFrame->u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2StatusCode, &u2RxStatusCode); */ + u2RxStatusCode = prAssocRspFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + /* 4 <4> Check CAP_INFO */ + /* NOTE(Kevin): CM suggest to add MGMT workaround for those APs didn't check + * the CAP Privacy Bit to overcome a corner case that the Privacy Bit + * of our SCAN result didn't consist with AP's Association Resp. + */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + /* WAPI AP allow the customer use WZC to join mode, the privacy bit is 0 */ + /* even at WAI & WAPI_PSK mode, but the assoc respose set the privacy bit set 1 */ + DBGLOG(SEC, TRACE, "Workaround the WAPI AP allow the customer to use WZC to join\n"); + } else +#endif +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && 1) { + /* Todo:: Fixed this */ + } else +#endif + { + } + +#if CFG_STRICT_CHECK_CAPINFO_PRIVACY + if ((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) ^ (u2RxCapInfo & CAP_INFO_PRIVACY)) + u2RxStatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; +#endif + } + + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { +#if CFG_RSN_MIGRATION + /* Update the information in the structure used to query and set + OID_802_11_ASSOCIATION_INFORMATION. */ + kalUpdateReAssocRspInfo(prAdapter->prGlueInfo, + (PUINT_8) &prAssocRspFrame->u2CapInfo, (UINT_32) (prSwRfb->u2PacketLen)); +#endif + } + /* 4 <5> Update CAP_INFO and ASSOC_ID */ + if (u2RxStatusCode == STATUS_CODE_SUCCESSFUL) { + prStaRec->u2CapInfo = u2RxCapInfo; + + /* WLAN_GET_FIELD_16(&prAssocRspFrame->u2AssocId, &u2RxAssocId); */ + u2RxAssocId = prAssocRspFrame->u2AssocId; /* NOTE(Kevin): Optimized for ARM */ + + /* 20110715 Workaround for Kingnet 710 AP (Realtek 8186) + * This AP raises the bit 6&7 not bit 14&15 in AID field. + * It cause wrong AID assignment. + * For AID = 2 + * Normal case: 0xC002(1100 0000 0000 0010) => 2 + * Kingnet 710: 0x00C2(0000 0000 1100 0010) => 194 + * workaround: mask bit 6&7 for this AP + */ + if ((u2RxAssocId & BIT(6)) && (u2RxAssocId & BIT(7)) && !(u2RxAssocId & BITS(8, 15))) { + prStaRec->u2AssocId = u2RxAssocId & ~BITS(6, 7); + } else { + prStaRec->u2AssocId = u2RxAssocId & ~AID_MSB; +#if CFG_SUPPORT_802_11W + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prBssSpecInfo->ucSaQueryTimedOut = 0; + } +#endif + } + } +#if CFG_SUPPORT_802_11W + if (u2RxStatusCode == STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED) { + DBGLOG(SAA, INFO, "AP rejected due the authentication algorithm not support\n"); + } else if (u2RxStatusCode == STATUS_CODE_ASSOC_REJECTED_TEMPORARILY) { + PUINT_8 pucIE, pucTime; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((ULONG) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_TIMEOUT_INTERVAL == IE_ID(pucIE) && IE_LEN(pucIE) == 5) { + pucTime = ((P_IE_HDR_T) pucIE)->aucInfo; + if (pucTime[0] == ACTION_SA_TIMEOUT_ASSOC_COMEBACK) { + UINT_32 tu; + + WLAN_GET_FIELD_32(pucTime + 1, &tu); + DBGLOG(SAA, INFO, + "AP rejected association temporarily;comeback duration %u TU (%u ms)\n", + tu, TU_TO_MSEC(tu)); + if (tu > TX_ASSOCIATION_RETRY_TIMEOUT_TU) { + DBGLOG(SAA, INFO, "Update timer based on comeback duration\n"); + /* ieee80211_reschedule_timer(wpa_s, ms); */ + } + } + break; + } + } /* end of IE_FOR_EACH */ + } +#endif + *pu2StatusCode = u2RxStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocCheckRxReAssocRspFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will compose the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2ReasonCode The reason code of disassociation +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeDisassocFrame(IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, IN UINT_8 aucMACAddress[], IN UINT_16 u2ReasonCode) +{ + P_WLAN_DISASSOC_FRAME_T prDisAssocFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(pucBuffer); + ASSERT(aucMACAddress); + + prDisAssocFrame = (P_WLAN_DISASSOC_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the DisAssociation frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DISASSOC; + + WLAN_SET_FIELD_16(&prDisAssocFrame->u2FrameCtrl, u2FrameCtrl); + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDisAssocFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDisAssocFrame->aucBSSID, prStaRec->aucMacAddr); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDisAssocFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Disassociation frame. */ + /* Fill the Reason Code field. */ + WLAN_SET_FIELD_16(&prDisAssocFrame->u2ReasonCode, u2ReasonCode); + +} /* end of assocComposeDisassocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Disassociation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2ReasonCode The reason code of disassociation +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendDisAssocFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2ReasonCode) +{ + PUINT_8 pucMacAddress; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + /* UINT_32 u4Status = WLAN_STATUS_SUCCESS; */ + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Disassociation Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending DisAssoc.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Disassociation frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + pucMacAddress = prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].aucOwnMacAddr; + + /* Compose Header and Fixed Field */ + assocComposeDisassocFrame(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucMacAddress, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + prDisassocFrame = + (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDisassocFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, "assocSendDisAssocFrame with protection\n"); + } +#endif + + u2PayloadLen = REASON_CODE_FIELD_LEN; + + /* 4 <3> Update information of MSDU_INFO_T */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Enqueue the frame to send this (Re)Association request frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of assocSendDisAssocFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Disassociation frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +assocProcessRxDisassocFrame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) +{ + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + UINT_16 u2RxReasonCode; + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + /* 4 <1> locate the Disassociation Frame. */ + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Disassociation Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDisassocFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, "Ignore Disassoc Frame from other BSS [ %pM ]\n", + prDisassocFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ + WLAN_GET_FIELD_16(&prDisassocFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxDisassocFrame() */ + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Association Req frame +* and return a Status Code. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode Pointer to store the Status Code for carried in Association Response. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocProcessRxAssocReqFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_RSN_INFO_ELEM_T prIeRsn = (P_RSN_INFO_ELEM_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + PUINT_8 pucIE, pucIEStart; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_16 u2StatusCode = STATUS_CODE_SUCCESSFUL; + UINT_16 u2RxFrameCtrl; + UINT_16 u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + /* 4 <1> locate the Association Req Frame. */ + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Association Req Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (CAP_INFO_FIELD_LEN + LISTEN_INTERVAL_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Check if this Disassoc Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prAssocReqFrame->aucBSSID, prBssInfo->aucBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + /* WLAN_GET_FIELD_16(&prAssocReqFrame->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prAssocReqFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (MAC_FRAME_REASSOC_REQ == u2RxFrameCtrl) { + prStaRec->fgIsReAssoc = TRUE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) (OFFSET_OF(WLAN_REASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = ((P_WLAN_REASSOC_REQ_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem; + } else { + prStaRec->fgIsReAssoc = FALSE; + + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) (OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN); + + pucIEStart = pucIE = prAssocReqFrame->aucInfoElem; + } + + /* 4 <3> Parse the Fixed Fields of Assoc Req Frame Body. */ + prStaRec->u2CapInfo = prAssocReqFrame->u2CapInfo; + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (((prStaRec->u2CapInfo & CAP_INFO_PRIVACY) && !kalP2PGetCipher(prAdapter->prGlueInfo))) { + u2StatusCode = STATUS_CODE_CAP_NOT_SUPPORTED; + DBGLOG(RSN, TRACE, "STA Assoc req privacy bit check fail\n"); + return WLAN_STATUS_SUCCESS; + } + } +#endif + + prStaRec->u2ListenInterval = prAssocReqFrame->u2ListenInterval; + prStaRec->ucPhyTypeSet = 0; + + /* Might be legacy client or p2p gc. */ + prStaRec->eStaType = STA_TYPE_LEGACY_CLIENT; + + /* 4 <4> Parse the IE of Assoc Req Frame Body. */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): Get SSID once */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + prIeSsid = (P_IE_SSID_T) pucIE; + } + break; + + case ELEM_ID_SUP_RATES: + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + if (!prIeExtSupportedRate) + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + case ELEM_ID_HT_CAP: + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + kalMemCopy(&prStaRec->u2HtCapInfo, &(HT_CAP_IE(pucIE)->u2HtCapInfo), 2); + break; + case ELEM_ID_RSN: +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + prIeRsn = RSN_IE(pucIE); + rsnParserCheckForRSNCCMPPSK(prAdapter, prIeRsn, &u2StatusCode); + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } +#endif + break; + case ELEM_ID_VENDOR: +#if CFG_ENABLE_WIFI_DIRECT + { + if ((prAdapter->fgIsP2PRegistered)) { + UINT_8 ucOuiType = 0; + + p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType); + + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + DBGLOG(P2P, TRACE, "Target Client is a P2P group client\n"); + prStaRec->eStaType = STA_TYPE_P2P_GC; + } + } + } +#endif + break; + default: + for (i = 0; i < (sizeof(rxAssocReqIETable) / sizeof(VERIFY_IE_ENTRY_T)); i++) { + + if ((IE_ID(pucIE)) == rxAssocReqIETable[i].ucElemID) { + rxAssocReqIETable[i].pfnVarifyIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIE, + &u2StatusCode); + + if (u2StatusCode != STATUS_CODE_SUCCESSFUL) { + *pu2StatusCode = u2StatusCode; + return WLAN_STATUS_SUCCESS; + } + } + } + + break; + } + } /* end of IE_FOR_EACH */ + + /* parsing for WMM related information (2010/12/21) */ + mqmProcessAssocReq(prAdapter, prSwRfb, pucIEStart, u2IELength); + + do { + if (prIeSsid) { + if (UNEQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + + u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; + break; + } + } else { + u2StatusCode = STATUS_CODE_UNSPECIFIED_FAILURE; + break; + } + + prStaRec->u2OperationalRateSet = 0; + prStaRec->u2BSSBasicRateSet = 0; + + if (prIeSupportedRate || prIeExtSupportedRate) { + rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, &prStaRec->u2OperationalRateSet, + &u2BSSBasicRateSet, /* Ignore any Basic Bit */ + &fgIsUnknownBssBasicRate); + + if ((prBssInfo->u2BSSBasicRateSet & prStaRec->u2OperationalRateSet) != + prBssInfo->u2BSSBasicRateSet) { + + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + + /* Accpet the Sta, update BSSBasicRateSet from Bss */ + + prStaRec->u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = (prStaRec->u2OperationalRateSet & RATE_SET_ALL_ABG); + + if (BAND_2G4 == HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr)) { +#if 0 /* Marked by CMC 20111024 */ + /* check if support 11n */ + if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + + if ((!(u2BSSBasicRateSet & RATE_SET_OFDM)) && + (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS)) { + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + + } + + } +#else + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + if (prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; +#endif + } else { /* (BAND_5G == prBssDesc->eBande) */ +#if 0 /* Marked by CMC 20111024 */ + if (!(u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + ASSERT((prStaRec->u2OperationalRateSet & RATE_SET_HR_DSSS) == 0); +#else + if (prStaRec->u2OperationalRateSet & RATE_SET_OFDM) + prStaRec->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; +#endif + } + + } else { + ASSERT(0); + u2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_HOTSPOT_PRIVACY_CHECK + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + if (prIeRsn) { + if (!kalP2PGetCipher(prAdapter->prGlueInfo)) { + u2StatusCode = STATUS_CODE_CIPHER_SUITE_REJECTED; + break; + } + } else { + prStaRec->rSecInfo.fgAllowOnly1x = FALSE; + if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + /* Only Allow 1x */ + prStaRec->rSecInfo.fgAllowOnly1x = TRUE; + break; + } + } + } +#endif + + } while (FALSE); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { +#if 1 /* ICS */ + { + PUINT_8 cp = (PUINT_8) &prAssocReqFrame->u2CapInfo; + P_UINT_8 prNewAssocReqIe = NULL; + + if (u2IELength) { + prNewAssocReqIe = kalMemAlloc(u2IELength, VIR_MEM_TYPE); + if (NULL == prNewAssocReqIe) { + DBGLOG(AIS, WARN, "allocate memory for (Re)assocReqIe fail!\n"); + u2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; + return WLAN_STATUS_FAILURE; + } + } + + if (prStaRec->fgIsReAssoc) + cp += 10; + else + cp += 4; + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + } + prStaRec->u2AssocReqIeLen = u2IELength; + if (u2IELength) { + prStaRec->pucAssocReqIe = prNewAssocReqIe; /* kalMemAlloc(u2IELength, VIR_MEM_TYPE); */ + kalMemCopy(prStaRec->pucAssocReqIe, cp, u2IELength); + } + } +#endif + kalP2PUpdateAssocInfo(prAdapter->prGlueInfo, (PUINT_8) &prAssocReqFrame->u2CapInfo, + u2IELength + (prStaRec->fgIsReAssoc ? 10 : 4), prStaRec->fgIsReAssoc); + } +#endif + + *pu2StatusCode = u2StatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of assocProcessRxAssocReqFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Association +* Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocBuildReAssocRespFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo) +{ + PUINT_8 pucBuffer; + P_STA_RECORD_T prStaRec; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) { + + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + } else { + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + ucExtSupRatesLen = 0; + } + + /* Fill the Supported Rates element. */ + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* end of assocBuildReAssocRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the (Re)Association Response frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucBssid Given BSSID. +* @param[in] u2CapInfo Capability Field of current BSS. +* @param[in out] pu2PayloadLen Return the length of the composed fixed fields +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +assocComposeReAssocRespFrameHeaderAndFF(IN P_STA_RECORD_T prStaRec, + IN PUINT_8 pucBuffer, + IN UINT_8 aucBSSID[], IN UINT_16 u2CapInfo, IN OUT PUINT_16 pu2PayloadLen) +{ + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame; + BOOLEAN fgIsReAssoc; + + UINT_16 u2FrameCtrl; + + ASSERT(prStaRec); + ASSERT(pucBuffer); + ASSERT(aucBSSID); + ASSERT(pu2PayloadLen); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) pucBuffer; + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* 4 <1> Compose the frame header of the (Re)Association Request frame. */ + /* Fill the Frame Control field. */ + if (fgIsReAssoc) + u2FrameCtrl = MAC_FRAME_REASSOC_RSP; + else + u2FrameCtrl = MAC_FRAME_ASSOC_RSP; + /* WLAN_SET_FIELD_16(&prAssocFrame->u2FrameCtrl, u2FrameCtrl); */ + prAssocRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target MAC Address. */ + COPY_MAC_ADDR(prAssocRspFrame->aucDestAddr, prStaRec->aucMacAddr); + + /* Fill the SA field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucSrcAddr, aucBSSID); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prAssocRspFrame->aucBSSID, aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prAssocRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the (Re)Association Request frame. */ + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prAssocFrame->u2CapInfo, u2CapInfo); */ + prAssocRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_SET_FIELD_16(&prAssocFrame->u2StatusCode, prStaRec->u2StatusCode); */ + prAssocRspFrame->u2StatusCode = prStaRec->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + /* WLAN_SET_FIELD_16(&prAssocFrame->u2AssocId, ((prStaRec->u2AssocId & AID_MASK) | AID_MSB)); */ + prAssocRspFrame->u2AssocId = ((prStaRec->u2AssocId & AID_MASK) | AID_MSB); /* NOTE(Kevin): Optimized for ARM */ + + *pu2PayloadLen = (CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); + +} /* end of assocComposeReAssocRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the (Re)Association Resp frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS assocSendReAssocRespFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + + UINT_16 u2PayloadLen; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + BOOLEAN fgIsReAssoc; + UINT_32 i; + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + fgIsReAssoc = prStaRec->fgIsReAssoc; + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + CAP_INFO_FIELD_LEN + + STATUS_CODE_FIELD_LEN + + AID_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].u2EstimatedFixedIELen != 0) { + u2EstimatedExtraIELen += txAssocRespIETable[i].u2EstimatedFixedIELen; + } else if (txAssocRespIETable[i].pfnCalculateVariableIELen != NULL) { + u2EstimatedExtraIELen += (UINT_16) txAssocRespIETable[i].pfnCalculateVariableIELen(prAdapter, + prStaRec->ucNetTypeIndex, + prStaRec); + } + + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(AAA, WARN, "No PKT_INFO_T for sending (Re)Assoc Response.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose (Re)Association Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex != NETWORK_TYPE_AIS_INDEX); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and Fixed Field */ + assocComposeReAssocRespFrameHeaderAndFF(prStaRec, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prBssInfo->aucBSSID, prBssInfo->u2CapInfo, &u2PayloadLen); + + /* 4 <3> Update information of MSDU_INFO_T */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = aaaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's IEs of the (Re)Association Request frame. */ + assocBuildReAssocRespFrameCommonIEs(prAdapter, prMsduInfo, prBssInfo); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ + + /* Append IE */ + for (i = 0; i < sizeof(txAssocRespIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txAssocRespIETable[i].pfnAppendIE) + txAssocRespIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Enqueue the frame to send this (Re)Association request frame. */ + DBGLOG(SAA, INFO, "Sending (Re)Assoc Response, network: %d seqNo: %d\n", + prMsduInfo->ucNetworkType, prMsduInfo->ucTxSeqNum); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of assocSendReAssocRespFrame() */ +#endif /* CFG_SUPPORT_AAA */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c new file mode 100644 index 0000000000000..43b91d72bd431 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/auth.c @@ -0,0 +1,1211 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/auth.c#1 +*/ + +/*! \file "auth.c" + \brief This file includes the authentication-related functions. + + This file includes the authentication-related functions. +*/ + +/* +** Log: auth.c + * + * 02 13 2012 cp.wu + * NULL + * show error message only instead of raise assertion when + * received authentication frame is carrying illegal parameters. + * + * 11 09 2011 yuche.tsai + * NULL + * Fix a network index & station record index issue when TX deauth frame. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 22 2011 yuche.tsai + * NULL + * Fix coding error. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000796] [Volunteer Patch][MT6620][Driver] Add BC deauth frame TX feature. + * BC deauth support. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * 1. Fix Service Disocvery Logical issue. + * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 21 2011 terry.wu + * [WCXRP00000381] [MT6620 Wi-Fi][Driver] Kernel panic when replying unaccept Auth in AP mode + * In AP mode, use STA_REC_INDEX_NOT_FOUND(0xFE) instead of StaRec index when replying an unaccept Auth frame. + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update authSendDeauthFrame() for correct the value of eNetTypeIndex in MSDU_INFO_T + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Check Net is active before sending Deauth frame. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Fix compile warning + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add debug message for abnormal authentication frame from AP + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * Fix the Debug Label + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update the authComposeAuthFrameHeader() + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the send deauth frame function + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Integrate send Auth with TXM + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +APPEND_IE_ENTRY_T txAuthIETable[] = { + {(ELEM_HDR_LEN + ELEM_MAX_LEN_CHALLENGE_TEXT), authAddIEChallengeText} +}; + +HANDLE_IE_ENTRY_T rxAuthIETable[] = { + {ELEM_ID_CHALLENGE_TEXT, authHandleIEChallengeText} +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Authentication frame header and fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2AuthAlgNum Authentication Algorithm Number +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[in] u2StatusCode Status Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +authComposeAuthFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], + IN UINT_16 u2AuthAlgNum, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Authentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_AUTH; + + /* If this frame is the third frame in the shared key authentication + * sequence, it shall be encrypted. + */ + if ((u2AuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3)) + u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; /* HW will also detect this bit for applying encryption */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2FrameCtrl, u2FrameCtrl); */ + prAuthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prAuthFrame->aucSrcAddr, aucMACAddress); + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucPeerMACAddress); + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + + /* Fill the BSSID field with Current BSSID. */ + COPY_MAC_ADDR(prAuthFrame->aucBSSID, aucMACAddress); + break; + + default: + ASSERT(0); + } + + /* Clear the SEQ/FRAG_NO field. */ + prAuthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ + /* Fill the Authentication Algorithm Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthAlgNum, u2AuthAlgNum); */ + prAuthFrame->u2AuthAlgNum = u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Authentication Transaction Sequence Number field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, u2TransactionSeqNum); */ + prAuthFrame->u2AuthTransSeqNo = u2TransactionSeqNum; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prAuthFrame->u2StatusCode, u2StatusCode); */ + prAuthFrame->u2StatusCode = u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of authComposeAuthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will append Challenge Text IE to the Authentication frame +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID authAddIEChallengeText(IN P_ADAPTER_T prAdapter, IN OUT P_MSDU_INFO_T prMsduInfo) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) + return; + + ASSERT(prStaRec); + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prMsduInfo->prPacket; + + WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) + + /* Only consider SEQ_3 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_3) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) && (prStaRec->prChallengeText != NULL)) { + + COPY_IE(((ULONG) (prMsduInfo->prPacket) + prMsduInfo->u2FrameLength), (prStaRec->prChallengeText)); + + prMsduInfo->u2FrameLength += IE_SIZE(prStaRec->prChallengeText); + } + + return; + +} /* end of authAddIEChallengeText() */ + +#if !CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authSendAuthFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN UINT_16 u2TransactionSeqNum) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_32 i; + + DBGLOG(SAA, LOUD, "Send Auth Frame\n"); + + ASSERT(prStaRec); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec->aucMacAddr, + prBssInfo->aucOwnMacAddr, + prStaRec->ucAuthAlgNum, u2TransactionSeqNum, STATUS_CODE_RESERVED); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = saaFsmRunEventTxDone; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Authentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#else + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Authenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendAuthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_SW_RFB_T prFalseAuthSwRfb, IN UINT_16 u2TransactionSeqNum, IN UINT_16 u2StatusCode) +{ + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + /*get from input parameter */ + /* ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; */ + PFN_TX_DONE_HANDLER pfTxDoneHandler = (PFN_TX_DONE_HANDLER) NULL; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedExtraIELen; + UINT_16 u2PayloadLen; + UINT_16 ucAuthAlgNum; + UINT_32 i; + + DBGLOG(SAA, LOUD, "Send Auth Frame %d, Status Code = %d\n", u2TransactionSeqNum, u2StatusCode); + + /* 4 <1> Allocate a PKT_INFO_T for Authentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) + u2EstimatedExtraIELen += txAuthIETable[i].u2EstimatedIELen; + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Auth Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Authentication Request frame header and fixed fields in MSDU_INfO_T. */ + if (prStaRec) { + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucReceiveAddr = prStaRec->aucMacAddr; + + ucAuthAlgNum = prStaRec->ucAuthAlgNum; + + switch (u2TransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: + pfTxDoneHandler = saaFsmRunEventTxDone; + break; + + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + pfTxDoneHandler = aaaFsmRunEventTxDone; + break; + } + + } else { /* For Error Status Code */ + P_WLAN_AUTH_FRAME_T prFalseAuthFrame; + + ASSERT(prFalseAuthSwRfb); + prFalseAuthFrame = (P_WLAN_AUTH_FRAME_T) prFalseAuthSwRfb->pvHeader; + + ASSERT(u2StatusCode != STATUS_CODE_SUCCESSFUL); + + pucTransmitAddr = prFalseAuthFrame->aucDestAddr; + + pucReceiveAddr = prFalseAuthFrame->aucSrcAddr; + + ucAuthAlgNum = prFalseAuthFrame->u2AuthAlgNum; + + u2TransactionSeqNum = (prFalseAuthFrame->u2AuthTransSeqNo + 1); + } + + /* Compose Header and some Fixed Fields */ + authComposeAuthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, + pucTransmitAddr, ucAuthAlgNum, u2TransactionSeqNum, u2StatusCode); + + u2PayloadLen = (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + if (prStaRec) + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + else + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; /* false Auth frame */ + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + for (i = 0; i < sizeof(txAuthIETable) / sizeof(APPEND_IE_ENTRY_T); i++) { + if (txAuthIETable[i].pfnAppendIE) + txAuthIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Authentication frame. */ + DBGLOG(SAA, INFO, "network: %d Send Auth Frame %d, Status Code = %d seq num %d\n", + eNetTypeIndex, u2TransactionSeqNum, u2StatusCode, prMsduInfo->ucTxSeqNum); + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendAuthFrame() */ + +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will strictly check the TX Authentication frame for SAA/AAA event +* handling. +* +* @param[in] prMsduInfo Pointer of MSDU_INFO_T +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authCheckTxAuthFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN UINT_16 u2TransactionSeqNum) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TxFrameCtrl; + UINT_16 u2TxAuthAlgNum; + UINT_16 u2TxTransactionSeqNum; + + ASSERT(prMsduInfo); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) (prMsduInfo->prPacket); + ASSERT(prAuthFrame); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2FrameCtrl, &u2TxFrameCtrl) */ + u2TxFrameCtrl = prAuthFrame->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + u2TxFrameCtrl &= MASK_FRAME_TYPE; + if (u2TxFrameCtrl != MAC_FRAME_AUTH) + return WLAN_STATUS_FAILURE; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2TxAuthAlgNum) */ + u2TxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + if (u2TxAuthAlgNum != (UINT_16) (prStaRec->ucAuthAlgNum)) + return WLAN_STATUS_FAILURE; + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TxTransactionSeqNum) */ + u2TxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + if (u2TxTransactionSeqNum != u2TransactionSeqNum) + return WLAN_STATUS_FAILURE; + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckTxAuthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Auth Frame's Transaction Sequence +* Number before delivering it to the corresponding SAA or AAA Module. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain authentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authCheckRxAuthFrameTransSeq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxTransactionSeqNum; + + ASSERT(prSwRfb); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Authentication Frame. */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < (AUTH_ALGORITHM_NUM_FIELD_LEN + + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + + STATUS_CODE_FIELD_LEN)) { + ASSERT(0); + return WLAN_STATUS_SUCCESS; + } + /* 4 <3> Parse the Fixed Fields of Authentication Frame Body. */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + + switch (u2RxTransactionSeqNum) { + case AUTH_TRANSACTION_SEQ_2: + case AUTH_TRANSACTION_SEQ_4: + saaFsmRunEventRxAuth(prAdapter, prSwRfb); + break; + + case AUTH_TRANSACTION_SEQ_1: + case AUTH_TRANSACTION_SEQ_3: +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAuth(prAdapter, prSwRfb); +#endif /* CFG_SUPPORT_AAA */ + break; + + default: + DBGLOG(SAA, WARN, "Strange Authentication Packet: Auth Trans Seq No = %d, Error Status Code = %d\n", + u2RxTransactionSeqNum, prAuthFrame->u2StatusCode); + break; + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameTransSeq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the incoming Authentication Frame and take +* the status code out. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] u2TransactionSeqNum Transaction Sequence Number +* @param[out] pu2StatusCode Pointer to store the Status Code from Authentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authCheckRxAuthFrameStatus(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN UINT_16 u2TransactionSeqNum, OUT PUINT_16 pu2StatusCode) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2RxAuthAlgNum; + UINT_16 u2RxTransactionSeqNum; + /* UINT_16 u2RxStatusCode; // NOTE(Kevin): Optimized for ARM */ + + ASSERT(prSwRfb); + ASSERT(pu2StatusCode); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Fixed Fields of Authentication Frame Body. */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthAlgNum, &u2RxAuthAlgNum); */ + u2RxAuthAlgNum = prAuthFrame->u2AuthAlgNum; /* NOTE(Kevin): Optimized for ARM */ + if (u2RxAuthAlgNum != (UINT_16) prStaRec->ucAuthAlgNum) { + DBGLOG(SAA, WARN, "Discard Auth frame with auth type = %d, current = %d\n", + u2RxAuthAlgNum, prStaRec->ucAuthAlgNum); + *pu2StatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + return WLAN_STATUS_SUCCESS; + } + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2RxTransactionSeqNum); */ + u2RxTransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + if (u2RxTransactionSeqNum != u2TransactionSeqNum) { + DBGLOG(SAA, WARN, "Discard Auth frame with Transaction Seq No = %d\n", u2RxTransactionSeqNum); + *pu2StatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + return WLAN_STATUS_SUCCESS; + } + /* 4 <3> Get the Status code */ + /* WLAN_GET_FIELD_16(&prAuthFrame->u2StatusCode, &u2RxStatusCode); */ + /* *pu2StatusCode = u2RxStatusCode; */ + *pu2StatusCode = prAuthFrame->u2StatusCode; /* NOTE(Kevin): Optimized for ARM */ + + return WLAN_STATUS_SUCCESS; + +} /* end of authCheckRxAuthFrameStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Challenge Text IE from the Authentication frame +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] prIEHdr Pointer to start address of IE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID authHandleIEChallengeText(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, P_IE_HDR_T prIEHdr) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + P_STA_RECORD_T prStaRec; + UINT_16 u2TransactionSeqNum; + + ASSERT(prSwRfb); + ASSERT(prIEHdr); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (!prStaRec) + return; + + /* For Management, frame header and payload are in a continuous buffer */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prAuthFrame->u2AuthTransSeqNo, &u2TransactionSeqNum) */ + u2TransactionSeqNum = prAuthFrame->u2AuthTransSeqNo; /* NOTE(Kevin): Optimized for ARM */ + + /* Only consider SEQ_2 for Challenge Text */ + if ((u2TransactionSeqNum == AUTH_TRANSACTION_SEQ_2) && + (prStaRec->ucAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY)) { + + /* Free previous allocated TCM memory */ + if (prStaRec->prChallengeText) { + ASSERT(0); + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + prStaRec->prChallengeText = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, IE_SIZE(prIEHdr)); + if (prStaRec->prChallengeText == NULL) + return; + + /* Save the Challenge Text from Auth Seq 2 Frame, before sending Auth Seq 3 Frame */ + COPY_IE(prStaRec->prChallengeText, prIEHdr); + } + + return; + +} /* end of authAddIEChallengeText() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authProcessRxAuth2_Auth4Frame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + PUINT_8 pucIEsBuffer; + UINT_16 u2IEsLen; + UINT_16 u2Offset; + UINT_8 ucIEID; + UINT_32 i; + + ASSERT(prSwRfb); + + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + pucIEsBuffer = &prAuthFrame->aucInfoElem[0]; + u2IEsLen = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (AUTH_ALGORITHM_NUM_FIELD_LEN + AUTH_TRANSACTION_SEQENCE_NUM_FIELD_LEN + STATUS_CODE_FIELD_LEN); + + IE_FOR_EACH(pucIEsBuffer, u2IEsLen, u2Offset) { + ucIEID = IE_ID(pucIEsBuffer); + + for (i = 0; i < (sizeof(rxAuthIETable) / sizeof(HANDLE_IE_ENTRY_T)); i++) { + + if (ucIEID == rxAuthIETable[i].ucElemID) + rxAuthIETable[i].pfnHandleIE(prAdapter, prSwRfb, (P_IE_HDR_T) pucIEsBuffer); + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth2_Auth4Frame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Deauthentication frame +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] aucPeerMACAddress Given Peer MAC Address. +* @param[in] aucMACAddress Given Our MAC Address. +* @param[in] u2StatusCode Status Code +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID +authComposeDeauthFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN UINT_8 aucPeerMACAddress[], + IN UINT_8 aucMACAddress[], IN UINT_8 aucBssid[], IN UINT_16 u2ReasonCode) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(aucPeerMACAddress); + ASSERT(aucMACAddress); + ASSERT(aucBssid); + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Deauthentication frame. */ + /* Fill the Frame Control field. */ + u2FrameCtrl = MAC_FRAME_DEAUTH; + + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2FrameCtrl, u2FrameCtrl); */ + prDeauthFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucDestAddr, aucPeerMACAddress); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prDeauthFrame->aucSrcAddr, aucMACAddress); + + /* Fill the BSSID field with Target BSSID. */ + COPY_MAC_ADDR(prDeauthFrame->aucBSSID, aucBssid); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prDeauthFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's fixed field part of the Authentication frame. */ + /* Fill the Status Code field. */ + /* WLAN_SET_FIELD_16(&prDeauthFrame->u2ReasonCode, u2ReasonCode); */ + prDeauthFrame->u2ReasonCode = u2ReasonCode; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of authComposeDeauthFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send the Deauthenticiation frame +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prClassErrSwRfb Pointer to the SW_RFB_T which is Class Error. +* @param[in] u2ReasonCode A reason code to indicate why to leave BSS. +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCES No available resource for frame composing. +* @retval WLAN_STATUS_SUCCESS Successfully send frame to TX Module +* @retval WLAN_STATUS_FAILURE Didn't send Deauth frame for various reasons. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authSendDeauthFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN P_SW_RFB_T prClassErrSwRfb, IN UINT_16 u2ReasonCode, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_WLAN_MAC_HEADER_A4_T prWlanMacHeader = NULL; + PUINT_8 pucReceiveAddr; + PUINT_8 pucTransmitAddr; + PUINT_8 pucBssid = NULL; + + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2RxFrameCtrl; + P_BSS_INFO_T prBssInfo; + + P_DEAUTH_INFO_T prDeauthInfo; + OS_SYSTIME rCurrentTime; + INT_32 i4NewEntryIndex, i; + UINT_8 ucStaRecIdx = STA_REC_INDEX_NOT_FOUND; + +#if CFG_ENABLE_WIFI_DIRECT + UINT_8 aucBMC[] = BC_MAC_ADDR; +#endif + + /* NOTE(Kevin): The best way to reply the Deauth is according to the incoming data + * frame + */ + /* 4 <1> Find the Receiver Address first. */ + if (prClassErrSwRfb) { + BOOLEAN fgIsAbleToSendDeauth = FALSE; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_A4_T) prClassErrSwRfb->pvHeader; + + /* WLAN_GET_FIELD_16(&prWlanMacHeader->u2FrameCtrl, &u2RxFrameCtrl); */ + u2RxFrameCtrl = prWlanMacHeader->u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* TODO(Kevin): Currently we won't send Deauth for IBSS node. How about DLS ? */ + if ((prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) == 0) + return WLAN_STATUS_FAILURE; + + /* Check if corresponding BSS is able to send Deauth */ + for (i = NETWORK_TYPE_AIS_INDEX; i < NETWORK_TYPE_INDEX_NUM; i++) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[i]); + + if (IS_NET_ACTIVE(prAdapter, i) && + (EQUAL_MAC_ADDR(prWlanMacHeader->aucAddr1, prBssInfo->aucOwnMacAddr))) { + { + fgIsAbleToSendDeauth = TRUE; + eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) i; + break; + } + } + } + + if (!fgIsAbleToSendDeauth) + return WLAN_STATUS_FAILURE; + + pucReceiveAddr = prWlanMacHeader->aucAddr2; + + } else if (prStaRec) { + + pucReceiveAddr = prStaRec->aucMacAddr; + } else { +#if CFG_ENABLE_WIFI_DIRECT + pucReceiveAddr = aucBMC; +#else + return WLAN_STATUS_FAILURE; +#endif + } + + /* 4 <2> Check if already send a Deauth frame in MIN_DEAUTH_INTERVAL_MSEC */ + GET_CURRENT_SYSTIME(&rCurrentTime); + + i4NewEntryIndex = -1; + for (i = 0; i < MAX_DEAUTH_INFO_COUNT; i++) { + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i]); + + /* For continuously sending Deauth frame, the minimum interval is + * MIN_DEAUTH_INTERVAL_MSEC. + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, + prDeauthInfo->rLastSendTime, MSEC_TO_SYSTIME(MIN_DEAUTH_INTERVAL_MSEC))) { + + i4NewEntryIndex = i; + } else if (EQUAL_MAC_ADDR(pucReceiveAddr, prDeauthInfo->aucRxAddr) && (!pfTxDoneHandler)) { + + return WLAN_STATUS_FAILURE; + } + } + + /* 4 <3> Update information. */ + if (i4NewEntryIndex > 0) { + + prDeauthInfo = &(prAdapter->rWifiVar.arDeauthInfo[i4NewEntryIndex]); + + COPY_MAC_ADDR(prDeauthInfo->aucRxAddr, pucReceiveAddr); + prDeauthInfo->rLastSendTime = rCurrentTime; + } else { + /* NOTE(Kevin): for the case of AP mode, we may encounter this case + * if deauth all the associated clients. + */ + DBGLOG(SAA, WARN, "No unused DEAUTH_INFO_T !\n"); + } + + /* 4 <4> Allocate a PKT_INFO_T for Deauthentication Frame */ + /* Init with MGMT Header Length + Length of Fixed Fields + IE Length */ + u2EstimatedFrameLen = (MAC_TX_RESERVED_FIELD + WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SAA, WARN, "No PKT_INFO_T for sending Deauth Request.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <5> Find the Transmitter Address and BSSID. */ + if (prClassErrSwRfb) { + + /* The TA of Deauth is the A1 of RX frame */ + pucTransmitAddr = prWlanMacHeader->aucAddr1; + + switch (prWlanMacHeader->u2FrameCtrl & MASK_TO_DS_FROM_DS) { + + case MASK_FC_FROM_DS: + /* The BSSID of Deauth is the A2 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + case MASK_FC_TO_DS: + /* The BSSID of Deauth is the A1 of RX frame */ + pucBssid = prWlanMacHeader->aucAddr1; + break; + + case MASK_TO_DS_FROM_DS: + /* TODO(Kevin): Consider BOW, now we set the BSSID of Deauth + * to the A2 of RX frame for temporary solution. + */ + pucBssid = prWlanMacHeader->aucAddr2; + break; + + /* No Default */ + } + + } else if (prStaRec) { + eNetTypeIndex = prStaRec->ucNetTypeIndex; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + } +#if CFG_ENABLE_WIFI_DIRECT + else { + if (prAdapter->fgIsP2PRegistered) { + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ucStaRecIdx = STA_REC_INDEX_BMCAST; + + pucTransmitAddr = prBssInfo->aucOwnMacAddr; + + pucBssid = prBssInfo->aucBSSID; + + eNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + } else { + /* 20130122: free packet by samplin */ + cnmMgtPktFree(prAdapter, prMsduInfo); + return WLAN_STATUS_FAILURE; + } + } + +#endif + + /* 4 <6> compose Deauthentication frame header and some fixed fields */ + authComposeDeauthFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucReceiveAddr, pucTransmitAddr, pucBssid, u2ReasonCode); + +#if CFG_SUPPORT_802_11W + if (rsnCheckBipKeyInstalled(prAdapter, prStaRec)) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + prDeauthFrame = + (P_WLAN_DEAUTH_FRAME_T) (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prDeauthFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + DBGLOG(TX, WARN, "authSendDeauthFrame with protection\n"); + } +#endif + + /* 4 <7> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = ((prStaRec == NULL) ? ucStaRecIdx : prStaRec->ucIndex); + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + REASON_CODE_FIELD_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + DBGLOG(SAA, INFO, "Sending Deauth, network: %d, seqNo %d\n", + eNetTypeIndex, prMsduInfo->ucTxSeqNum); + + /* 4 <8> Inform TXM to send this Deauthentication frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; +} /* end of authSendDeauthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Deauthentication frame +* if the given BSSID is matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucBSSID Given BSSID +* @param[out] pu2ReasonCode Pointer to store the Reason Code from Deauthentication. +* +* @retval WLAN_STATUS_FAILURE This is not the frame we should handle at current state. +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS authProcessRxDeauthFrame(IN P_SW_RFB_T prSwRfb, IN UINT_8 aucBSSID[], OUT PUINT_16 pu2ReasonCode) +{ + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + UINT_16 u2RxReasonCode; + + ASSERT(prSwRfb); + ASSERT(aucBSSID); + ASSERT(pu2ReasonCode); + + /* 4 <1> locate the Deauthentication Frame. */ + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Parse the Header of Deauthentication Frame. */ +#if 0 /* Kevin: Seems redundant */ + WLAN_GET_FIELD_16(&prDeauthFrame->u2FrameCtrl, &u2RxFrameCtrl) + u2RxFrameCtrl &= MASK_FRAME_TYPE; + if (u2RxFrameCtrl != MAC_FRAME_DEAUTH) + return WLAN_STATUS_FAILURE; +#endif + + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < REASON_CODE_FIELD_LEN) { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* Check if this Deauth Frame is coming from Target BSSID */ + if (UNEQUAL_MAC_ADDR(prDeauthFrame->aucBSSID, aucBSSID)) { + DBGLOG(SAA, LOUD, "Ignore Deauth Frame from other BSS [ %pM ]\n", + prDeauthFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <3> Parse the Fixed Fields of Deauthentication Frame Body. */ + WLAN_GET_FIELD_16(&prDeauthFrame->u2ReasonCode, &u2RxReasonCode); + *pu2ReasonCode = u2RxReasonCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxDeauthFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will parse and process the incoming Authentication frame. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] aucExpectedBSSID Given Expected BSSID. +* @param[in] u2ExpectedAuthAlgNum Given Expected Authentication Algorithm Number +* @param[in] u2ExpectedTransSeqNum Given Expected Transaction Sequence Number. +* @param[out] pu2ReturnStatusCode Return Status Code. +* +* @retval WLAN_STATUS_SUCCESS This is the frame we should handle. +* @retval WLAN_STATUS_FAILURE The frame we will ignore. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +authProcessRxAuth1Frame(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN UINT_8 aucExpectedBSSID[], + IN UINT_16 u2ExpectedAuthAlgNum, + IN UINT_16 u2ExpectedTransSeqNum, OUT PUINT_16 pu2ReturnStatusCode) +{ + P_WLAN_AUTH_FRAME_T prAuthFrame; + UINT_16 u2ReturnStatusCode = STATUS_CODE_SUCCESSFUL; + + ASSERT(prSwRfb); + ASSERT(aucExpectedBSSID); + ASSERT(pu2ReturnStatusCode); + + /* 4 <1> locate the Authentication Frame. */ + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + /* 4 <2> Check the BSSID */ + if (UNEQUAL_MAC_ADDR(prAuthFrame->aucBSSID, aucExpectedBSSID)) + return WLAN_STATUS_FAILURE; /* Just Ignore this MMPDU */ + /* 4 <3> Check the SA, which should not be MC/BC */ + if (prAuthFrame->aucSrcAddr[0] & BIT(0)) { + DBGLOG(P2P, WARN, "Invalid STA MAC with MC/BC bit set: %pM\n", + prAuthFrame->aucSrcAddr); + return WLAN_STATUS_FAILURE; + } + /* 4 <4> Parse the Fixed Fields of Authentication Frame Body. */ + if (prAuthFrame->u2AuthAlgNum != u2ExpectedAuthAlgNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_ALGORITHM_NOT_SUPPORTED; + + if (prAuthFrame->u2AuthTransSeqNo != u2ExpectedTransSeqNum) + u2ReturnStatusCode = STATUS_CODE_AUTH_OUT_OF_SEQ; + + *pu2ReturnStatusCode = u2ReturnStatusCode; + + return WLAN_STATUS_SUCCESS; + +} /* end of authProcessRxAuth1Frame() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c new file mode 100644 index 0000000000000..160779583655f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/bss.c @@ -0,0 +1,2521 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/bss.c#3 +*/ + +/*! \file "bss.c" + \brief This file contains the functions for creating BSS(AP)/IBSS(AdHoc). + + This file contains the functions for BSS(AP)/IBSS(AdHoc). We may create a BSS/IBSS + network, or merge with exist IBSS network and sending Beacon Frame or reply + the Probe Response Frame for received Probe Request Frame. +*/ + +/* +** Log: bss.c +** +** 09 03 2013 cp.wu +** add path for reassociation +** +** 08 30 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 14 2012 chinglan.wang + * NULL + * Fix the losing of the HT IE in assoc request.. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 08 2012 yuche.tsai + * NULL + * Fix FW assert when start Hot-Spot. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 20 2012 chinglan.wang + * 03 02 2012 terry.wu + * NULL + * Fix the WPA-PSK TKIP and WPA2-PSK AES security mode bug. + * + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 15 2012 yuche.tsai + * NULL + * Fix wrong basic rate issue. + * + * 01 13 2012 yuche.tsai + * NULL + * WiFi Hot Spot Tethering for ICS ALPHA testing version. + * + * 11 03 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Always set short slot time to TRUE initially in AP mode + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 09 14 2011 yuche.tsai + * NULL + * Add P2P IE in assoc response. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 29 2011 eddie.chen + * [WCXRP00000608] [MT6620 Wi-Fi][DRV] Change wmm parameters in beacon + * Change wmm parameters in beacon. + * + * 03 29 2011 yuche.tsai + * [WCXRP00000607] [Volunteer Patch][MT6620][Driver] Coding Style Fix for klocwork scan. + * Fix klocwork issue. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Make assoc req to append P2P IE if wifi direct is enabled. + * + * 03 11 2011 chinglan.wang + * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. + * . + * + * 03 03 2011 george.huang + * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated + * . + * + * 03 03 2011 george.huang + * [WCXRP00000508] [MT6620 Wi-Fi][Driver] aware of beacon MSDU will be free, after BSS deactivated + * modify to handle if beacon MSDU been released when BSS deactivated + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 03 02 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * Add code to send beacon and probe response WSC IE at Auto GO. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Change GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 12 2011 yuche.tsai + * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. + * bss should create station record type according to callers input. + * + * 02 11 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * In p2p link function, check networktype before calling p2p function. + * + * 02 11 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Modify p2p link function to avoid assert. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 25 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Fix the compile error in windows. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 24 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * .Fix typo and missing entry + * + * 12 30 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Fix prBssInfo->aucCWminLog to prBssInfo->aucCWminLogForBcast + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, + +Add per station flow control when STA is in PS + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC + * for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 29 2010 yuche.tsai + * NULL + * Finish SLT TX/RX & Rate Changing Support. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 16 2010 yuche.tsai + * NULL + * Before composing Beacon IE, assign network type index for msdu info, + * this information is needed by RLM module while composing some RLM related IE field. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Fix undefined pucDestAddr in bssUpdateBeaconContent() + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 08 02 2010 george.huang + * NULL + * add WMM-PS test related OID/ CMD handlers + * + * 07 26 2010 yuche.tsai + * + * Add support to RX probe response for P2P. + * + * 07 20 2010 cp.wu + * + * 1) bugfix: do not stop timer for join after switched into normal_tr state, for providing chance for DHCP handshasking + * 2) modify rsnPerformPolicySelection() invoking + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * when IBSS is being merged-in, send command packet to PM for connected indication + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error while enable WIFI_DIRECT support. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct when ADHOC support is turned on. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * auth.c is migrated. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fix compilation error when WIFI_DIRECT is turned on + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add bss.c. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add ClientList handling API - bssClearClientList, bssAddStaRecToClientList + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update bssProcessProbeRequest() to avoid redundant SSID IE {0,0} for IOT. + * + * 05 21 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine txmInitWtblTxRateTable() - set TX initial rate according to AP's operation rate set + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Use TX MGMT Frame API for sending PS NULL frame to avoid the TX Burst Mechanism in TX FW Frame API + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Separate Beacon and ProbeResp IE array + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed the use of compiling flag MQM_WMM_PARSING + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 20 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Fix restart Beacon Timeout Func after connection diagnosis + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * adding the wpa-none for ibss beacon. + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the protected bit at cap info for ad-hoc. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename the CFG flags + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Update outgoing beacon's TX data rate + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add DTIM count update while TX Beacon + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify code due to define - BAND_24G and specific BSS_INFO_T was changed + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +APPEND_VAR_IE_ENTRY_T txBcnIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE}, /* 50 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE}, /* 42 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE}, /* 45 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE}, /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE}, /* 74 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE}, /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE}, /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE}, /* 221 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWPAIE}, /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE}, /* 48 */ +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ + {0, p2pFuncCalculateExtra_IELenForBeacon, p2pFuncGenerateExtra_IEForBeacon}, /* 221 */ +#else + {0, p2pFuncCalculateP2p_IELenForBeacon, p2pFuncGenerateP2p_IEForBeacon}, /* 221 */ + {0, p2pFuncCalculateWSC_IELenForBeacon, p2pFuncGenerateWSC_IEForBeacon}, /* 221 */ + {0, p2pFuncCalculateP2P_IE_NoA, p2pFuncGenerateP2P_IE_NoA}, /* 221 */ +#endif +#endif /* CFG_ENABLE_WIFI_DIRECT */ +}; + +APPEND_VAR_IE_ENTRY_T txProbRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE}, /* 50 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE}, /* 42 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE}, /* 45 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE}, /* 61 */ +#if CFG_ENABLE_WIFI_DIRECT + {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE}, /* 48 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE}, /* 74 */ +#endif + {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE}, /* 127 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE}, /* 221 */ + {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} /* 221 */ +}; + +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines for all Operation Modes */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will create or reset a STA_RECORD_T by given BSS_DESC_T for +* Infrastructure or AdHoc Mode. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eStaType Assign STA Type for this STA_RECORD_T +* @param[in] eNetTypeIndex Assign Net Type Index for this STA_RECORD_T +* @param[in] prBssDesc Received Beacon/ProbeResp from this STA +* +* @retval Pointer to STA_RECORD_T +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T +bssCreateStaRecFromBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_STA_TYPE_T eStaType, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_BSS_DESC_T prBssDesc) +{ + P_STA_RECORD_T prStaRec; + UINT_8 ucNonHTPhyTypeSet; + + ASSERT(prBssDesc); + + /* 4 <1> Get a valid STA_RECORD_T */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); + if (!prStaRec) { + + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) eNetTypeIndex); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + + if (!prStaRec) { + ASSERT(FALSE); + return NULL; + } + + ASSERT(prStaRec); + + prStaRec->ucStaState = STA_STATE_1; + prStaRec->ucJoinFailureCount = 0; + /* TODO(Kevin): If this is an old entry, we may also reset the ucJoinFailureCount to 0. + */ + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prBssDesc->aucSrcAddr); + } + /* 4 <2> Setup STA TYPE and NETWORK */ + prStaRec->eStaType = eStaType; + + prStaRec->ucNetTypeIndex = eNetTypeIndex; + + /* 4 <3> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + prStaRec->u2CapInfo = prBssDesc->u2CapInfo; + + prStaRec->u2OperationalRateSet = prBssDesc->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prBssDesc->u2BSSBasicRateSet; + + prStaRec->ucPhyTypeSet = prBssDesc->ucPhyTypeSet; + if (IS_STA_IN_AIS(prStaRec)) { + if (!((prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_KEY_ABSENT) || + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION_DISABLED) || + (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) || (prAdapter->prGlueInfo->u2WapiAssocInfoIESz))) { + DBGLOG(BSS, TRACE, "Ignore the HT Bit for TKIP as pairwise cipher configured!\n"); + prStaRec->ucPhyTypeSet &= ~PHY_TYPE_BIT_HT; + } + } else { + DBGLOG(BSS, TRACE, "P2P skip TKIP limitation for HT Hit!\n"); + } + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prAdapter->rWifiVar.ucAvailablePhyTypeSet; + + ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; + + /* Check for Target BSS's non HT Phy Types */ + if (ucNonHTPhyTypeSet) { + + if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = TRUE; + } else { + /* Use mandatory for 11N only BSS */ + ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); + + { + /* TODO(Kevin): which value should we set for 11n ? ERP ? */ + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = FALSE; + } + + /* Update non HT Desired Rate Set */ + { + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + } + + /* 4 <4> Update information from BSS_DESC_T to current P_STA_RECORD_T */ + if (IS_AP_STA(prStaRec)) { + /* do not need to parse IE for DTIM, + * which have been parsed before inserting into BSS_DESC_T + */ + if (prBssDesc->ucDTIMPeriod) + prStaRec->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + else + prStaRec->ucDTIMPeriod = 0; /* Means that TIM was not parsed. */ + } + /* 4 <5> Update default value */ + prStaRec->fgDiagnoseConnection = FALSE; + + /* 4 <6> Update default value for other Modules */ + /* Determine fgIsWmmSupported and fgIsUapsdSupported in STA_REC */ + mqmProcessScanResult(prAdapter, prBssDesc, prStaRec); + + return prStaRec; + +} /* end of bssCreateStaRecFromBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssComposeNullFrame(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec) +{ + P_WLAN_MAC_HEADER_T prNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prNullFrame = (P_WLAN_MAC_HEADER_T) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ + u2FrameCtrl = MAC_FRAME_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) + u2FrameCtrl |= MASK_FC_PWR_MGT; + } else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } else { + /* NOTE(Kevin): We won't send Null frame for IBSS */ + ASSERT(0); + return; + } + + /* 4 <2> Compose the Null frame */ + /* Fill the Frame Control field. */ + /* WLAN_SET_FIELD_16(&prNullFrame->u2FrameCtrl, u2FrameCtrl); */ + prNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prNullFrame->u2SeqCtrl = 0; + + return; + +} /* end of bssComposeNullFrameHeader() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the QoS Null Data frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* @param[in] ucUP User Priority. +* @param[in] fgSetEOSP Set the EOSP bit. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuffer, IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN BOOLEAN fgSetEOSP) +{ + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + P_BSS_INFO_T prBssInfo; + UINT_16 u2FrameCtrl; + UINT_16 u2QosControl; + + ASSERT(pucBuffer); + ASSERT(prStaRec); + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo); + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) pucBuffer; + + /* 4 <1> Decide the Frame Control Field */ + u2FrameCtrl = MAC_FRAME_QOS_NULL; + + if (IS_AP_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_TO_DS; + + if (prStaRec->fgSetPwrMgtBit) + u2FrameCtrl |= MASK_FC_PWR_MGT; + } else if (IS_CLIENT_STA(prStaRec)) { + u2FrameCtrl |= MASK_FC_FROM_DS; + } else if (IS_DLS_STA(prStaRec)) { + /* TODO(Kevin) */ + } else { + /* NOTE(Kevin): We won't send QoS Null frame for IBSS */ + ASSERT(0); + return; + } + + /* 4 <2> Compose the QoS Null frame */ + /* Fill the Frame Control field. */ + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2FrameCtrl, u2FrameCtrl); */ + prQoSNullFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Address 1 field with Target Peer Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr1, prStaRec->aucMacAddr); + + /* Fill the Address 2 field with our MAC Address. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr2, prBssInfo->aucOwnMacAddr); + + /* Fill the Address 3 field with Target BSSID. */ + COPY_MAC_ADDR(prQoSNullFrame->aucAddr3, prBssInfo->aucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prQoSNullFrame->u2SeqCtrl = 0; + + u2QosControl = (UINT_16) (ucUP & WMM_QC_UP_MASK); + + if (fgSetEOSP) + u2QosControl |= WMM_QC_EOSP; + /* WLAN_SET_FIELD_16(&prQoSNullFrame->u2QosCtrl, u2QosControl); */ + prQoSNullFrame->u2QosCtrl = u2QosControl; /* NOTE(Kevin): Optimized for ARM */ + + return; + +} /* end of bssComposeQoSNullFrameHeader() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Succe]ss. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendNullFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeNullFrame(prAdapter, (PUINT_8) ((ULONG) prMsduInfo->prPacket + MAC_TX_RESERVED_FIELD), prStaRec); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */ , + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */ , + /* Resource TC */ 0 /* Irrelevant */ , + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */ , + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ BSS_DEFAULT_CONN_TEST_NULL_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */ , + /* ACL SN */ 0 /* Irrelevant */ , + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendNullFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the QoS Null Frame +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] pfTxDoneHandler TX Done call back function +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUP, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, FALSE); +#if 0 + /* 4 <3> Update information of MSDU_INFO_T */ + TXM_SET_DATA_PACKET( + /* STA_REC ptr */ prStaRec, + /* MSDU_INFO ptr */ prMsduInfo, + /* MAC HDR ptr */ (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD), + /* MAC HDR length */ WLAN_MAC_HEADER_QOS_LEN, + /* PAYLOAD ptr */ + (prMsduInfo->pucBuffer + MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN), + /* PAYLOAD length */ 0, + /* Network Type Index */ (UINT_8) prStaRec->ucNetTypeIndex, + /* TID */ 0 /* BE: AC1 */ , + /* Flag 802.11 */ TRUE, + /* Pkt arrival time */ 0 /* TODO: Obtain the system time */ , + /* Resource TC */ 0 /* Irrelevant */ , + /* Flag 802.1x */ FALSE, + /* TX-done callback */ pfTxDoneHandler, + /* PS forwarding type */ PS_FORWARDING_TYPE_NON_PS, + /* PS Session ID */ 0 /* Irrelevant */ , + /* Flag fixed rate */ TRUE, + /* Fixed tx rate */ g_aprBssInfo[prStaRec->ucNetTypeIndex]->ucHwDefaultFixedRateCode, + /* Fixed-rate retry */ TXM_DEFAULT_DATA_FRAME_RETRY_LIMIT, + /* PAL LLH */ 0 /* Irrelevant */ , + /* ACL SN */ 0 /* Irrelevant */ , + /* Flag No Ack */ FALSE + ); + + /* Terminate with a NULL pointer */ + NIC_HIF_TX_SET_NEXT_MSDU_INFO(prMsduInfo, NULL); + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* Indicate the packet to TXM */ + /* 4 <4> Inform TXM to send this Null frame. */ + txmSendFwDataPackets(prMsduInfo); +#endif + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendQoSNullFrame() */ + +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) +/*----------------------------------------------------------------------------*/ +/* Routines for both IBSS(AdHoc) and BSS(AP) */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate Information Elements of Extended +* Support Rate +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssGenerateExtSuppRate_IE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + PUINT_8 pucBuffer; + UINT_8 ucExtSupRatesLen; + + ASSERT(prMsduInfo); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + ucExtSupRatesLen = prBssInfo->ucAllSupportedRatesLen - ELEM_MAX_LEN_SUP_RATES; + else + ucExtSupRatesLen = 0; + + /* Fill the Extended Supported Rates element. */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pucBuffer)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pucBuffer)->aucExtSupportedRates, + &prBssInfo->aucAllSupportedRates[ELEM_MAX_LEN_SUP_RATES], ucExtSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* end of bssGenerateExtSuppRate_IE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for Beacon +* or Probe Response Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssBuildBeaconProbeRespFrameCommonIEs(IN P_MSDU_INFO_T prMsduInfo, IN P_BSS_INFO_T prBssInfo, IN PUINT_8 pucDestAddr) +{ + PUINT_8 pucBuffer; + UINT_8 ucSupRatesLen; + + ASSERT(prMsduInfo); + ASSERT(prBssInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + ASSERT(pucBuffer); + + /* Compose the frame body of the Probe Response frame. */ + /* 4 <1> Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + if (prBssInfo->eHiddenSsidType == ENUM_HIDDEN_SSID_LEN) { + if ((!pucDestAddr) && /* For Beacon only */ + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + SSID_IE(pucBuffer)->ucLength = 0; + } else { /* Probe response */ + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + } else { + SSID_IE(pucBuffer)->ucLength = prBssInfo->ucSSIDLen; + if (prBssInfo->ucSSIDLen) + kalMemCopy(SSID_IE(pucBuffer)->aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + } + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + /* 4 <2> Fill the Supported Rates element. */ + if (prBssInfo->ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) + ucSupRatesLen = ELEM_MAX_LEN_SUP_RATES; + else + ucSupRatesLen = prBssInfo->ucAllSupportedRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pucBuffer)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pucBuffer)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pucBuffer)->aucSupportedRates, prBssInfo->aucAllSupportedRates, ucSupRatesLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <3> Fill the DS Parameter Set element. */ + if (prBssInfo->eBand == BAND_2G4) { + DS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_DS_PARAM_SET; + DS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_DS_PARAMETER_SET; + DS_PARAM_IE(pucBuffer)->ucCurrChnl = prBssInfo->ucPrimaryChannel; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <4> IBSS Parameter Set element, ID: 6 */ + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + IBSS_PARAM_IE(pucBuffer)->ucId = ELEM_ID_IBSS_PARAM_SET; + IBSS_PARAM_IE(pucBuffer)->ucLength = ELEM_MAX_LEN_IBSS_PARAMETER_SET; + WLAN_SET_FIELD_16(&(IBSS_PARAM_IE(pucBuffer)->u2ATIMWindow), prBssInfo->u2ATIMWindow); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + } + /* 4 <5> TIM element, ID: 5 */ + if ((!pucDestAddr) && /* For Beacon only. */ + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + +#if CFG_ENABLE_WIFI_DIRECT + /*no fgIsP2PRegistered protect */ + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { +#if 0 + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_8 ucBitmapControl = 0; + UINT_32 u4N1, u4N2; + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Clear existing value. */ + prP2pSpecificBssInfo->ucBitmapCtrl = 0; + kalMemZero(prP2pSpecificBssInfo->aucPartialVirtualBitmap, + sizeof(prP2pSpecificBssInfo->aucPartialVirtualBitmap)); + + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucDTIMCount = prBssInfo->ucDTIMCount; + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + + /* Setup DTIM Count for next TBTT. */ + if (prBssInfo->ucDTIMCount == 0) { + /*Do nothing*/ + /* 3 *** pmQueryBufferedBCAST(); */ + } + /* 3 *** pmQueryBufferedPSNode(); */ + /* TODO(Kevin): Call PM Module here to loop all STA_RECORD_Ts and it + * will call bssSetTIMBitmap to toggle the Bitmap. + */ + + /* Set Virtual Bitmap for UCAST */ + u4N1 = (prP2pSpecificBssInfo->u2SmallestAID >> 4) << 1; /* Find the largest even number. */ + u4N2 = prP2pSpecificBssInfo->u2LargestAID >> 3; /* Find the smallest number. */ + + ASSERT(u4N2 >= u4N1); + + kalMemCopy(TIM_IE(pucBuffer)->aucPartialVirtualMap, + &prP2pSpecificBssInfo->aucPartialVirtualBitmap[u4N1], ((u4N2 - u4N1) + 1)); + + /* Set Virtual Bitmap for BMCAST */ + /* BMC bit only indicated when DTIM count == 0. */ + if (prBssInfo->ucDTIMCount == 0) + ucBitmapControl = prP2pSpecificBssInfo->ucBitmapCtrl; + TIM_IE(pucBuffer)->ucBitmapControl = ucBitmapControl | (UINT_8) u4N1; + + TIM_IE(pucBuffer)->ucLength = ((u4N2 - u4N1) + 4); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); +#else + + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP); /*((u4N2 - u4N1) + 4) */ + /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucDTIMCount = 0; /*prBssInfo->ucDTIMCount */ + TIM_IE(pucBuffer)->ucDTIMPeriod = prBssInfo->ucDTIMPeriod; + /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucBitmapControl = 0; /*ucBitmapControl | (UINT_8)u4N1 */ + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +#endif + + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + /* NOTE(Kevin): 1. AIS - Didn't Support AP Mode. + * 2. BOW - Didn't Support BCAST and PS. + */ + } + + } + +} /* end of bssBuildBeaconProbeRespFrameCommonIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Beacon/Probe Response frame header and +* its fixed fields. +* +* @param[in] pucBuffer Pointer to the frame buffer. +* @param[in] pucDestAddr Pointer to the Destination Address, if NULL, means Beacon. +* @param[in] pucOwnMACAddress Given Our MAC Address. +* @param[in] pucBSSID Given BSSID of the BSS. +* @param[in] u2BeaconInterval Given Beacon Interval. +* @param[in] u2CapInfo Given Capability Info. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +bssComposeBeaconProbeRespFrameHeaderAndFF(IN PUINT_8 pucBuffer, + IN PUINT_8 pucDestAddr, + IN PUINT_8 pucOwnMACAddress, + IN PUINT_8 pucBSSID, IN UINT_16 u2BeaconInterval, IN UINT_16 u2CapInfo) +{ + P_WLAN_BEACON_FRAME_T prBcnProbRspFrame; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + UINT_16 u2FrameCtrl; + + DEBUGFUNC("bssComposeBeaconProbeRespFrameHeaderAndFF"); + /* DBGLOG(INIT, LOUD, ("\n")); */ + + ASSERT(pucBuffer); + ASSERT(pucOwnMACAddress); + ASSERT(pucBSSID); + + prBcnProbRspFrame = (P_WLAN_BEACON_FRAME_T) pucBuffer; + + /* 4 <1> Compose the frame header of the Beacon /ProbeResp frame. */ + /* Fill the Frame Control field. */ + if (pucDestAddr) { + u2FrameCtrl = MAC_FRAME_PROBE_RSP; + } else { + u2FrameCtrl = MAC_FRAME_BEACON; + pucDestAddr = aucBCAddr; + } + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2FrameCtrl, u2FrameCtrl); */ + prBcnProbRspFrame->u2FrameCtrl = u2FrameCtrl; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the DA field with BCAST MAC ADDR or TA of ProbeReq. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucDestAddr, pucDestAddr); + + /* Fill the SA field with our MAC Address. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucSrcAddr, pucOwnMACAddress); + + /* Fill the BSSID field with current BSSID. */ + COPY_MAC_ADDR(prBcnProbRspFrame->aucBSSID, pucBSSID); + + /* Clear the SEQ/FRAG_NO field(HW won't overide the FRAG_NO, so we need to clear it). */ + prBcnProbRspFrame->u2SeqCtrl = 0; + + /* 4 <2> Compose the frame body's common fixed field part of the Beacon /ProbeResp frame. */ + /* MAC will update TimeStamp field */ + + /* Fill the Beacon Interval field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2BeaconInterval, u2BeaconInterval); */ + prBcnProbRspFrame->u2BeaconInterval = u2BeaconInterval; /* NOTE(Kevin): Optimized for ARM */ + + /* Fill the Capability Information field. */ + /* WLAN_SET_FIELD_16(&prBcnProbRspFrame->u2CapInfo, u2CapInfo); */ + prBcnProbRspFrame->u2CapInfo = u2CapInfo; /* NOTE(Kevin): Optimized for ARM */ + +} /* end of bssComposeBeaconProbeRespFrameHeaderAndFF() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the Beacon Frame Template to FW for AIS AdHoc and P2P GO. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssUpdateBeaconContent(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_WLAN_BEACON_FRAME_T prBcnFrame; + UINT_32 i; + + DEBUGFUNC("bssUpdateBeaconContent"); + DBGLOG(BSS, LOUD, "\n"); + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + /* 4 <1> Allocate a PKT_INFO_T for Beacon Frame */ + /* Allocate a MSDU_INFO_T */ + /* For Beacon */ + prMsduInfo = prBssInfo->prBeacon; + + /* beacon prMsduInfo will be NULLify once BSS deactivated, so skip if it is */ + if (prMsduInfo == NULL) + return WLAN_STATUS_SUCCESS; + /* 4 <2> Compose header */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + NULL, + prBssInfo->aucOwnMacAddr, + prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + + prMsduInfo->ucNetworkType = eNetTypeIndex; + + /* 4 <3> Compose the frame body's Common IEs of the Beacon frame. */ + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, NULL); + + /* 4 <4> Compose IEs in MSDU_INFO_T */ + + /* Append IE for Beacon */ + for (i = 0; i < sizeof(txBcnIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); i++) { + if (txBcnIETable[i].pfnAppendIE) + txBcnIETable[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + prBcnFrame = (P_WLAN_BEACON_FRAME_T) prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + eNetTypeIndex, + prBssInfo->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem)); + +} /* end of bssUpdateBeaconContent() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send the Beacon Frame(for BOW) or Probe Response Frame according to the given +* Destination Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eNetTypeIndex Specify which network reply the Probe Response. +* @param[in] pucDestAddr Pointer to the Destination Address to reply +* @param[in] u4ControlFlags Control flags for information on Probe Response. +* +* @retval WLAN_STATUS_RESOURCE No available resources to send frame. +* @retval WLAN_STATUS_SUCCESS Success. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +bssSendBeaconProbeResponse(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN PUINT_8 pucDestAddr, IN UINT_32 u4ControlFlags) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + UINT_16 u2EstimatedFixedIELen; + UINT_16 u2EstimatedExtraIELen; + P_APPEND_VAR_IE_ENTRY_T prIeArray = NULL; + UINT_32 u4IeArraySize = 0; + UINT_32 i; + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (!pucDestAddr) { /* For Beacon */ + prIeArray = &txBcnIETable[0]; + u4IeArraySize = sizeof(txBcnIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + } else { + prIeArray = &txProbRspIETable[0]; + u4IeArraySize = sizeof(txProbRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + } + + /* 4 <1> Allocate a PKT_INFO_T for Beacon /Probe Response Frame */ + /* Allocate a MSDU_INFO_T */ + + /* Init with MGMT Header Length + Length of Fixed Fields + Common IE Fields */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + + WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_IBSS_PARAMETER_SET) + (ELEM_HDR_LEN + (3 + MAX_LEN_TIM_PARTIAL_BMP)); + + /* + Extra IE Length */ + u2EstimatedExtraIELen = 0; + + for (i = 0; i < u4IeArraySize; i++) { + u2EstimatedFixedIELen = prIeArray[i].u2EstimatedFixedIELen; + + if (u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += u2EstimatedFixedIELen; + } else { + ASSERT(prIeArray[i].pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += (UINT_16) + prIeArray[i].pfnCalculateVariableIELen(prAdapter, eNetTypeIndex, NULL); + } + } + + u2EstimatedFrameLen += u2EstimatedExtraIELen; + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(BSS, WARN, "No PKT_INFO_T for sending %s.\n", ((!pucDestAddr) ? "Beacon" : "Probe Response")); + return WLAN_STATUS_RESOURCES; + } + /* 4 <2> Compose Beacon/Probe Response frame header and fixed fields in MSDU_INfO_T. */ + /* Compose Header and Fixed Field */ +#if CFG_ENABLE_WIFI_DIRECT + if (u4ControlFlags & BSS_PROBE_RESP_USE_P2P_DEV_ADDR) { + if (prAdapter->fgIsP2PRegistered) { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + + MAC_TX_RESERVED_FIELD), pucDestAddr, + prAdapter->rWifiVar.aucDeviceAddress, + prAdapter->rWifiVar.aucDeviceAddress, + DOT11_BEACON_PERIOD_DEFAULT, + (prBssInfo->u2CapInfo & + ~(CAP_INFO_ESS | CAP_INFO_IBSS))); + } + } else +#endif /* CFG_ENABLE_WIFI_DIRECT */ + { + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + pucDestAddr, prBssInfo->aucOwnMacAddr, prBssInfo->aucBSSID, + prBssInfo->u2BeaconInterval, prBssInfo->u2CapInfo); + } + + /* 4 <3> Update information of MSDU_INFO_T */ + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = (UINT_8) eNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + + /* 4 <4> Compose the frame body's Common IEs of the Beacon/ProbeResp frame. */ + bssBuildBeaconProbeRespFrameCommonIEs(prMsduInfo, prBssInfo, pucDestAddr); + + /* 4 <5> Compose IEs in MSDU_INFO_T */ + + /* Append IE */ + for (i = 0; i < u4IeArraySize; i++) { + if (prIeArray[i].pfnAppendIE) + prIeArray[i].pfnAppendIE(prAdapter, prMsduInfo); + } + + /* TODO(Kevin): Also release the unused tail room of the composed MMPDU */ + + /* 4 <6> Inform TXM to send this Beacon /Probe Response frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return WLAN_STATUS_SUCCESS; + +} /* end of bssSendBeaconProbeResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Probe Request Frame and then send +* back the corresponding Probe Response Frame if the specified conditions +* were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + UINT_8 aucBCBSSID[] = BC_BSSID; + BOOLEAN fgIsBcBssid; + BOOLEAN fgReplyProbeResp; + UINT_32 u4CtrlFlagsForProbeResp = 0; + ENUM_BAND_T eBand; + UINT_8 ucHwChannelNum; + + ASSERT(prSwRfb); + + /* 4 <1> Parse Probe Req and Get BSSID */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + if (EQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID)) + fgIsBcBssid = TRUE; + else + fgIsBcBssid = FALSE; + + /* 4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) */ + for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) + continue; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if ((!fgIsBcBssid) && UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) + continue; + + eBand = HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr); + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + + if (prBssInfo->eBand != eBand) + continue; + + if (prBssInfo->ucPrimaryChannel != ucHwChannelNum) + continue; + + fgReplyProbeResp = FALSE; + + if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { + +#if CFG_SUPPORT_ADHOC + fgReplyProbeResp = aisValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex)) { + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + fgReplyProbeResp = + p2pFuncValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); + } + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) + fgReplyProbeResp = bowValidateProbeReq(prAdapter, prSwRfb, &u4CtrlFlagsForProbeResp); +#endif + + if (fgReplyProbeResp) { + if (nicTxGetFreeCmdCount(prAdapter) > (CFG_TX_MAX_CMD_PKT_NUM / 2)) { + /* Resource margin is enough */ + bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr, + u4CtrlFlagsForProbeResp); + } + } + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ + +#if 0 /* NOTE(Kevin): condition check should move to P2P_FSM.c */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Probe Request Frame and then send +* back the corresponding Probe Response Frame if the specified conditions +* were matched. +* +* @param[in] prSwRfb Pointer to SW RFB data structure. +* +* @retval WLAN_STATUS_SUCCESS Always return success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS bssProcessProbeRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr; + P_BSS_INFO_T prBssInfo; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + UINT_8 aucBCBSSID[] = BC_BSSID; + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + BOOLEAN fgReplyProbeResp; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgP2PTargetDeviceFound; + UINT_8 aucP2PWildcardSSID[] = P2P_WILDCARD_SSID; +#endif + + ASSERT(prSwRfb); + + /* 4 <1> Parse Probe Req and Get SSID IE ptr */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + u2IELength = prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen; + pucIE = (PUINT_8) ((UINT_32) prSwRfb->pvHeader + prSwRfb->u2HeaderLen); + + prIeSsid = (P_IE_SSID_T) NULL; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) + prIeSsid = (P_IE_SSID_T) pucIE; + break; + + case ELEM_ID_SUP_RATES: + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SUP_RATES) { */ + if (IE_LEN(pucIE) <= RATE_NUM) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + +#if CFG_ENABLE_WIFI_DIRECT + /* TODO: P2P IE & WCS IE parsing for P2P. */ + case ELEM_ID_P2P: + + break; +#endif + + /* no default */ + } + } /* end of IE_FOR_EACH */ + + /* 4 <2> Check network conditions before reply Probe Response Frame (Consider Concurrent) */ + for (eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; eNetTypeIndex < NETWORK_TYPE_INDEX_NUM; eNetTypeIndex++) { + + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) + continue; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (UNEQUAL_MAC_ADDR(aucBCBSSID, prMgtHdr->aucBSSID) && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prMgtHdr->aucBSSID)) { + /* BSSID not Wildcard BSSID. */ + continue; + } + + fgReplyProbeResp = FALSE; + + if (NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + + /* TODO(Kevin): Check if we are IBSS Master. */ + if (TRUE && prIeSsid) { + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (NETWORK_TYPE_P2P_INDEX == eNetTypeIndex) { + + /* TODO(Kevin): Move following lines to p2p_fsm.c */ + + if ((prIeSsid) && + ((prIeSsid->ucLength == BC_SSID_LEN) || + (EQUAL_SSID(aucP2PWildcardSSID, + P2P_WILDCARD_SSID_LEN, prIeSsid->aucSSID, prIeSsid->ucLength)))) { + /* if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prMgtHdr->aucSrcAddr, + pucIE, u2IELength)) { */ + if (p2pFsmRunEventRxProbeRequestFrame(prAdapter, prSwRfb)) { + /* Extand channel request time & cancel scan request. */ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + /* TODO: RX probe request may not caused by LISTEN state. */ + /* TODO: It can be GO. */ + /* Generally speaking, cancel a non-exist scan request is fine. + * We can check P2P FSM here for only LISTEN state. + */ + + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + /* Abort JOIN process. */ + prScanCancelMsg = + (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + ASSERT(0); /* Can't abort SCN FSM */ + continue; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucSeqNum = prP2pFsmInfo->ucSeqNumOfScnMsg; + prScanCancelMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->fgIsChannelExt = TRUE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); + } + } else { + /* 1. Probe Request without SSID. + * 2. Probe Request with SSID not Wildcard SSID & not P2P Wildcard SSID. + */ + continue; + } + +#if 0 /* Frog */ + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_LISTEN) { + /* P2P 2.4.1 - P2P Devices shall not respond to Probe Request frames + which only contain 11b rates only. */ + if (prIeSupportedRate || prIeExtSupportedRate) { + UINT_16 u2OperationalRateSet, u2BSSBasicRateSet; + BOOLEAN fgIsUnknownBssBasicRate; + + rateGetRateSetFromIEs(prIeSupportedRate, prIeExtSupportedRate, + &u2OperationalRateSet, + &u2BSSBasicRateSet, /* Ignore any Basic Bit */ + &fgIsUnknownBssBasicRate); + + if (u2OperationalRateSet & ~RATE_SET_HR_DSSS) + continue; + } + } + /* TODO: Check channel time before first check point to: */ + /* If Target device is selected: + * 1. Send XXXX request frame. + * else + * 1. Send Probe Response frame. + */ + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* TODO(Kevin): During PROVISION state, can we reply Probe Response ? */ + + /* TODO(Kevin): + * If we are GO, accept legacy client --> accept Wildcard SSID + * If we are in Listen State, accept only P2P Device --> check P2P IE and WPS IE + */ + if (TRUE /* We are GO */ && prIeSsid) { + UINT_8 aucSSID[] = P2P_WILDCARD_SSID; + + if ((prIeSsid->ucLength == BC_SSID_LEN) || /* WILDCARD SSID */ + EQUAL_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, + prIeSsid->aucSSID, prIeSsid->ucLength) || + EQUAL_SSID(aucSSID, P2P_WILDCARD_SSID_LEN, + prIeSsid->aucSSID, prIeSsid->ucLength)) { + fgReplyProbeResp = TRUE; + } + } +/* else if (FALSE) { */ /* We are in Listen State */ +/* } */ + + /* TODO(Kevin): Check P2P IE and WPS IE */ + } +#endif + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (NETWORK_TYPE_BOW_INDEX == eNetTypeIndex) { + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* Do nothing */ + /* TODO(Kevin): TBD */ + } + } +#endif + else + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + if (fgReplyProbeResp) + bssSendBeaconProbeResponse(prAdapter, eNetTypeIndex, prMgtHdr->aucSrcAddr); + + } + + return WLAN_STATUS_SUCCESS; + +} /* end of bssProcessProbeRequest() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to clear the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssClearClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prPeerStaRec; + + LINK_FOR_EACH_ENTRY(prPeerStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + cnmStaRecChangeState(prAdapter, prPeerStaRec, STA_STATE_1); + } + + LINK_INITIALIZE(prStaRecOfClientList); + } + +} /* end of bssClearClientList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Add a STA_RECORD_T to the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Given related BSS_INFO_T. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssAddStaRecToClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + DBGLOG(BSS, WARN, + "Current Client List already contains that STA_RECORD_T[%pM]\n", + prStaRec->aucMacAddr); + return; + } + } + } + + LINK_INSERT_TAIL(prStaRecOfClientList, &prStaRec->rLinkEntry); + +} /* end of bssAddStaRecToClientList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to Remove a STA_RECORD_T from the client list for AdHoc or AP Mode +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssRemoveStaRecFromClientList(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_STA_RECORD_T prStaRec) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + +#if 0 + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + + if (prCurrStaRec == prStaRec) { + + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prStaRec->rLinkEntry); + + return; + } + } + } +#endif + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((ULONG) prStaRec == (ULONG) prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prStaRec->rLinkEntry); + return; + } + } + } + + DBGLOG(BSS, INFO, "Current Client List didn't contain that STA_RECORD_T[%pM] before removing.\n", + prStaRec->aucMacAddr); + +} /* end of bssRemoveStaRecFromClientList() */ +#endif /* CFG_SUPPORT_ADHOC || CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get station record by Address for AP mode +* +* @param[in] prBssInfo Pointer to BSS_INFO_T. +* @param[in] pucMacAddr Pointer to target mac address +* +* @return pointer of STA_RECORD_T if found, otherwise, return NULL +*/ +/*----------------------------------------------------------------------------*/ + +P_STA_RECORD_T bssGetClientByAddress(IN P_BSS_INFO_T prBssInfo, PUINT_8 pucMacAddr) +{ + P_LINK_T prStaRecOfClientList; + + ASSERT(prBssInfo); + ASSERT(pucMacAddr); + + prStaRecOfClientList = &prBssInfo->rStaRecOfClientList; + if (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_FOR_EACH_ENTRY(prCurrStaRec, prStaRecOfClientList, rLinkEntry, STA_RECORD_T) { + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, pucMacAddr)) + return prCurrStaRec; + } + } + return NULL; +} + +#if CFG_SUPPORT_ADHOC +/*----------------------------------------------------------------------------*/ +/* Routines for IBSS(AdHoc) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to process Beacons from current Ad-Hoc network peers. +* We also process Beacons from other Ad-Hoc network during SCAN. If it has +* the same SSID and we'll decide to merge into it if it has a larger TSF. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +ibssProcessMatchedBeacon(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_BSS_DESC_T prBssDesc, IN UINT_8 ucRCPI) +{ + P_STA_RECORD_T prStaRec = NULL; + + BOOLEAN fgIsCheckCapability = FALSE; + BOOLEAN fgIsCheckTSF = FALSE; + BOOLEAN fgIsGoingMerging = FALSE; + BOOLEAN fgIsSameBSSID; + + ASSERT(prBssInfo); + ASSERT(prBssDesc); + + /* 4 <1> Process IBSS Beacon only after we create or merge with other IBSS. */ + if (!prBssInfo->fgIsBeaconActivated) + return; + /* 4 <2> Get the STA_RECORD_T of TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prBssDesc->aucSrcAddr); + + fgIsSameBSSID = UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID) ? FALSE : TRUE; + + /* 4 <3> IBSS Merge Decision Flow for Processing Beacon. */ + if (fgIsSameBSSID) { + + /* Same BSSID: + * Case I. This is a new TA and it has decide to merged with us. + * a) If fgIsMerging == FALSE - we will send msg to notify AIS. + * b) If fgIsMerging == TRUE - already notify AIS. + * Case II. This is an old TA and we've already merged together. + */ + if (!prStaRec) { + + /* For Case I - Check this IBSS's capability first before adding this Sta Record. */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + + } else { + + ASSERT((prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) && IS_ADHOC_STA(prStaRec)); + + if (prStaRec->ucStaState != STA_STATE_3) { + + if (!prStaRec->fgIsMerging) { + + /* For Case I - Check this IBSS's capability first + * before adding this Sta Record. */ + fgIsCheckCapability = TRUE; + + /* If check is passed, then we perform merging with this new IBSS */ + fgIsGoingMerging = TRUE; + } else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + } else { + /* For Case II - Update rExpirationTime of Sta Record */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + } + + } + } else { + + /* Unequal BSSID: + * Case III. This is a new TA and we need to compare the TSF and get the winner. + * Case IV. This is an old TA and it merge into a new IBSS before we do the same thing. + * We need to compare the TSF to get the winner. + * Case V. This is an old TA and it restart a new IBSS. We also need to + * compare the TSF to get the winner. + */ + + /* For Case III, IV & V - We'll always check this new IBSS's capability first + * before merging into new IBSS. + */ + fgIsCheckCapability = TRUE; + + /* If check is passed, we need to perform TSF check to decide the major BSSID */ + fgIsCheckTSF = TRUE; + + /* For Case IV & V - We won't update rExpirationTime of Sta Record */ + } + + /* 4 <7> Check this BSS_DESC_T's capability. */ + if (fgIsCheckCapability) { + BOOLEAN fgIsCapabilityMatched = FALSE; + + do { + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Unsupported Phy.\n", + prBssDesc->aucSrcAddr); + + break; + } + + if (prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Unknown Basic Rate.\n", + prBssDesc->aucSrcAddr); + + break; + } + + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", + prBssDesc->aucSrcAddr); + + break; + } + + fgIsCapabilityMatched = TRUE; + } while (FALSE); + + if (!fgIsCapabilityMatched) { + + if (prStaRec) { + /* For Case II - We merge this STA_RECORD in RX Path. + * Case IV & V - They change their BSSID after we merge with them. + */ + + DBGLOG(BSS, LOUD, + "IBSS MERGE: Ignore Peer MAC: %pM - Capability is not matched.\n", + prBssDesc->aucSrcAddr); + } + + return; + } + + DBGLOG(BSS, LOUD, + "IBSS MERGE: Peer MAC: %pM - Check capability was passed.\n", + prBssDesc->aucSrcAddr); + } + + if (fgIsCheckTSF) { +#if CFG_SLT_SUPPORT + fgIsGoingMerging = TRUE; +#else + if (prBssDesc->fgIsLargerTSF) + fgIsGoingMerging = TRUE; + else + return; +#endif + } + + if (fgIsGoingMerging) { + P_MSG_AIS_IBSS_PEER_FOUND_T prAisIbssPeerFoundMsg; + + /* 4 <1> We will merge with to this BSS immediately. */ + prBssDesc->fgIsConnecting = TRUE; + prBssDesc->fgIsConnected = FALSE; + + /* 4 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + STA_TYPE_ADHOC_PEER, NETWORK_TYPE_AIS_INDEX, prBssDesc); + + if (!prStaRec) { + /* no memory ? */ + return; + } + + prStaRec->fgIsMerging = TRUE; + + /* update RCPI */ + prStaRec->ucRCPI = ucRCPI; + + /* 4 <3> Send Merge Msg to CNM to obtain the channel privilege. */ + prAisIbssPeerFoundMsg = (P_MSG_AIS_IBSS_PEER_FOUND_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_AIS_IBSS_PEER_FOUND_T)); + + if (!prAisIbssPeerFoundMsg) { + + ASSERT(0); /* Can't send Merge Msg */ + return; + } + + prAisIbssPeerFoundMsg->rMsgHdr.eMsgId = MID_SCN_AIS_FOUND_IBSS; + prAisIbssPeerFoundMsg->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_AIS_INDEX; + prAisIbssPeerFoundMsg->prStaRec = prStaRec; + + /* Inform AIS to do STATE TRANSITION + * For Case I - If AIS in IBSS_ALONE, let it jump to NORMAL_TR after we know the new member. + * For Case III, IV - Now this new BSSID wins the TSF, follow it. + */ + if (fgIsSameBSSID) { + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; + } else { +#if CFG_SLT_SUPPORT + prAisIbssPeerFoundMsg->fgIsMergeIn = TRUE; +#else + prAisIbssPeerFoundMsg->fgIsMergeIn = (prBssDesc->fgIsLargerTSF) ? FALSE : TRUE; +#endif + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prAisIbssPeerFoundMsg, MSG_SEND_METHOD_BUF); + + } + +} /* end of ibssProcessMatchedBeacon() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the Capability for Ad-Hoc to decide if we are +* able to merge with(same capability). +* +* @param[in] prBSSDesc Pointer to the BSS Descriptor. +* +* @retval WLAN_STATUS_FAILURE Can't pass the check of Capability. +* @retval WLAN_STATUS_SUCCESS Pass the check of Capability. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS ibssCheckCapabilityForAdHocMode(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + + ASSERT(prBssDesc); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + do { + /* 4 <1> Check the BSS Basic Rate Set for current AdHoc Mode */ + if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11B) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_HR_DSSS)) { + break; + } else if ((prConnSettings->eAdHocMode == AD_HOC_MODE_11A) && + (prBssDesc->u2BSSBasicRateSet & ~RATE_SET_OFDM)) { + break; + } + /* 4 <2> Check the Short Slot Time. */ +#if 0 /* Do not check ShortSlotTime until Wi-Fi define such policy */ + if (prConnSettings->eAdHocMode == AD_HOC_MODE_11G) { + if (((prConnSettings->fgIsShortSlotTimeOptionEnable) && + !(prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) || + (!(prConnSettings->fgIsShortSlotTimeOptionEnable) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME))) { + break; + } + } +#endif + + /* 4 <3> Check the ATIM window setting. */ + if (prBssDesc->u2ATIMWindow) { + DBGLOG(BSS, INFO, "AdHoc PS was not supported(ATIM Window: %d)\n", prBssDesc->u2ATIMWindow); + break; + } +#if CFG_RSN_MIGRATION + /* 4 <4> Check the Security setting. */ + if (!rsnPerformPolicySelection(prAdapter, prBssDesc)) + break; +#endif + + rStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rStatus; + +} /* end of ibssCheckCapabilityForAdHocMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for IBSS Mode. +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID ibssInitForAdHoc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLowestBasicRateIndex; + UINT_8 aucBSSID[MAC_ADDR_LEN]; + PUINT_16 pu2BSSID = (PUINT_16) &aucBSSID[0]; + UINT_32 i; + + ASSERT(prBssInfo); + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_IBSS); + + /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTAdHocModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + + /* 4 <2> Setup BSSID */ + if (!prBssInfo->fgHoldSameBssidForIBSS) { + + for (i = 0; i < sizeof(aucBSSID) / sizeof(UINT_16); i++) + pu2BSSID[i] = (UINT_16) (kalRandomNumber() & 0xFFFF); + + aucBSSID[0] &= ~0x01; /* 7.1.3.3.3 - The individual/group bit of the address is set to 0. */ + aucBSSID[0] |= 0x02; /* 7.1.3.3.3 - The universal/local bit of the address is set to 1. */ + + COPY_MAC_ADDR(prBssInfo->aucBSSID, aucBSSID); + } + /* 4 <3> Setup Capability - Short Preamble */ + if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO))) { + prBssInfo->fgIsShortPreambleAllowed = TRUE; + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + + /* 4 <4> Setup Capability - Short Slot Time */ + /* 7.3.1.4 For IBSS, the Short Slot Time subfield shall be set to 0. */ + prBssInfo->fgUseShortSlotTime = FALSE; /* Set to FALSE for AdHoc */ + + /* 4 <5> Compoase Capability */ + prBssInfo->u2CapInfo = CAP_INFO_IBSS; + + if (prBssInfo->fgIsProtection) + prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; + + if (prBssInfo->fgIsShortPreambleAllowed) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + + if (prBssInfo->fgUseShortSlotTime) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + + prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + +} /* end of ibssInitForAdHoc() */ + +#endif /* CFG_SUPPORT_ADHOC */ + +#if CFG_SUPPORT_AAA + +/*----------------------------------------------------------------------------*/ +/* Routines for BSS(AP) only */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial the BSS_INFO_T for AP Mode. +* +* @param[in] prBssInfo Given related BSS_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssInitForAP(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN BOOLEAN fgIsRateUpdate) +{ + UINT_8 ucLowestBasicRateIndex; + + P_AC_QUE_PARMS_T prACQueParms; + + ENUM_WMM_ACI_T eAci; + + UINT_8 auCWminLog2ForBcast[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/ }; + UINT_8 auCWmaxLog2ForBcast[WMM_AC_INDEX_NUM] = { 10, 10, 4, 3 }; + UINT_8 auAifsForBcast[WMM_AC_INDEX_NUM] = { 3, 7, 2, 2 }; + UINT_8 auTxopForBcast[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ + + UINT_8 auCWminLog2[WMM_AC_INDEX_NUM] = { 4 /*BE*/, 4 /*BK*/, 3 /*VO*/, 2 /*VI*/ }; + UINT_8 auCWmaxLog2[WMM_AC_INDEX_NUM] = { 7, 10, 4, 3 }; + UINT_8 auAifs[WMM_AC_INDEX_NUM] = { 3, 7, 1, 1 }; + UINT_8 auTxop[WMM_AC_INDEX_NUM] = { 0, 0, 94, 47 }; /* If the AP is OFDM */ + + DEBUGFUNC("bssInitForAP"); + DBGLOG(BSS, LOUD, "\n"); + + ASSERT(prBssInfo); + ASSERT((prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || (prBssInfo->eCurrentOPMode == OP_MODE_BOW)); + +#if 0 + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = CONFIG_BW_20M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = CONFIG_BW_20M; +#endif + + /* 4 <1> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prBssInfo->u2OperationalRateSet = rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + if (fgIsRateUpdate) { + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, &prBssInfo->ucAllSupportedRatesLen); + } + /* 4 <2> Setup BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssInfo->aucOwnMacAddr); + + /* 4 <3> Setup Capability - Short Preamble */ + if (rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].fgIsShortPreambleOptionImplemented && + ((prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_SHORT) || /* Short Preamble Option Enable is TRUE */ + (prAdapter->rWifiVar.ePreambleType == PREAMBLE_TYPE_AUTO))) { + prBssInfo->fgIsShortPreambleAllowed = TRUE; + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + + /* 4 <4> Setup Capability - Short Slot Time */ + prBssInfo->fgUseShortSlotTime = TRUE; + + /* 4 <5> Compoase Capability */ + prBssInfo->u2CapInfo = CAP_INFO_ESS; + + if (prBssInfo->fgIsProtection) + prBssInfo->u2CapInfo |= CAP_INFO_PRIVACY; + + if (prBssInfo->fgIsShortPreambleAllowed) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_PREAMBLE; + + if (prBssInfo->fgUseShortSlotTime) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + /* 4 <6> Find Lowest Basic Rate Index for default TX Rate of MMPDU */ + rateGetLowestRateIndexFromRateSet(prBssInfo->u2BSSBasicRateSet, &ucLowestBasicRateIndex); + + prBssInfo->ucHwDefaultFixedRateCode = aucRateIndex2RateCode[PREAMBLE_DEFAULT_LONG_NONE][ucLowestBasicRateIndex]; + + /* 4 <7> Fill the EDCA */ + + prACQueParms = prBssInfo->arACQueParmsForBcast; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].fgIsACMSet = FALSE; + prACQueParms[eAci].u2Aifsn = auAifsForBcast[eAci]; + prACQueParms[eAci].u2CWmin = BIT(auCWminLog2ForBcast[eAci]) - 1; + prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2ForBcast[eAci]) - 1; + prACQueParms[eAci].u2TxopLimit = auTxopForBcast[eAci]; + + prBssInfo->aucCWminLog2ForBcast[eAci] = auCWminLog2ForBcast[eAci]; /* used to send WMM IE */ + prBssInfo->aucCWmaxLog2ForBcast[eAci] = auCWmaxLog2ForBcast[eAci]; + + DBGLOG(BSS, INFO, "Bcast: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prACQueParms[eAci].fgIsACMSet, + prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, + prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); + + } + + prACQueParms = prBssInfo->arACQueParms; + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prACQueParms[eAci].fgIsACMSet = FALSE; + prACQueParms[eAci].u2Aifsn = auAifs[eAci]; + prACQueParms[eAci].u2CWmin = BIT(auCWminLog2[eAci]) - 1; + prACQueParms[eAci].u2CWmax = BIT(auCWmaxLog2[eAci]) - 1; + prACQueParms[eAci].u2TxopLimit = auTxop[eAci]; + + DBGLOG(BSS, INFO, "eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prACQueParms[eAci].fgIsACMSet, + prACQueParms[eAci].u2Aifsn, + prACQueParms[eAci].u2CWmin, + prACQueParms[eAci].u2CWmax, prACQueParms[eAci].u2TxopLimit); + } + + /* Note: Caller should update the EDCA setting to HW by nicQmUpdateWmmParms() it there is no AIS network */ + /* Note: In E2, only 4 HW queues. The the Edca parameters should be folow by AIS network */ + /* Note: In E3, 8 HW queues. the Wmm parameters should be updated to right queues according to BSS */ + +} /* end of bssInitForAP() */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update DTIM Count +* +* @param[in] eNetTypeIndex Specify which network to update +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssUpdateDTIMCount(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(eNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + /* Setup DTIM Count for next TBTT. */ + if (prBssInfo->ucDTIMCount > 0) { + prBssInfo->ucDTIMCount--; + } else { + + ASSERT(prBssInfo->ucDTIMPeriod > 0); + + prBssInfo->ucDTIMCount = prBssInfo->ucDTIMPeriod - 1; + } + } + +} /* end of bssUpdateDTIMIE() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to set the Virtual Bitmap in TIM Information Elements +* +* @param[in] prBssInfo Pointer to the BSS_INFO_T. +* @param[in] u2AssocId The association id to set in Virtual Bitmap. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID bssSetTIMBitmap(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN UINT_16 u2AssocId) +{ + + ASSERT(prBssInfo); + + if (prBssInfo->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + prP2pSpecificBssInfo = &(prAdapter->rWifiVar.rP2pSpecificBssInfo); + + /* Use Association ID == 0 for BMCAST indication */ + if (u2AssocId == 0) { + + prP2pSpecificBssInfo->ucBitmapCtrl |= (UINT_8) BIT(0); + } else { + PUINT_8 pucPartialVirtualBitmap; + UINT_8 ucBitmapToSet; + + /* (u2AssocId / 8) */ + pucPartialVirtualBitmap = &prP2pSpecificBssInfo->aucPartialVirtualBitmap[(u2AssocId >> 3)]; + ucBitmapToSet = (UINT_8) BIT((u2AssocId % 8)); + + if (*pucPartialVirtualBitmap & ucBitmapToSet) { + /* The virtual bitmap has been set */ + return; + } + + *pucPartialVirtualBitmap |= ucBitmapToSet; + + /* Update u2SmallestAID and u2LargestAID */ + if ((u2AssocId < prP2pSpecificBssInfo->u2SmallestAID) || + (prP2pSpecificBssInfo->u2SmallestAID == 0)) { + prP2pSpecificBssInfo->u2SmallestAID = u2AssocId; + } + + if ((u2AssocId > prP2pSpecificBssInfo->u2LargestAID) || + (prP2pSpecificBssInfo->u2LargestAID == 0)) { + prP2pSpecificBssInfo->u2LargestAID = u2AssocId; + } + } + } + +} /* end of bssSetTIMBitmap() */ +#endif + +#endif /* CFG_SUPPORT_AAA */ + +VOID bssCreateStaRecFromAuth(IN P_ADAPTER_T prAdapter) +{ + +} + +VOID bssUpdateStaRecFromAssocReq(IN P_ADAPTER_T prAdapter) +{ + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c new file mode 100644 index 0000000000000..39af02df2af29 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm.c @@ -0,0 +1,738 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm.c#2 +*/ + +/*! \file "cnm.c" + \brief Module of Concurrent Network Management + + Module of Concurrent Network Management +*/ + +/* +** Log: cnm.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Fix possible wrong message when P2P is unregistered + * + * 11 14 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Fix large network type index assert in FW issue. + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 01 2011 cm.chang + * [WCXRP00001077] [All Wi-Fi][Driver] Fix wrong preferred channel for AP and BOW + * Only check AIS channel for P2P and BOW + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Extension channel of some 5G AP will not follow regulation requirement + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * . + * + * 09 01 2011 cm.chang + * [WCXRP00000937] [MT6620 Wi-Fi][Driver][FW] cnm.c line #848 assert when doing monkey test + * Print message only in Linux platform for monkey testing + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Limit AIS to fixed channel same with BOW + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Check if P2P network index is Tethering AP + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 02 17 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * When P2P registried, invoke BOW deactivate function + * + * 01 12 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Provide function to decide if BSS can be activated or not + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 10 13 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when cmd buffer is not available + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Fix wrong message ID for channel grant to requester + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set 20/40M bandwidth of AP HT OP before association process + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 21 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support TCP/UDP/IP Checksum offload feature + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add a new function to send abort message + * + * 04 27 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * BMC mac address shall be ignored in basic config command + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support change of MAC address by host command + * + * 04 16 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * adding the wpa-none for ibss beacon. + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix bug for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 25 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * use the Rx0 dor event indicate. + * + * 02 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support partial part about cmd basic configuration + * + * Dec 10 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove conditional compiling FPGA_V5 + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add function cnmFsmEventInit() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmInit(P_ADAPTER_T prAdapter) +{ + +} /* end of cnmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in CNM_INFO_T. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmUninit(P_ADAPTER_T prAdapter) +{ + +} /* end of cnmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before handle the message from other module, it need to obtain +* the Channel privilege from Channel Manager +* +* @param[in] prMsgHdr The message need to be handled. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrRequestPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_CH_REQ_T prMsgChReq; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChReq = (P_MSG_CH_REQ_T) prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, "ChReq: fail to get buf (net=%d, token=%d)\n", + prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, "ChReq net=%d token=%d b=%d c=%d s=%d\n", + prMsgChReq->ucNetTypeIndex, prMsgChReq->ucTokenID, + prMsgChReq->eRfBand, prMsgChReq->ucPrimaryChannel, prMsgChReq->eRfSco); + + prCmdBody->ucNetTypeIndex = prMsgChReq->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChReq->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_REQ; /* Request */ + prCmdBody->ucPrimaryChannel = prMsgChReq->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prMsgChReq->eRfSco; + prCmdBody->ucRfBand = (UINT_8) prMsgChReq->eRfBand; + prCmdBody->ucReqType = (UINT_8) prMsgChReq->eReqType; + prCmdBody->ucReserved = 0; + prCmdBody->u4MaxInterval = prMsgChReq->u4MaxInterval; + COPY_MAC_ADDR(prCmdBody->aucBSSID, prMsgChReq->aucBSSID); + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) + DBGLOG(CNM, ERROR, "CNM: ChReq with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of cnmChMngrRequestPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Before deliver the message to other module, it need to release +* the Channel privilege to Channel Manager. +* +* @param[in] prMsgHdr The message need to be delivered +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrAbortPrivilege(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_CH_ABORT_T prMsgChAbort; + P_CMD_CH_PRIVILEGE_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prMsgChAbort = (P_MSG_CH_ABORT_T) prMsgHdr; + + prCmdBody = (P_CMD_CH_PRIVILEGE_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_CH_PRIVILEGE_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(CNM, ERROR, "ChAbort: fail to get buf (net=%d, token=%d)\n", + prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); + + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(CNM, INFO, "ChAbort net=%d token=%d\n", prMsgChAbort->ucNetTypeIndex, prMsgChAbort->ucTokenID); + + prCmdBody->ucNetTypeIndex = prMsgChAbort->ucNetTypeIndex; + prCmdBody->ucTokenID = prMsgChAbort->ucTokenID; + prCmdBody->ucAction = CMD_CH_ACTION_ABORT; /* Abort */ + + ASSERT(prCmdBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + /* For monkey testing 20110901 */ + if (prCmdBody->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) + DBGLOG(CNM, ERROR, "CNM: ChAbort with wrong netIdx=%d\n\n", prCmdBody->ucNetTypeIndex); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_CH_PRIVILEGE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_CH_PRIVILEGE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); + cnmMemFree(prAdapter, prMsgHdr); + +} /* end of cnmChMngrAbortPrivilege() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmChMngrHandleChEvent(P_ADAPTER_T prAdapter, P_WIFI_EVENT_T prEvent) +{ + P_EVENT_CH_PRIVILEGE_T prEventBody; + P_MSG_CH_GRANT_T prChResp; + + ASSERT(prAdapter); + ASSERT(prEvent); + + prEventBody = (P_EVENT_CH_PRIVILEGE_T) (prEvent->aucBuffer); + prChResp = (P_MSG_CH_GRANT_T) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_GRANT_T)); + ASSERT(prChResp); + + /* To do: exception handle */ + if (!prChResp) { + DBGLOG(CNM, ERROR, "ChGrant: fail to get buf (net=%d, token=%d)\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID); + + return; + } + + DBGLOG(CNM, INFO, "ChGrant net=%d token=%d ch=%d sco=%d\n", + prEventBody->ucNetTypeIndex, prEventBody->ucTokenID, + prEventBody->ucPrimaryChannel, prEventBody->ucRfSco); + + ASSERT(prEventBody->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventBody->ucStatus == EVENT_CH_STATUS_GRANT); + + /* Decide message ID based on network and response status */ + if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) + prChResp->rMsgHdr.eMsgId = MID_CNM_AIS_CH_GRANT; +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (prEventBody->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) + prChResp->rMsgHdr.eMsgId = MID_CNM_P2P_CH_GRANT; +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prEventBody->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + prChResp->rMsgHdr.eMsgId = MID_CNM_BOW_CH_GRANT; +#endif + else { + cnmMemFree(prAdapter, prChResp); + return; + } + + prChResp->ucNetTypeIndex = prEventBody->ucNetTypeIndex; + prChResp->ucTokenID = prEventBody->ucTokenID; + prChResp->ucPrimaryChannel = prEventBody->ucPrimaryChannel; + prChResp->eRfSco = (ENUM_CHNL_EXT_T) prEventBody->ucRfSco; + prChResp->eRfBand = (ENUM_BAND_T) prEventBody->ucRfBand; + prChResp->eReqType = (ENUM_CH_REQ_TYPE_T) prEventBody->ucReqType; + prChResp->u4GrantInterval = prEventBody->u4GrantInterval; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prChResp, MSG_SEND_METHOD_BUF); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked for P2P or BOW networks +* +* @param (none) +* +* @return TRUE: suggest to adopt the returned preferred channel +* FALSE: No suggestion. Caller should adopt its preference +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +cnmPreferredChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel, P_ENUM_CHNL_EXT_T prBssSCO) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prBand); + ASSERT(pucPrimaryChannel); + ASSERT(prBssSCO); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + *prBssSCO = prBssInfo->eBssSCO; + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: available channel is limited to return value +* FALSE: no limited +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmAisInfraChannelFixed(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) +{ +#if CFG_ENABLE_WIFI_DIRECT || (CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL) + P_BSS_INFO_T prBssInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { + + ASSERT(prAdapter->fgIsP2PRegistered); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_LIMIT_AIS_CHNL + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + *prBand = prBssInfo->eBand; + *pucPrimaryChannel = prBssInfo->ucPrimaryChannel; + + return TRUE; + } +#endif + + return FALSE; +} + +#if CFG_P2P_LEGACY_COEX_REVISE +BOOLEAN cnmAisDetectP2PChannel(P_ADAPTER_T prAdapter, P_ENUM_BAND_T prBand, PUINT_8 pucPrimaryChannel) +{ + P_WIFI_VAR_T prWifiVar = &prAdapter->rWifiVar; + P_BSS_INFO_T prP2PBssInfo = &prWifiVar->arBssInfo[NETWORK_TYPE_P2P_INDEX]; +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX) && + (prP2PBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED || + (prP2PBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && prP2PBssInfo->eIntendOPMode == OP_MODE_NUM))) { + *prBand = prP2PBssInfo->eBand; + *pucPrimaryChannel = prP2PBssInfo->ucPrimaryChannel; +#if CFG_SUPPORT_MCC + if (nicFreq2ChannelNum(prWifiVar->rConnSettings.u4FreqInKHz * 1000) != *pucPrimaryChannel) { + DBGLOG(CNM, INFO, "p2p is running on Channel %d, but supplicant try to run as MCC\n", + *pucPrimaryChannel); + return FALSE; + } +#endif + DBGLOG(CNM, INFO, "p2p is running on Channel %d, supplicant try to run as SCC\n", + *pucPrimaryChannel); + return TRUE; + } +#endif + return FALSE; +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmAisInfraConnectNotify(P_ADAPTER_T prAdapter) +{ +#if CFG_ENABLE_BT_OVER_WIFI + P_BSS_INFO_T prAisBssInfo, prBowBssInfo; + + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prBowBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + if (RLM_NET_PARAM_VALID(prAisBssInfo) && RLM_NET_PARAM_VALID(prBowBssInfo)) { + if (prAisBssInfo->eBand != prBowBssInfo->eBand || + prAisBssInfo->ucPrimaryChannel != prBowBssInfo->ucPrimaryChannel) { + + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmAisIbssIsPermitted(P_ADAPTER_T prAdapter) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) + return FALSE; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) + return FALSE; +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmP2PIsPermitted(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; +#if CFG_ENABLE_BT_OVER_WIFI + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_BOW_INDEX)) { + /* Notify BOW to do deactivation */ + bowNotifyAllLinkDisconnected(prAdapter); + } +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBowIsPermitted(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + if (IS_BSS_ACTIVE(prBssInfo) && prBssInfo->eCurrentOPMode == OP_MODE_IBSS) + return FALSE; +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) + return FALSE; +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param (none) +* +* @return TRUE: permitted +* FALSE: Not permitted +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN cnmBss40mBwPermitted(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 i; + P_BSS_DESC_T prBssDesc = NULL; + + /* Note: To support real-time decision instead of current activated-time, + * the STA roaming case shall be considered about synchronization + * problem. Another variable fgAssoc40mBwAllowed is added to + * represent HT capability when association + */ + for (i = 0; i < NETWORK_TYPE_INDEX_NUM; i++) { + if (i != (UINT_8) eNetTypeIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[i]; + + if (IS_BSS_ACTIVE(prBssInfo) && (prBssInfo->fg40mBwAllowed || prBssInfo->fgAssoc40mBwAllowed)) + return FALSE; + } + } + + if (eNetTypeIdx == NETWORK_TYPE_AIS_INDEX) + prBssDesc = prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc; + else if ((eNetTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->rWifiVar.prP2pFsmInfo)) + prBssDesc = prAdapter->rWifiVar.prP2pFsmInfo->prTargetBss; + if (prBssDesc) { +#if (CFG_FORCE_USE_20BW == 1) + if (prBssDesc->eBand == BAND_2G4) + return FALSE; +#endif + if (prBssDesc->eSco == CHNL_EXT_SCN) + return FALSE; + } + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c new file mode 100644 index 0000000000000..05bd0ff35f7ac --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_mem.c @@ -0,0 +1,1236 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_mem.c#2 +*/ + +/*! \file "cnm_mem.c" + \brief This file contain the management function of packet buffers and + generic memory alloc/free functioin for mailbox message. + + A data packet has a fixed size of buffer, but a management + packet can be equipped with a variable size of buffer. +*/ + +/* +** Log: cnm_mem.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 14 2012 wh.su + * [WCXRP00001173] [MT6620 Wi-Fi][Driver] Adding the ICS Tethering WPA2-PSK supporting + * Add code from 2.2 + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * initialize fgNeedResp. + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 11 29 2010 cm.chang + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC + * for initial TX rate selection of auto-rate algorithm + * Sync RCPI of STA_REC to FW as reference of initial TX rate + * + * 11 25 2010 yuche.tsai + * NULL + * Update SLT Function for QoS Support and not be affected by fixed rate function. + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete + * and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 10 13 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when cmd buffer is not available + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD + * when entering RF test with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 07 07 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support state of STA record change from 1 to 1 + * + * 07 05 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Fix correct structure size in cnmStaSendDeactivateCmd() + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * spin lock target revised + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change inner loop index from i to k. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 05 31 2010 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add RX TSF Log Feature and ADDBA Rsp with DECLINE handling + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support checking of duplicated buffer free + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 28 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Move define of STA_REC_NUM to config.h and rename to CFG_STA_REC_NUM + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 28 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Modified some MQM-related data structures (SN counter, TX/RX BA table) + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Added new TX/RX BA tables in STA_REC + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Notify MQM, TXM, and RXM upon disconnection . + * + * 04 26 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Call mqm, txm, rxm functions upon disconnection + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support + * * * * * * * * * * and will send Null frame to diagnose connection + * + * 04 09 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * [BORA00000644] WiFi phase 4 integration + * * Added per-TID SN cache in STA_REC + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * move the wlan table alloc / free to change state function. + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support power control + * + * 03 03 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Initialize StaRec->arStaWaitQueue + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add debug message when no available pkt buffer + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Fixed STA_REC initialization bug: prStaRec->au2CachedSeqCtrl[k] + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsWmmSupported in STA_RECORD_T. + * + * 02 26 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added fgIsUapsdSupported in STA_RECORD_T + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * add support of Driver STA_RECORD_T activation + * + * 02 13 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added arTspecTable in STA_REC for TSPEC management + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable mgmt buffer debug by default + * + * 02 12 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Added BUFFER_SOURCE_BCN + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 cp.wu + * [BORA00000368]Integrate HIF part into BORA + * 1) separate wifi_var_emu.c/.h from wifi_var.c/.h + * * * * * * * * * 2) eliminate HIF_EMULATION code sections appeared in wifi_var/cnm_mem + * * * * * * * * * 3) use cnmMemAlloc() instead to allocate SRAM buffer + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * * * * * * MQM: BA handling + * * * * * * * TXM: Macros updates + * * * * * * * RXM: Macros/Duplicate Removal updates + * + * 12 24 2009 yarco.yang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * 12 21 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support several data buffer banks. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * .For new FPGA memory size + * + * Dec 9 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed DBGPRINT + * + * Dec 9 2009 mtk02752 + * [BORA00000368] Integrate HIF part into BORA + * add cnmDataPktFree() for emulation loopback purpose + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix warning of null pointer + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add cnmGetStaRecByAddress() and add fgIsInUse flag in STA_RECORD_T + * + * Nov 23 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Assign ucBufferSource in function cnmMgtPktAlloc() + * + * Nov 23 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added packet redispatch function calls + * + * Nov 13 2009 mtk01084 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * enable packet re-usable in current emulation driver + * + * Nov 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * 1. Add new function cnmGetStaRecByIndex() + * 2. Rename STA_REC_T to STA_RECORD_T + * + * Nov 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call cnmDataPktDispatch() in cnmPktFree() + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove definition of pragma section code + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Oct 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * + * Oct 8 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf); + +static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp); + +static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T cnmMgtPktAlloc(P_ADAPTER_T prAdapter, UINT_32 u4Length) +{ + P_MSDU_INFO_T prMsduInfo; + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + /* Get a free MSDU_INFO_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(prQueList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo) { + prMsduInfo->prPacket = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + prMsduInfo->eSrc = TX_PACKET_MGMT; + + if (prMsduInfo->prPacket == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = NULL; + } + if (prMsduInfo) { + prMsduInfo->eCmdType = COMMAND_TYPE_NUM; + prMsduInfo->ucCID = 0xff; + prMsduInfo->u4InqueTime = 0; + prMsduInfo->ucPacketType = TX_PACKET_NUM; + } + } else { + P_QUE_T prTxingQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + P_TX_TCQ_STATUS_T pTc = (P_TX_TCQ_STATUS_T) NULL; + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + pTc = &(prAdapter->rTxCtrl.rTc); + + DBGLOG(MEM, LOUD, "++dump TxPendingMsdu=%u, Tc0=%d Tc1=%d Tc2=%d Tc3=%d, Tc4=%d Tc5=%d\n", + prTxingQue->u4NumElem, pTc->aucFreeBufferCount[TC0_INDEX], + pTc->aucFreeBufferCount[TC1_INDEX], pTc->aucFreeBufferCount[TC2_INDEX], + pTc->aucFreeBufferCount[TC3_INDEX], pTc->aucFreeBufferCount[TC4_INDEX], + pTc->aucFreeBufferCount[TC5_INDEX]); + + prQueueEntry = QUEUE_GET_HEAD(prTxingQue); + + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + DBGLOG(MEM, LOUD, + "msdu type=%u, ucid=%u, type=%d, time=%u, seq=%u, sta=%u\n", + prMsduInfo->ucPacketType, + prMsduInfo->ucCID, + prMsduInfo->eCmdType, + prMsduInfo->u4InqueTime, prMsduInfo->ucTxSeqNum, prMsduInfo->ucStaRecIndex); + prQueueEntry = QUEUE_GET_NEXT_ENTRY(prQueueEntry); + } + DBGLOG(MEM, LOUD, "--end dump\n"); + } + +#if DBG + if (prMsduInfo == NULL) { + DBGLOG(MEM, WARN, "MgtDesc#=%u\n", prQueList->u4NumElem); + +#if CFG_DBG_MGT_BUF + DBGLOG(MEM, WARN, "rMgtBufInfo: alloc#=%u, free#=%u, null#=%u\n", + prAdapter->rMgtBufInfo.u4AllocCount, + prAdapter->rMgtBufInfo.u4FreeCount, prAdapter->rMgtBufInfo.u4AllocNullCount); +#endif + + DBGLOG(MEM, WARN, "\n"); + } +#endif + + return prMsduInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMgtPktFree(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_QUE_T prQueList; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prQueList = &prAdapter->rTxCtrl.rFreeMsduInfoList; + + ASSERT(prMsduInfo->prPacket); + if (prMsduInfo->prPacket) { + cnmMemFree(prAdapter, prMsduInfo->prPacket); + prMsduInfo->prPacket = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo->fgIsBasicRate = FALSE; + QUEUE_INSERT_TAIL(prQueList, &prMsduInfo->rQueEntry) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to initial the MGMT/MSG memory pool. +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMemInit(P_ADAPTER_T prAdapter) +{ + P_BUF_INFO_T prBufInfo; + + /* Initialize Management buffer pool */ + prBufInfo = &prAdapter->rMgtBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMgtBufInfo)); + prBufInfo->pucBuf = prAdapter->pucMgtBufCached; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + /* Initialize Message buffer pool */ + prBufInfo = &prAdapter->rMsgBufInfo; + kalMemZero(prBufInfo, sizeof(prAdapter->rMsgBufInfo)); + prBufInfo->pucBuf = &prAdapter->aucMsgBuf[0]; + + /* Setup available memory blocks. 1 indicates FREE */ + prBufInfo->rFreeBlocksBitmap = (BUF_BITMAP) BITS(0, MAX_NUM_OF_BUF_BLOCKS - 1); + + return; + +} /* end of cnmMemInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate MGMT/MSG memory pool. +* +* \param[in] eRamType Target RAM type. +* TCM blk_sz= 16bytes, BUF blk_sz= 256bytes +* \param[in] u4Length Length of the buffer to allocate. +* +* \retval !NULL Pointer to the start address of allocated memory. +* \retval NULL Fail to allocat memory +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4MemAllocCnt = 0, u4MemFreeCnt = 0; +PVOID cnmMemAlloc(IN P_ADAPTER_T prAdapter, IN ENUM_RAM_TYPE_T eRamType, IN UINT_32 u4Length) +{ + P_BUF_INFO_T prBufInfo; + BUF_BITMAP rRequiredBitmap; + UINT_32 u4BlockNum; + UINT_32 i, u4BlkSzInPower; + PVOID pvMemory; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(u4Length); + + u4MemAllocCnt++; + + if (eRamType == RAM_TYPE_MSG && u4Length <= 256) { + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlkSzInPower = MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4Length += (MSG_BUF_BLOCK_SIZE - 1); + u4BlockNum = u4Length >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } else { + eRamType = RAM_TYPE_BUF; + + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlkSzInPower = MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + u4Length += (MGT_BUF_BLOCK_SIZE - 1); + u4BlockNum = u4Length >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + + ASSERT(u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS); + } + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocCount++; +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + if ((u4BlockNum > 0) && (u4BlockNum <= MAX_NUM_OF_BUF_BLOCKS)) { + + /* Convert number of block into bit cluster */ + rRequiredBitmap = BITS(0, u4BlockNum - 1); + + for (i = 0; i <= (MAX_NUM_OF_BUF_BLOCKS - u4BlockNum); i++) { + + /* Have available memory blocks */ + if ((prBufInfo->rFreeBlocksBitmap & rRequiredBitmap) + == rRequiredBitmap) { + + /* Clear corresponding bits of allocated memory blocks */ + prBufInfo->rFreeBlocksBitmap &= ~rRequiredBitmap; + + /* Store how many blocks be allocated */ + prBufInfo->aucAllocatedBlockNum[i] = (UINT_8) u4BlockNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, + eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + /* Return the start address of allocated memory */ + return (PVOID) (prBufInfo->pucBuf + (i << u4BlkSzInPower)); + + } + + rRequiredBitmap <<= 1; + } + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + /* cannot move the allocation between spin_lock_irqsave and spin_unlock_irqrestore */ +#ifdef LINUX + pvMemory = (PVOID) kalMemAlloc(u4Length, VIR_MEM_TYPE); + if (pvMemory) + kalMemZero(pvMemory, u4Length); +#else + pvMemory = (PVOID) NULL; +#endif + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4AllocNullCount++; + + if (pvMemory) + prAdapter->u4MemAllocDynamicCount++; +#endif + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return pvMemory; + +} /* end of cnmMemAlloc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release memory to MGT/MSG memory pool. +* +* \param pucMemory Start address of previous allocated memory +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmMemFree(IN P_ADAPTER_T prAdapter, IN PVOID pvMemory) +{ + P_BUF_INFO_T prBufInfo; + UINT_32 u4BlockIndex; + BUF_BITMAP rAllocatedBlocksBitmap; + ENUM_RAM_TYPE_T eRamType; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(pvMemory); + if (!pvMemory) + return; + + u4MemFreeCnt++; + + /* Judge it belongs to which RAM type */ + if (((ULONG) pvMemory >= (ULONG)&prAdapter->aucMsgBuf[0]) && + ((ULONG) pvMemory <= (ULONG)&prAdapter->aucMsgBuf[MSG_BUFFER_SIZE - 1])) { + + prBufInfo = &prAdapter->rMsgBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MSG_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_MSG; + } else if (((ULONG) pvMemory >= (ULONG) prAdapter->pucMgtBufCached) && + ((ULONG) pvMemory <= ((ULONG) prAdapter->pucMgtBufCached + MGT_BUFFER_SIZE - 1))) { + prBufInfo = &prAdapter->rMgtBufInfo; + u4BlockIndex = ((ULONG) pvMemory - (ULONG) prBufInfo->pucBuf) + >> MGT_BUF_BLOCK_SIZE_IN_POWER_OF_2; + ASSERT(u4BlockIndex < MAX_NUM_OF_BUF_BLOCKS); + eRamType = RAM_TYPE_BUF; + } else { +#ifdef LINUX + /* For Linux, it is supported because size is not needed */ + kalMemFree(pvMemory, VIR_MEM_TYPE, 0); +#else + /* For Windows, it is not supported because of no size argument */ + ASSERT(0); +#endif + +#if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount++; +#endif + return; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + +#if CFG_DBG_MGT_BUF + prBufInfo->u4FreeCount++; +#endif + + /* Convert number of block into bit cluster */ + ASSERT(prBufInfo->aucAllocatedBlockNum[u4BlockIndex] > 0); + + rAllocatedBlocksBitmap = BITS(0, prBufInfo->aucAllocatedBlockNum[u4BlockIndex] - 1); + rAllocatedBlocksBitmap <<= u4BlockIndex; + + /* Clear saved block count for this memory segment */ + prBufInfo->aucAllocatedBlockNum[u4BlockIndex] = 0; + + /* Set corresponding bit of released memory block */ + prBufInfo->rFreeBlocksBitmap |= rAllocatedBlocksBitmap; + + KAL_RELEASE_SPIN_LOCK(prAdapter, eRamType == RAM_TYPE_MSG ? SPIN_LOCK_MSG_BUF : SPIN_LOCK_MGT_BUF); + + return; + +} /* end of cnmMemFree() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecInit(P_ADAPTER_T prAdapter) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + prStaRec->ucIndex = (UINT_8) i; + prStaRec->fgIsInUse = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecUninit(IN P_ADAPTER_T prAdapter) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse) + cnmStaRecFree(prAdapter, prStaRec, FALSE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmStaRecAlloc(P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i, k; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (!prStaRec->fgIsInUse) { + /*---- Initialize STA_REC_T here ----*/ + kalMemZero(prStaRec, sizeof(STA_RECORD_T)); + prStaRec->ucIndex = (UINT_8) i; + prStaRec->ucNetTypeIndex = ucNetTypeIndex; + prStaRec->fgIsInUse = TRUE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + /* Initialize the SN caches for duplicate detection */ + for (k = 0; k < TID_NUM + 1; k++) + prStaRec->au2CachedSeqCtrl[k] = 0xFFFF; + + /* Initialize SW TX queues in STA_REC */ + for (k = 0; k < STA_WAIT_QUEUE_NUM; k++) + LINK_INITIALIZE(&prStaRec->arStaWaitQueue[k]); + + /* Default enable TX/RX AMPDU */ + prStaRec->fgTxAmpduEn = TRUE; + prStaRec->fgRxAmpduEn = TRUE; + +#if CFG_ENABLE_PER_STA_STATISTICS && CFG_ENABLE_PKT_LIFETIME_PROFILE + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; +#endif + + for (k = 0; k < NUM_OF_PER_STA_TX_QUEUES; k++) + QUEUE_INITIALIZE(&prStaRec->arTxQueue[k]); + + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecFree(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgSyncToChip) +{ + ASSERT(prAdapter); + ASSERT(prStaRec); + + /* To do: free related resources, e.g. timers, buffers, etc */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + prStaRec->fgTransmitKeyExist = FALSE; + prStaRec->fgSetPwrMgtBit = FALSE; + + if (prStaRec->pucAssocReqIe) { + kalMemFree(prStaRec->pucAssocReqIe, VIR_MEM_TYPE, prStaRec->u2AssocReqIeLen); + prStaRec->pucAssocReqIe = NULL; + prStaRec->u2AssocReqIeLen = 0; + } + + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + + if (fgSyncToChip) + cnmStaSendRemoveCmd(prAdapter, prStaRec); + + prStaRec->fgIsInUse = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaFreeAllStaByNetType(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, BOOLEAN fgSyncToChip) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex) + cnmStaRecFree(prAdapter, prStaRec, fgSyncToChip); + } /* end of for loop */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmGetStaRecByIndex(P_ADAPTER_T prAdapter, UINT_8 ucIndex) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + + prStaRec = (ucIndex < CFG_STA_REC_NUM) ? &prAdapter->arStaRec[ucIndex] : NULL; + + if (prStaRec && prStaRec->fgIsInUse == FALSE) + prStaRec = NULL; + + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Get STA_RECORD_T by Peer MAC Address(Usually TA). +* +* @param[in] pucPeerMacAddr Given Peer MAC Address. +* +* @retval Pointer to STA_RECORD_T, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_STA_RECORD_T cnmGetStaRecByAddress(P_ADAPTER_T prAdapter, UINT_8 ucNetTypeIndex, PUINT_8 pucPeerMacAddr) +{ + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + ASSERT(pucPeerMacAddr); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucNetTypeIndex == ucNetTypeIndex && + EQUAL_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMacAddr)) { + break; + } + } + + return (i < CFG_STA_REC_NUM) ? prStaRec : NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Reset the Status and Reason Code Field to 0 of all Station Records for +* the specified Network Type +* +* @param[in] eNetType Specify Network Type +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecResetStatus(P_ADAPTER_T prAdapter, ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + cnmStaFreeAllStaByNetType(prAdapter, eNetTypeIndex, FALSE); + +#if 0 + P_STA_RECORD_T prStaRec; + UINT_16 i; + + ASSERT(prAdapter); + + for (i = 0; i < CFG_STA_REC_NUM; i++) { + prStaRec = &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse) { + if ((NETWORK_TYPE_AIS_INDEX == eNetTypeIndex) && IS_STA_IN_AIS(prStaRec->eStaType)) { + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + } + + /* TODO(Kevin): For P2P and BOW */ + } + } + + return; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will change the ucStaState of STA_RECORD_T and also do +* event indication to HOST to sync the STA_RECORD_T in driver. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] u4NewState New STATE to change. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmStaRecChangeState(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, UINT_8 ucNewState) +{ + BOOLEAN fgNeedResp; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* Do nothing when following state transitions happen, + * other 6 conditions should be sync to FW, including 1-->1, 3-->3 + */ + if ((ucNewState == STA_STATE_2 && prStaRec->ucStaState != STA_STATE_3) || + (ucNewState == STA_STATE_1 && prStaRec->ucStaState == STA_STATE_2)) { + prStaRec->ucStaState = ucNewState; + return; + } + + fgNeedResp = FALSE; + if (ucNewState == STA_STATE_3) { + secFsmEventStart(prAdapter, prStaRec); + if (ucNewState != prStaRec->ucStaState) + fgNeedResp = TRUE; + } else { + if (ucNewState != prStaRec->ucStaState && prStaRec->ucStaState == STA_STATE_3) + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + fgNeedResp = FALSE; + } + prStaRec->ucStaState = ucNewState; + + cnmStaSendUpdateCmd(prAdapter, prStaRec, fgNeedResp); + +#if CFG_ENABLE_WIFI_DIRECT + /* To do: Confirm if it is invoked here or other location, but it should + * be invoked after state sync of STA_REC + * Update system operation parameters for AP mode + */ + if (prAdapter->fgIsP2PRegistered && (IS_STA_IN_P2P(prStaRec))) { + P_BSS_INFO_T prBssInfo; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + } +#endif +} + +P_STA_RECORD_T +cnmStaTheTypeGet(P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, ENUM_STA_TYPE_T eStaType, UINT32 *pu4StartIdx) +{ + P_STA_RECORD_T prStaRec = NULL; + UINT_16 i; + + for (i = *pu4StartIdx; i < CFG_STA_REC_NUM; i++) { + prStaRec = (P_STA_RECORD_T) &prAdapter->arStaRec[i]; + + if (prStaRec->fgIsInUse && + prStaRec->ucNetTypeIndex == (UINT_8) eNetTypeIndex && prStaRec->eStaType == eStaType) { + i++; + break; + } + + prStaRec = NULL; /* reset */ + } /* end of for loop */ + + *pu4StartIdx = i; + return prStaRec; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaRecHandleEventPkt(P_ADAPTER_T prAdapter, P_CMD_INFO_T prCmdInfo, PUINT_8 pucEventBuf) +{ + P_EVENT_ACTIVATE_STA_REC_T prEventContent; + P_STA_RECORD_T prStaRec; + + prEventContent = (P_EVENT_ACTIVATE_STA_REC_T) pucEventBuf; + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventContent->ucStaRecIdx); + + if (prStaRec && prStaRec->ucStaState == STA_STATE_3 && + !kalMemCmp(&prStaRec->aucMacAddr[0], &prEventContent->aucMacAddr[0], MAC_ADDR_LEN)) { + + qmActivateStaRec(prAdapter, prStaRec); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaSendUpdateCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec, BOOLEAN fgNeedResp) +{ + P_CMD_UPDATE_STA_RECORD_T prCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prStaRec->fgIsInUse); + + /* To do: come out a mechanism to limit one STA_REC sync once for AP mode + * to avoid buffer empty case when many STAs are associated + * simultaneously. + */ + + /* To do: how to avoid 2 times of allocated memory. Use Stack? + * One is here, the other is in wlanSendQueryCmd() + */ + prCmdContent = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_UPDATE_STA_RECORD_T)); + ASSERT(prCmdContent); + + /* To do: exception handle */ + if (!prCmdContent) + return; + + prCmdContent->ucIndex = prStaRec->ucIndex; + prCmdContent->ucStaType = (UINT_8) prStaRec->eStaType; + kalMemCopy(&prCmdContent->aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); + prCmdContent->u2AssocId = prStaRec->u2AssocId; + prCmdContent->u2ListenInterval = prStaRec->u2ListenInterval; + prCmdContent->ucNetTypeIndex = prStaRec->ucNetTypeIndex; + + prCmdContent->ucDesiredPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + prCmdContent->u2DesiredNonHTRateSet = prStaRec->u2DesiredNonHTRateSet; + prCmdContent->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + prCmdContent->ucMcsSet = prStaRec->ucMcsSet; + prCmdContent->ucSupMcs32 = (UINT_8) prStaRec->fgSupMcs32; + prCmdContent->u2HtCapInfo = prStaRec->u2HtCapInfo; + prCmdContent->ucNeedResp = (UINT_8) fgNeedResp; + +#if !CFG_SLT_SUPPORT + if (prAdapter->rWifiVar.eRateSetting != FIXED_RATE_NONE) { + /* override rate configuration */ + nicUpdateRateParams(prAdapter, + prAdapter->rWifiVar.eRateSetting, + &(prCmdContent->ucDesiredPhyTypeSet), + &(prCmdContent->u2DesiredNonHTRateSet), + &(prCmdContent->u2BSSBasicRateSet), + &(prCmdContent->ucMcsSet), + &(prCmdContent->ucSupMcs32), &(prCmdContent->u2HtCapInfo)); + } +#endif + + prCmdContent->ucIsQoS = prStaRec->fgIsQoS; + prCmdContent->ucIsUapsdSupported = prStaRec->fgIsUapsdSupported; + prCmdContent->ucStaState = prStaRec->ucStaState; + + prCmdContent->ucAmpduParam = prStaRec->ucAmpduParam; + prCmdContent->u2HtExtendedCap = prStaRec->u2HtExtendedCap; + prCmdContent->u4TxBeamformingCap = prStaRec->u4TxBeamformingCap; + prCmdContent->ucAselCap = prStaRec->ucAselCap; + prCmdContent->ucRCPI = prStaRec->ucRCPI; + + prCmdContent->ucUapsdAc = prStaRec->ucBmpTriggerAC | (prStaRec->ucBmpDeliveryAC << 4); + prCmdContent->ucUapsdSp = prStaRec->ucUapsdSp; + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_UPDATE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + fgNeedResp, /* fgNeedResp */ + FALSE, /* fgIsOid */ + fgNeedResp ? cnmStaRecHandleEventPkt : NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_UPDATE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdContent); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmStaSendRemoveCmd(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + CMD_REMOVE_STA_RECORD_T rCmdContent; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + rCmdContent.ucIndex = prStaRec->ucIndex; + kalMemCopy(&rCmdContent.aucMacAddr[0], &prStaRec->aucMacAddr[0], MAC_ADDR_LEN); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_REMOVE_STA_RECORD, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_REMOVE_STA_RECORD_T), /* u4SetQueryInfoLen */ + (PUINT_8) &rCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c new file mode 100644 index 0000000000000..8cc9ef9078fe4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/cnm_timer.c @@ -0,0 +1,482 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/cnm_timer.c#1 +*/ + +/*! \file "cnm_timer.c" + \brief + +*/ + +/* +** Log: cnm_timer.c + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation + * because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support sleep notification to host + * + * 05 19 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some checking assertions + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Return timer token back to COS when entering wait off state + * + * 01 11 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Remove compiling warning + * + * 01 08 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support longer timeout interval to 45 days from 65secu1rwduu`wvpghlqg|fh+fmdkb + * + * 01 06 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix system time is 32KHz instead of 1ms + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Place rRootTimer.rNextExpiredSysTime = rExpiredSysTime; before set timer + * + * Oct 30 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * In cnmTimerInitialize(), just stop timer if it was already created. + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Move the external reference for Lint to precomp.h + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] rTimeout Time out interval from current time. +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN cnmTimerSetTimer(IN P_ADAPTER_T prAdapter, IN OS_SYSTIME rTimeout) +{ + P_ROOT_TIMER prRootTimer; + BOOLEAN fgNeedWakeLock; + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + kalSetTimer(prAdapter->prGlueInfo, rTimeout); + + if (rTimeout <= SEC_TO_SYSTIME(WAKE_LOCK_MAX_TIME)) { + fgNeedWakeLock = TRUE; + + if (!prRootTimer->fgWakeLocked) { + KAL_WAKE_LOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = TRUE; + } + } else { + fgNeedWakeLock = FALSE; + } + + return fgNeedWakeLock; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a root timer. +* +* \param[in] prAdapter +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerInitialize(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + /* Note: glue layer have configured timer */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + KAL_WAKE_LOCK_INIT(prAdapter, &prRootTimer->rWakeLock, "WLAN Timer"); + prRootTimer->fgWakeLocked = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to destroy a root timer. +* When WIFI is off, the token shall be returned back to system. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDestroy(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prRootTimer = &prAdapter->rRootTimer; + + if (prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + KAL_WAKE_LOCK_DESTROY(prAdapter, &prRootTimer->rWakeLock); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + LINK_INITIALIZE(&prRootTimer->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + /* Note: glue layer will be responsible for timer destruction */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to initialize a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] pfnFunc Pointer to the call back function. +* \param[in] u4Data Parameter for call back function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerInitTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN PFN_MGMT_TIMEOUT_FUNC pfFunc, IN ULONG ulData) +{ + ASSERT(prAdapter); + + ASSERT(prTimer); + +#if DBG + /* Note: NULL function pointer is permitted for HEM POWER */ + if (pfFunc == NULL) + DBGLOG(CNM, WARN, "Init timer with NULL callback function!\n"); +#endif + +#if DBG + ASSERT(prAdapter->rRootTimer.rLinkHead.prNext); + { + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prPendingTimer; + + prTimerList = &(prAdapter->rRootTimer.rLinkHead); + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prPendingTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prPendingTimer); + ASSERT(prPendingTimer != prTimer); + } + } +#endif + + LINK_ENTRY_INITIALIZE(&prTimer->rLinkEntry); + + prTimer->pfMgmtTimeOutFunc = pfFunc; + prTimer->ulData = ulData; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID cnmTimerStopTimer_impl(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN BOOLEAN fgAcquireSpinlock) +{ + P_ROOT_TIMER prRootTimer; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + prRootTimer = &prAdapter->rRootTimer; + + if (fgAcquireSpinlock) + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + if (timerPendingTimer(prTimer)) { + LINK_REMOVE_KNOWN_ENTRY(&prRootTimer->rLinkHead, &prTimer->rLinkEntry); + + /* Reduce dummy timeout for power saving, especially HIF activity. + * If two or more timers exist and being removed timer is smallest, + * this dummy timeout will still happen, but it is OK. + */ + if (LINK_IS_EMPTY(&prRootTimer->rLinkHead)) { + kalCancelTimer(prAdapter->prGlueInfo); + + if (fgAcquireSpinlock && prRootTimer->fgWakeLocked) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + } + } + + if (fgAcquireSpinlock) + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to stop a timer. +* +* \param[in] prTimer Pointer to a timer structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerStopTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer) +{ + ASSERT(prAdapter); + ASSERT(prTimer); + + cnmTimerStopTimer_impl(prAdapter, prTimer, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to start a timer with wake_lock. +* +* \param[in] prTimer Pointer to a timer structure. +* \param[in] u4TimeoutMs Timeout to issue the timer and call back function +* (unit: ms). +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerStartTimer(IN P_ADAPTER_T prAdapter, IN P_TIMER_T prTimer, IN UINT_32 u4TimeoutMs) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + OS_SYSTIME rExpiredSysTime, rTimeoutSystime; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prTimer); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList = &prRootTimer->rLinkHead; + + /* If timeout interval is larger than 1 minute, the mod value is set + * to the timeout value first, then per minutue. + */ + if (u4TimeoutMs > MSEC_PER_MIN) { + ASSERT(u4TimeoutMs <= ((UINT_32) 0xFFFF * MSEC_PER_MIN)); + + prTimer->u2Minutes = (UINT_16) (u4TimeoutMs / MSEC_PER_MIN); + u4TimeoutMs -= (prTimer->u2Minutes * MSEC_PER_MIN); + if (u4TimeoutMs == 0) { + u4TimeoutMs = MSEC_PER_MIN; + prTimer->u2Minutes--; + } + } else { + prTimer->u2Minutes = 0; + } + + /* The assertion check if MSEC_TO_SYSTIME() may be overflow. */ + ASSERT(u4TimeoutMs < (((UINT_32) 0x80000000 - MSEC_PER_SEC) / KAL_HZ)); + rTimeoutSystime = MSEC_TO_SYSTIME(u4TimeoutMs); + rExpiredSysTime = kalGetTimeTick() + rTimeoutSystime; + + /* If no timer pending or the fast time interval is used. */ + if (LINK_IS_EMPTY(prTimerList) || TIME_BEFORE(rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + + prRootTimer->rNextExpiredSysTime = rExpiredSysTime; + cnmTimerSetTimer(prAdapter, rTimeoutSystime); + } + + /* Add this timer to checking list */ + prTimer->rExpiredSysTime = rExpiredSysTime; + + if (!timerPendingTimer(prTimer)) + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routines is called to check the timer list. +* +* \param[in] +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cnmTimerDoTimeOutCheck(IN P_ADAPTER_T prAdapter) +{ + P_ROOT_TIMER prRootTimer; + P_LINK_T prTimerList; + P_LINK_ENTRY_T prLinkEntry; + P_TIMER_T prTimer; + OS_SYSTIME rCurSysTime; + PFN_MGMT_TIMEOUT_FUNC pfMgmtTimeOutFunc; + ULONG ulTimeoutData; + BOOLEAN fgNeedWakeLock; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* acquire spin lock */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + + prRootTimer = &prAdapter->rRootTimer; + prTimerList = &prRootTimer->rLinkHead; + + rCurSysTime = kalGetTimeTick(); + + /* Set the permitted max timeout value for new one */ + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + + LINK_FOR_EACH(prLinkEntry, prTimerList) { + prTimer = LINK_ENTRY(prLinkEntry, TIMER_T, rLinkEntry); + ASSERT(prTimer); + + /* Check if this entry is timeout. */ + if (!TIME_BEFORE(rCurSysTime, prTimer->rExpiredSysTime)) { + cnmTimerStopTimer_impl(prAdapter, prTimer, FALSE); + + pfMgmtTimeOutFunc = prTimer->pfMgmtTimeOutFunc; + ulTimeoutData = prTimer->ulData; + + if (prTimer->u2Minutes > 0) { + prTimer->u2Minutes--; + prTimer->rExpiredSysTime = rCurSysTime + MSEC_TO_SYSTIME(MSEC_PER_MIN); + LINK_INSERT_TAIL(prTimerList, &prTimer->rLinkEntry); + } else if (pfMgmtTimeOutFunc) { + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + (pfMgmtTimeOutFunc) (prAdapter, ulTimeoutData); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); + } + + /* Search entire list again because of nest del and add timers + * and current MGMT_TIMER could be volatile after stopped + */ + prLinkEntry = (P_LINK_ENTRY_T) prTimerList; + + prRootTimer->rNextExpiredSysTime = rCurSysTime + MGMT_MAX_TIMEOUT_INTERVAL; + } else if (TIME_BEFORE(prTimer->rExpiredSysTime, prRootTimer->rNextExpiredSysTime)) { + prRootTimer->rNextExpiredSysTime = prTimer->rExpiredSysTime; + } + } /* end of for loop */ + + /* Setup the prNext timeout event. It is possible the timer was already + * set in the above timeout callback function. + */ + fgNeedWakeLock = FALSE; + if (!LINK_IS_EMPTY(prTimerList)) { + ASSERT(TIME_AFTER(prRootTimer->rNextExpiredSysTime, rCurSysTime)); + + fgNeedWakeLock = cnmTimerSetTimer(prAdapter, (OS_SYSTIME) + ((INT_32) prRootTimer->rNextExpiredSysTime - (INT_32) rCurSysTime)); + } + + if (prRootTimer->fgWakeLocked && !fgNeedWakeLock) { + KAL_WAKE_UNLOCK(prAdapter, &prRootTimer->rWakeLock); + prRootTimer->fgWakeLocked = FALSE; + } + + /* release spin lock */ + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TIMER); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c new file mode 100644 index 0000000000000..c7a23eb018b63 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hem_mbox.c @@ -0,0 +1,816 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/hem_mbox.c#3 +*/ + +/*! \file "hem_mbox.c" + \brief + +*/ + +/* +** Log: hem_mbox.c +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device +** have connected to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 05 03 2012 cp.wu + * [WCXRP00001231] [MT6620 Wi-Fi][MT5931][Driver] Correct SCAN_V2 related debugging facilities within hem_mbox.c + * correct for debug message string table by adding missed scan_v2 related definitions. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 17 2012 yuche.tsai + * NULL + * Update mgmt frame filter setting. + * Please also update FW 2.1 + * + * 01 13 2012 yuche.tsai + * NULL + * WiFi Hot Spot Tethering for ICS ALPHA testing version. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 15 2011 cm.chang + * NULL + * Add exception handle for NULL function pointer of mailbox message + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search + * for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support + * as well as uProbeDelay in NDIS 6.x driver model + * + * 06 07 2011 yuche.tsai + * [WCXRP00000696] [Volunteer Patch][MT6620][Driver] Infinite loop issue when RX invitation response. + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Add invitation support. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation + * because NdisMSleep() won't sleep long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update bowString and channel grant. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 12 08 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support concurrent networks. + * + * 11 08 2010 cm.chang + * [WCXRP00000169] [MT6620 Wi-Fi][Driver][FW] Remove unused CNM recover message ID + * Remove CNM channel reover message ID + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 16 2010 cm.chang + * NULL + * Remove unused message ID + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 26 2010 yuche.tsai + * NULL + * Add P2P Connection Abort Event Message handler. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 yarco.yang + * NULL + * Fixed Driver ASSERT at mboxInitMsgMap() + * + * 08 24 2010 chinghwa.yu + * NULL + * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. + * Update saa_fsm for BOW. + * + * 08 23 2010 chinghwa.yu + * NULL + * Add CFG_ENABLE_BT_OVER_WIFI. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 16 2010 yuche.tsai + * NULL + * Add debug message for newly add P2P message. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some function entry for P2P FSM under provisioning phase.. + * + * 08 11 2010 yuche.tsai + * NULL + * Add some events to P2P Module. + * + * 08 05 2010 yuche.tsai + * NULL + * Add message box event for P2P device switch on & device discovery. + * + * 08 04 2010 cp.wu + * NULL + * remove unused mailbox message definitions. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * message table should not be commented out by compilation option without modifying header file + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 yuche.tsai + * + * Add wifi direct scan done callback. + * + * 07 09 2010 cp.wu + * + * change handler of MID_MNY_CNM_CONNECTION_ABORT from NULL to mboxDummy. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Rename MID_MNY_CNM_CH_RELEASE to MID_MNY_CNM_CH_ABORT + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Modify CNM message handler for new flow + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable currently migrated message call-backs. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * restore utility function invoking via hem_mbox to direct calls + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add buildable & linkable ais_fsm.c + * + * related reference are still waiting to be resolved + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * hem_mbox is migrated. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add hem_mbox.c and cnm_mem.h (but disabled some feature) for further migration + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Fix file merge error + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_QOS_ACTION_FRAME + * + * 04 29 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * Removed MID_RXM_MQM_BA_ACTION_FRAME + * + * 04 27 2010 tehuang.liu + * [BORA00000605][WIFISYS] Phase3 Integration + * MID_RXM_MQM_BA_ACTION_FRAME + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Develop partial DPD code + * + * 02 11 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Updated arMsgMapTable for MID_RXM_MQM_QOS_ACTION_FRAME + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * Dec 9 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add hemRunEventScanDone() to arMsgMapTable[] + * + * Dec 4 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix mboxDummy() didn't free prMsgHdr + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add saaAisJoinComplete event handler + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Fixed the handler function name in arMsgMapTable for MID_RXM_MQM_BA_ACTION_FRAME + * + * Dec 2 2009 MTK02468 + * [BORA00000337] To check in codes for FPGA emulation + * Added MID_RXM_MQM_BA_ACTION_FRAME to MsgMapTable + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MSG Handler (remove dummy and add for SAA) + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add aisFsmRunEventAbort() event handler + * + * Nov 11 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Nov 10 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add more MSG_HNDL_ENTRY_T to avoid ASSERT() in mboxInitMsgMap() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add SCN message and function entry to arMsgMapTable[] + * + * Nov 2 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix sorting algorithm in mboxInitMsgMap() + * + * Oct 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugMsg[] = { + (PUINT_8) DISP_STRING("MID_MNY_CNM_CH_REQ"), + (PUINT_8) DISP_STRING("MID_MNY_CNM_CH_ABORT"), + (PUINT_8) DISP_STRING("MID_CNM_AIS_CH_GRANT"), + (PUINT_8) DISP_STRING("MID_CNM_P2P_CH_GRANT"), + (PUINT_8) DISP_STRING("MID_CNM_BOW_CH_GRANT"), + + (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_REQ"), + (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_REQ_V2"), + (PUINT_8) DISP_STRING("MID_AIS_SCN_SCAN_CANCEL"), + (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_REQ"), + (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_REQ_V2"), + (PUINT_8) DISP_STRING("MID_P2P_SCN_SCAN_CANCEL"), + (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_REQ"), + (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_REQ_V2"), + (PUINT_8) DISP_STRING("MID_BOW_SCN_SCAN_CANCEL"), + (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_REQ"), + (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_REQ_V2"), + (PUINT_8) DISP_STRING("MID_RLM_SCN_SCAN_CANCEL"), + (PUINT_8) DISP_STRING("MID_SCN_AIS_SCAN_DONE"), + (PUINT_8) DISP_STRING("MID_SCN_P2P_SCAN_DONE"), + (PUINT_8) DISP_STRING("MID_SCN_BOW_SCAN_DONE"), + (PUINT_8) DISP_STRING("MID_SCN_RLM_SCAN_DONE"), + + (PUINT_8) DISP_STRING("MID_OID_AIS_FSM_JOIN_REQ"), + (PUINT_8) DISP_STRING("MID_OID_AIS_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_AIS_SAA_FSM_START"), + (PUINT_8) DISP_STRING("MID_AIS_SAA_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_SAA_AIS_JOIN_COMPLETE"), + +#if CFG_ENABLE_BT_OVER_WIFI + (PUINT_8) DISP_STRING("MID_BOW_SAA_FSM_START"), + (PUINT_8) DISP_STRING("MID_BOW_SAA_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_SAA_BOW_JOIN_COMPLETE"), +#endif + +#if CFG_ENABLE_WIFI_DIRECT + (PUINT_8) DISP_STRING("MID_P2P_SAA_FSM_START"), + (PUINT_8) DISP_STRING("MID_P2P_SAA_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_SAA_P2P_JOIN_COMPLETE"), + + (PUINT_8) DISP_STRING("MID_MNY_P2P_FUN_SWITCH"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_DEVICE_DISCOVERY"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_CONNECTION_REQ"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_CONNECTION_ABORT"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_BEACON_UPDATE"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_STOP_AP"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_CHNL_REQ"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_CHNL_ABORT"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_MGMT_TX"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_GROUP_DISSOLVE"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_MGMT_FRAME_REGISTER"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_NET_DEV_REGISTER"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_START_AP"), + (PUINT_8) DISP_STRING("MID_MNY_P2P_UPDATE_IE_BUF"), +#endif + +#if CFG_SUPPORT_ADHOC + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_CREATE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_CREATE_IBSS_GRANT"), */ + /* (PUINT_8)DISP_STRING("MID_AIS_CNM_MERGE_IBSS_REQ"), */ + /* (PUINT_8)DISP_STRING("MID_CNM_AIS_MERGE_IBSS_GRANT"), */ + (PUINT_8) DISP_STRING("MID_SCN_AIS_FOUND_IBSS"), +#endif /* CFG_SUPPORT_ADHOC */ + + (PUINT_8) DISP_STRING("MID_SAA_AIS_FSM_ABORT"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL"), + (PUINT_8) DISP_STRING("MID_MNY_AIS_MGMT_TX") +}; + +/*lint -restore */ +#endif /* DBG */ + +/* This message entry will be re-ordered based on the message ID order + * by invoking mboxInitMsgMap() + */ +static MSG_HNDL_ENTRY_T arMsgMapTable[] = { + {MID_MNY_CNM_CH_REQ, cnmChMngrRequestPrivilege}, + {MID_MNY_CNM_CH_ABORT, cnmChMngrAbortPrivilege}, + {MID_CNM_AIS_CH_GRANT, aisFsmRunEventChGrant}, +#if CFG_ENABLE_WIFI_DIRECT + {MID_CNM_P2P_CH_GRANT, p2pFsmRunEventChGrant}, /*set in gl_p2p_init.c */ +#else + {MID_CNM_P2P_CH_GRANT, mboxDummy}, +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + {MID_CNM_BOW_CH_GRANT, bowRunEventChGrant}, +#else + {MID_CNM_BOW_CH_GRANT, mboxDummy}, +#endif + + /*--------------------------------------------------*/ + /* SCN Module Mailbox Messages */ + /*--------------------------------------------------*/ + {MID_AIS_SCN_SCAN_REQ, scnFsmMsgStart}, + {MID_AIS_SCN_SCAN_REQ_V2, scnFsmMsgStart}, + {MID_AIS_SCN_SCAN_CANCEL, scnFsmMsgAbort}, + {MID_P2P_SCN_SCAN_REQ, scnFsmMsgStart}, + {MID_P2P_SCN_SCAN_REQ_V2, scnFsmMsgStart}, + {MID_P2P_SCN_SCAN_CANCEL, scnFsmMsgAbort}, + {MID_BOW_SCN_SCAN_REQ, scnFsmMsgStart}, + {MID_BOW_SCN_SCAN_REQ_V2, scnFsmMsgStart}, + {MID_BOW_SCN_SCAN_CANCEL, scnFsmMsgAbort}, + {MID_RLM_SCN_SCAN_REQ, scnFsmMsgStart}, + {MID_RLM_SCN_SCAN_REQ_V2, scnFsmMsgStart}, + {MID_RLM_SCN_SCAN_CANCEL, scnFsmMsgAbort}, + {MID_SCN_AIS_SCAN_DONE, aisFsmRunEventScanDone}, +#if CFG_ENABLE_WIFI_DIRECT + {MID_SCN_P2P_SCAN_DONE, p2pFsmRunEventScanDone}, /*set in gl_p2p_init.c */ +#else + {MID_SCN_P2P_SCAN_DONE, mboxDummy}, +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + {MID_SCN_BOW_SCAN_DONE, bowResponderScanDone}, +#else + {MID_SCN_BOW_SCAN_DONE, mboxDummy}, +#endif + {MID_SCN_RLM_SCAN_DONE, rlmObssScanDone}, + + /*--------------------------------------------------*/ + /* AIS Module Mailbox Messages */ + /*--------------------------------------------------*/ + {MID_OID_AIS_FSM_JOIN_REQ, aisFsmRunEventAbort}, + {MID_OID_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_AIS_SAA_FSM_START, saaFsmRunEventStart}, + {MID_AIS_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_AIS_JOIN_COMPLETE, aisFsmRunEventJoinComplete}, + +#if CFG_ENABLE_BT_OVER_WIFI + /*--------------------------------------------------*/ + /* BOW Module Mailbox Messages */ + /*--------------------------------------------------*/ + {MID_BOW_SAA_FSM_START, saaFsmRunEventStart}, + {MID_BOW_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_BOW_JOIN_COMPLETE, bowFsmRunEventJoinComplete}, +#endif + +#if CFG_ENABLE_WIFI_DIRECT /*set in gl_p2p_init.c */ + {MID_P2P_SAA_FSM_START, saaFsmRunEventStart}, + {MID_P2P_SAA_FSM_ABORT, saaFsmRunEventAbort}, + {MID_SAA_P2P_JOIN_COMPLETE, p2pFsmRunEventJoinComplete}, /* TODO: p2pFsmRunEventJoinComplete */ + + {MID_MNY_P2P_FUN_SWITCH, p2pFsmRunEventSwitchOPMode}, + {MID_MNY_P2P_DEVICE_DISCOVERY, p2pFsmRunEventScanRequest}, + {MID_MNY_P2P_CONNECTION_REQ, p2pFsmRunEventConnectionRequest}, + {MID_MNY_P2P_CONNECTION_ABORT, p2pFsmRunEventConnectionAbort}, + {MID_MNY_P2P_BEACON_UPDATE, p2pFsmRunEventBeaconUpdate}, + {MID_MNY_P2P_STOP_AP, p2pFsmRunEventStopAP}, + {MID_MNY_P2P_CHNL_REQ, p2pFsmRunEventChannelRequest}, + {MID_MNY_P2P_CHNL_ABORT, p2pFsmRunEventChannelAbort}, + {MID_MNY_P2P_MGMT_TX, p2pFsmRunEventMgmtFrameTx}, + {MID_MNY_P2P_GROUP_DISSOLVE, p2pFsmRunEventDissolve}, + {MID_MNY_P2P_MGMT_FRAME_REGISTER, p2pFsmRunEventMgmtFrameRegister}, + {MID_MNY_P2P_NET_DEV_REGISTER, p2pFsmRunEventNetDeviceRegister}, + {MID_MNY_P2P_START_AP, p2pFsmRunEventStartAP}, + {MID_MNY_P2P_MGMT_FRAME_UPDATE, p2pFsmRunEventUpdateMgmtFrame}, + {MID_MNY_P2P_EXTEND_LISTEN_INTERVAL, p2pFsmRunEventExtendListen}, +#if CFG_SUPPORT_WFD + {MID_MNY_P2P_WFD_CFG_UPDATE, p2pFsmRunEventWfdSettingUpdate}, +#endif + +#endif + +#if CFG_SUPPORT_ADHOC + {MID_SCN_AIS_FOUND_IBSS, aisFsmRunEventFoundIBSSPeer}, +#endif /* CFG_SUPPORT_ADHOC */ + + {MID_SAA_AIS_FSM_ABORT, aisFsmRunEventAbort}, + {MID_MNY_AIS_REMAIN_ON_CHANNEL, aisFsmRunEventRemainOnChannel}, + {MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL, aisFsmRunEventCancelRemainOnChannel}, + {MID_MNY_AIS_MGMT_TX, aisFsmRunEventMgmtFrameTx} +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +#if DBG +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, "DO MSG [%d: %s]\n", prMsg->eMsgId, apucDebugMsg[prMsg->eMsgId]); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#else +#define MBOX_HNDL_MSG(prAdapter, prMsg) do { \ + ASSERT(arMsgMapTable[prMsg->eMsgId].pfMsgHndl); \ + if (arMsgMapTable[prMsg->eMsgId].pfMsgHndl) { \ + DBGLOG(CNM, LOUD, "DO MSG [%d]\n", prMsg->eMsgId); \ + arMsgMapTable[prMsg->eMsgId].pfMsgHndl(prAdapter, prMsg); \ + } \ + else { \ + DBGLOG(CNM, ERROR, "NULL fptr for MSG [%d]\n", prMsg->eMsgId); \ + cnmMemFree(prAdapter, prMsg); \ + } \ +} while (0) +#endif +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxInitMsgMap(VOID) +{ + UINT_32 i, idx; + MSG_HNDL_ENTRY_T rTempEntry; + + ASSERT((sizeof(arMsgMapTable) / sizeof(MSG_HNDL_ENTRY_T)) == MID_TOTAL_NUM); + + for (i = 0; i < MID_TOTAL_NUM; i++) { + if (arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i) + continue; + for (idx = i + 1; idx < MID_TOTAL_NUM; idx++) { + if (arMsgMapTable[idx].eMsgId == (ENUM_MSG_ID_T) i) + break; + } + ASSERT(idx < MID_TOTAL_NUM); + if (idx >= MID_TOTAL_NUM) + continue; + + /* Swap target entry and current entry */ + rTempEntry.eMsgId = arMsgMapTable[idx].eMsgId; + rTempEntry.pfMsgHndl = arMsgMapTable[idx].pfMsgHndl; + + arMsgMapTable[idx].eMsgId = arMsgMapTable[i].eMsgId; + arMsgMapTable[idx].pfMsgHndl = arMsgMapTable[i].pfMsgHndl; + + arMsgMapTable[i].eMsgId = rTempEntry.eMsgId; + arMsgMapTable[i].pfMsgHndl = rTempEntry.pfMsgHndl; + } + + /* Verify the correctness of final message map */ + for (i = 0; i < MID_TOTAL_NUM; i++) { + ASSERT(arMsgMapTable[i].eMsgId == (ENUM_MSG_ID_T) i); + while (arMsgMapTable[i].eMsgId != (ENUM_MSG_ID_T) i) + ; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxSetup(IN P_ADAPTER_T prAdapter, IN ENUM_MBOX_ID_T eMboxId) +{ + P_MBOX_T prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INITIALIZE(&prMbox->rLinkHead); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mboxSendMsg(IN P_ADAPTER_T prAdapter, + IN ENUM_MBOX_ID_T eMboxId, IN P_MSG_HDR_T prMsg, IN EUNM_MSG_SEND_METHOD_T eMethod) +{ + P_MBOX_T prMbox; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prMsg); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + switch (eMethod) { + case MSG_SEND_METHOD_BUF: + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_INSERT_TAIL(&prMbox->rLinkHead, &prMsg->rLinkEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + /* to wake up main service thread */ + GLUE_SET_EVENT(prAdapter->prGlueInfo); + + break; + + case MSG_SEND_METHOD_UNBUF: + MBOX_HNDL_MSG(prAdapter, prMsg); + break; + + default: + ASSERT(0); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxRcvAllMsg(IN P_ADAPTER_T prAdapter, ENUM_MBOX_ID_T eMboxId) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(eMboxId < MBOX_ID_TOTAL_NUM); + ASSERT(prAdapter); + + prMbox = &(prAdapter->arMbox[eMboxId]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + MBOX_HNDL_MSG(prAdapter, prMsg); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxInitialize(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* Initialize Mailbox */ + mboxInitMsgMap(); + + /* Setup/initialize each mailbox */ + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) + mboxSetup(prAdapter, i); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDestroy(IN P_ADAPTER_T prAdapter) +{ + P_MBOX_T prMbox; + P_MSG_HDR_T prMsg; + UINT_8 i; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + for (i = 0; i < MBOX_ID_TOTAL_NUM; i++) { + prMbox = &(prAdapter->arMbox[i]); + + while (!LINK_IS_EMPTY(&prMbox->rLinkHead)) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + LINK_REMOVE_HEAD(&prMbox->rLinkHead, prMsg, P_MSG_HDR_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_MAILBOX); + + ASSERT(prMsg); + cnmMemFree(prAdapter, prMsg); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This is dummy function to prevent empty arMsgMapTable[] for compiling. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mboxDummy(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + ASSERT(prAdapter); + + cnmMemFree(prAdapter, prMsgHdr); + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c new file mode 100644 index 0000000000000..7fb71a199ccf4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/hs20.c @@ -0,0 +1,498 @@ +/* +** Id: //Department/DaVinci/BRANCHES/HS2_DEV_SW/MT6620_WIFI_DRIVER_V2_1_HS_2_0/mgmt/hs20.c#2 +*/ + +/*! \file "hs20.c" + \brief This file including the hotspot 2.0 related function. + + This file provided the macros and functions library support for the + protocol layer hotspot 2.0 related function. + +*/ + +/* +** Log: hs20.c + * + */ + + /******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_HOTSPOT_2_0 + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate Interworking IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateInterworkingIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate Roaming Consortium IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateRoamingConsortiumIE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to generate HS2.0 IE for Probe Rsp, Bcn, Assoc Req/Rsp. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] prMsduInfo Pointer of the Msdu Info +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20GenerateHS20IE(IN P_ADAPTER_T prAdapter, OUT P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 221 :0xDD */ + if (prAdapter->prGlueInfo->u2HS20AssocInfoIELen) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucHS20AssocInfoIE, + prAdapter->prGlueInfo->u2HS20AssocInfoIELen); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2HS20AssocInfoIELen; + } + +} + +VOID hs20FillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_HS20_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + /* Add Extended Capabilities IE */ + prExtCap = (P_HS20_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + kalPrint("IE_SIZE(prExtCap) = %d, %d %d\n", IE_SIZE(prExtCap), ELEM_HDR_LEN, ELEM_MAX_LEN_EXT_CAP); + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of Ext Cap IE bit 31. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillProreqExtCapIE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_HS20_EXT_CAP_T prExtCap; + + ASSERT(prAdapter); + + /* Add Extended Capabilities IE */ + prExtCap = (P_HS20_EXT_CAP_T) pucIE; + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prExtCap->aucCapabilities, prExtCap->ucLength); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_BSS_TRANSITION_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_UTC_TSF_OFFSET_BIT); + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to fill up the content of HS2.0 IE. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[out] pucIE Pointer of the IE buffer +* +* \return VOID +*/ +/*----------------------------------------------------------------------------*/ +VOID hs20FillHS20IE(IN P_ADAPTER_T prAdapter, OUT PUINT_8 pucIE) +{ + P_IE_HS20_INDICATION_T prHS20IndicationIe; + /* P_HS20_INFO_T prHS20Info; */ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + /* prHS20Info = &(prAdapter->rWifiVar.rHS20Info); */ + + prHS20IndicationIe = (P_IE_HS20_INDICATION_T) pucIE; + + prHS20IndicationIe->ucId = ELEM_ID_VENDOR; + prHS20IndicationIe->ucLength = sizeof(IE_HS20_INDICATION_T) - ELEM_HDR_LEN; + prHS20IndicationIe->aucOui[0] = aucWfaOui[0]; + prHS20IndicationIe->aucOui[1] = aucWfaOui[1]; + prHS20IndicationIe->aucOui[2] = aucWfaOui[2]; + prHS20IndicationIe->ucType = VENDOR_OUI_TYPE_HS20; + prHS20IndicationIe->ucHotspotConfig = 0x00; /* prHS20Info->ucHotspotConfig; */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while calculating length of hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* +* \return the length of composed HS20 IE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 hs20CalculateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID) +{ + UINT_32 u4IeLength; + + if (0) /* Todo:: Not HS20 STA */ + return 0; + + u4IeLength = + sizeof(IE_HS20_INDICATION_T) + /* sizeof(IE_INTERWORKING_T) */ + (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP); + + if (!pucTargetBSSID) { + /* Do nothing */ + /* u4IeLength -= MAC_ADDR_LEN; */ + } + + return u4IeLength; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called while composing hotspot 2.0 indication IE for Probe Request. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* \param[in] pucTargetBSSID Pointer of target HESSID +* \param[out] prIE Pointer of the IE buffer +* +* \return the wlan status +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS hs20GenerateHS20RelatedIEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucTargetBSSID, OUT PUINT_8 prIE) +{ + if (0) /* Todo:: Not HS20 STA */ + return 0; +#if 0 + P_HS20_INFO_T prHS20Info; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + + /* + * Generate 802.11u Interworking IE (107) + */ + hs20FillInterworkingIE(prAdapter, + prHS20Info->ucAccessNetworkOptions, + prHS20Info->ucVenueGroup, prHS20Info->ucVenueType, pucTargetBSSID, prIE); + prIE += IE_SIZE(prIE); +#endif + /* + * Generate Ext Cap IE (127) + */ + hs20FillProreqExtCapIE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + /* + * Generate HS2.0 Indication IE (221) + */ + hs20FillHS20IE(prAdapter, prIE); + prIE += IE_SIZE(prIE); + + return WLAN_STATUS_SUCCESS; +} + +BOOLEAN hs20IsGratuitousArp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucSenderIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SENDER_IP_OFFSET; + PUINT_8 pucTargetIP = prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_IP_OFFSET; + PUINT_8 pucSenderMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_SNEDER_MAC_OFFSET); +#if CFG_HS20_DEBUG && 0 +/* UINT_8 aucIpAllZero[4] = {0,0,0,0}; */ +/* UINT_8 aucMACAllZero[MAC_ADDR_LEN] = {0,0,0,0,0,0}; */ + PUINT_8 pucTargetMac = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_TARGET_MAC_OFFSET); +#endif + +#if CFG_HS20_DEBUG && 0 + PUINT_16 pu2ArpOper = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + ARP_OPERATION_OFFSET); + + kalPrint("Recv ARP 0x%04X\n", htons(*pu2ArpOper)); + kalPrint("SENDER[ %pM ] [%pI4]\n", pucSenderMac, pucSenderIP); + kalPrint("TARGET[ %pM ] [%pI4]\n", pucTargetMac, pucTargetIP); +#endif + + /* IsGratuitousArp */ + if (!kalMemCmp(pucSenderIP, pucTargetIP, 4)) { + kalPrint("Drop Gratuitous ARP from [ %pM ] [%pI4]\n", pucSenderMac, pucTargetIP); + return TRUE; + } + return FALSE; +} + +BOOLEAN hs20IsUnsolicitedNeighborAdv(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_8 pucIpv6Protocol = ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_PROTOCOL_OFFSET); + + /* kalPrint("pucIpv6Protocol [%02X:%02X]\n", *pucIpv6Protocol, IPV6_PROTOCOL_ICMPV6); */ + if (*pucIpv6Protocol == IPV6_PROTOCOL_ICMPV6) { + PUINT_8 pucICMPv6Type = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_TYPE_OFFSET); + /* kalPrint("pucICMPv6Type [%02X:%02X]\n", *pucICMPv6Type, ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT); */ + if (*pucICMPv6Type == ICMPV6_TYPE_NEIGHBOR_ADVERTISEMENT) { + PUINT_8 pucICMPv6Flag = + ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_LEN + ICMPV6_FLAG_OFFSET); + PUINT_8 pucSrcMAC = ((PUINT_8) prCurrSwRfb->pvHeader + MAC_ADDR_LEN); + +#if CFG_HS20_DEBUG + kalPrint("NAdv Flag [%02X] [R(%d)\\S(%d)\\O(%d)]\n", + *pucICMPv6Flag, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_ROUTER_BIT) >> 7, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT) >> 6, + (UINT_8) (*pucICMPv6Flag & ICMPV6_FLAG_OVERWRITE_BIT) >> 5); +#endif + if (!(*pucICMPv6Flag & ICMPV6_FLAG_SOLICITED_BIT)) { + kalPrint("Drop Unsolicited Neighbor Advertisement from [%pM]\n", pucSrcMAC); + return TRUE; + } + } + } + + return FALSE; +} + +#if CFG_ENABLE_GTK_FRAME_FILTER +BOOLEAN hs20IsForgedGTKFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + /* + P_CONNECTION_SETTINGS_T prConnSettings = &prAdapter->rWifiVar.rConnSettings; + PUINT_8 pucEthDestAddr = prCurrSwRfb->pvHeader; + */ + /* 3 TODO: Need to verify this function before enable it */ + return FALSE; + /* + if ((prConnSettings->eEncStatus != ENUM_ENCRYPTION_DISABLED) && IS_BMCAST_MAC_ADDR(pucEthDestAddr)) { + UINT_8 ucIdx = 0; + PUINT_32 prIpAddr, prPacketDA; + PUINT_16 pu2PktIpVer = + (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + if (*pu2PktIpVer == htons(ETH_P_IPV4)) { + if (!prBssInfo->prIpV4NetAddrList) + return FALSE; + for (ucIdx = 0; ucIdx < prBssInfo->prIpV4NetAddrList->ucAddrCount; ucIdx++) { + prIpAddr = (PUINT_32) &prBssInfo->prIpV4NetAddrList->arNetAddr[ucIdx].aucIpAddr[0]; + prPacketDA = + (PUINT_32) ((PUINT_8) prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + + IPV4_HDR_IP_DST_ADDR_OFFSET); + + if (kalMemCmp(prIpAddr, prPacketDA, 4) == 0) { + kalPrint("Drop FORGED IPv4 packet\n"); + return TRUE; + } + } + } +#ifdef CONFIG_IPV6 + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) { + UINT_8 aucIPv6Mac[MAC_ADDR_LEN]; + PUINT_8 pucIdx = + prCurrSwRfb->pvHeader + ETHER_HEADER_LEN + IPV6_HDR_IP_DST_ADDR_MAC_HIGH_OFFSET; + + kalMemCopy(&aucIPv6Mac[0], pucIdx, 3); + pucIdx += 5; + kalMemCopy(&aucIPv6Mac[3], pucIdx, 3); + kalPrint("Get IPv6 frame Dst IP MAC part %pM\n", aucIPv6Mac); + if (EQUAL_MAC_ADDR(aucIPv6Mac, prBssInfo->aucOwnMacAddr)) { + kalPrint("Drop FORGED IPv6 packet\n"); + return TRUE; + } + } +#endif + } + + return FALSE; + */ +} +#endif + +BOOLEAN hs20IsUnsecuredFrame(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo, IN P_SW_RFB_T prCurrSwRfb) +{ + PUINT_16 pu2PktIpVer = (PUINT_16) ((PUINT_8) prCurrSwRfb->pvHeader + (ETHER_HEADER_LEN - ETHER_TYPE_LEN)); + + /* kalPrint("IPVER 0x%4X\n", htons(*pu2PktIpVer)); */ +#if CFG_HS20_DEBUG & 0 + UINT_8 i = 0; + + kalPrint("==============================================="); + for (i = 0; i < 96; i++) { + if (!(i % 16)) + kalPrint("\n"); + kalPrint("%02X ", *((PUINT_8) prCurrSwRfb->pvHeader + i)); + } + kalPrint("\n"); +#endif + +#if CFG_ENABLE_GTK_FRAME_FILTER + if (hs20IsForgedGTKFrame(prAdapter, prBssInfo, prCurrSwRfb)) + return TRUE; + +#endif + if (*pu2PktIpVer == htons(ETH_P_ARP)) + return hs20IsGratuitousArp(prAdapter, prCurrSwRfb); + else if (*pu2PktIpVer == htons(ETH_P_IPV6)) + return hs20IsUnsolicitedNeighborAdv(prAdapter, prCurrSwRfb); + + return FALSE; +} + +BOOLEAN hs20IsFrameFilterEnabled(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prBssInfo) +{ +#if 1 + if (prAdapter->prGlueInfo->fgConnectHS20AP) + return TRUE; +#else + PARAM_SSID_T rParamSsid; + P_BSS_DESC_T prBssDesc; + + rParamSsid.u4SsidLen = prBssInfo->ucSSIDLen; + COPY_SSID(rParamSsid.aucSsid, rParamSsid.u4SsidLen, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, prBssInfo->aucBSSID, TRUE, &rParamSsid); + if (!prBssDesc) + return FALSE; + + if (prBssDesc->fgIsSupportHS20) { + if (!(prBssDesc->ucHotspotConfig & ELEM_HS_CONFIG_DGAF_DISABLED_MASK)) + return TRUE; + + /* Disable frame filter only if DGAF == 1 */ + return FALSE; + + } +#endif + + /* For Now, always return true to run hs20 check even for legacy AP */ + return TRUE; +} + +WLAN_STATUS hs20SetBssidPool(IN P_ADAPTER_T prAdapter, IN PVOID pvBuffer, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx) +{ + P_PARAM_HS20_SET_BSSID_POOL prParamBssidPool = (P_PARAM_HS20_SET_BSSID_POOL) pvBuffer; + P_HS20_INFO_T prHS20Info; + UINT_8 ucIdx; + + prHS20Info = &(prAdapter->rWifiVar.rHS20Info); + kalPrint("[%s]Set Bssid Pool! enable[%d] num[%d]\n", __func__, prParamBssidPool->fgIsEnable, + prParamBssidPool->ucNumBssidPool); + for (ucIdx = 0; ucIdx < prParamBssidPool->ucNumBssidPool; ucIdx++) { + COPY_MAC_ADDR(prHS20Info->arBssidPool[ucIdx].aucBSSID, &prParamBssidPool->arBSSID[ucIdx]); + kalPrint("[%s][%d][ %pM ]\n", __func__, ucIdx, (prHS20Info->arBssidPool[ucIdx].aucBSSID)); + } + prHS20Info->fgIsHS2SigmaMode = prParamBssidPool->fgIsEnable; + prHS20Info->ucNumBssidPoolEntry = prParamBssidPool->ucNumBssidPool; + +#if 0 + wlanClearScanningResult(prAdapter); +#endif + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c new file mode 100644 index 0000000000000..469a48ebe9c10 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/mib.c @@ -0,0 +1,111 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/mib.c#1 +*/ + +/*! \file "mib.c" + \brief This file includes the mib default vale and functions. +*/ + +/* +** Log: mib.c + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add mib.c. + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +NON_HT_PHY_ATTRIBUTE_T rNonHTPhyAttributes[] = { + {RATE_SET_HR_DSSS, TRUE, FALSE} + , /* For PHY_TYPE_HR_DSSS_INDEX(0) */ + {RATE_SET_ERP, TRUE, TRUE} + , /* For PHY_TYPE_ERP_INDEX(1) */ + {RATE_SET_ERP_P2P, TRUE, TRUE} + , /* For PHY_TYPE_ERP_P2P_INDEX(2) */ + {RATE_SET_OFDM, FALSE, FALSE} + , /* For PHY_TYPE_OFDM_INDEX(3) */ +}; + +NON_HT_ADHOC_MODE_ATTRIBUTE_T rNonHTAdHocModeAttributes[AD_HOC_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AD_HOC_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AD_HOC_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AD_HOC_MODE_11G(2) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AD_HOC_MODE_11A(3) */ +}; + +NON_HT_AP_MODE_ATTRIBUTE_T rNonHTApModeAttributes[AP_MODE_NUM] = { + {PHY_TYPE_HR_DSSS_INDEX, BASIC_RATE_SET_HR_DSSS} + , /* For AP_MODE_11B(0) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_HR_DSSS_ERP} + , /* For AP_MODE_MIXED_11BG(1) */ + {PHY_TYPE_ERP_INDEX, BASIC_RATE_SET_ERP} + , /* For AP_MODE_11G(2) */ + {PHY_TYPE_ERP_P2P_INDEX, BASIC_RATE_SET_ERP_P2P} + , /* For AP_MODE_11G_P2P(3) */ + {PHY_TYPE_OFDM_INDEX, BASIC_RATE_SET_OFDM} + , /* For AP_MODE_11A(4) */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c new file mode 100644 index 0000000000000..cb5fbebedd495 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_assoc.c @@ -0,0 +1,87 @@ +/* +** Id: @(#) p2p_assoc.c@@ +*/ + +/*! \file "p2p_assoc.c" + \brief This file includes the Wi-Fi Direct association-related functions. + + This file includes the association-related functions. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to compose Common Information Elements for P2P Association +* Request Frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +PUINT_8 p2pBuildReAssocReqFrameCommonIEs(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN PUINT_8 pucBuffer) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + /* Fill the SSID element. */ + SSID_IE(pucBuffer)->ucId = ELEM_ID_SSID; + + /* NOTE(Kevin): We copy the SSID from CONNECTION_SETTINGS for the case of + * Passive Scan and the target BSS didn't broadcast SSID on its Beacon Frame. + */ + + COPY_SSID(SSID_IE(pucBuffer)->aucSSID, + SSID_IE(pucBuffer)->ucLength, prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen); + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + return pucBuffer; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c new file mode 100644 index 0000000000000..72a20a322cee6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_bss.c @@ -0,0 +1,58 @@ +/* +** Id: @(#) p2p_bss.c@@ +*/ + +/*! \file "p2p_bss.c" + \brief This file contains the functions for creating p2p BSS(AP). + + This file contains the functions for BSS(AP). We may create a BSS + network, or merge with exist IBSS network and sending Beacon Frame or reply + the Probe Response Frame for received Probe Request Frame. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c new file mode 100644 index 0000000000000..f8c09e2aa9ded --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_fsm.c @@ -0,0 +1,3139 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/mgmt/p2p_fsm.c#61 +*/ + +/*! \file "p2p_fsm.c" + \brief This file defines the FSM for P2P Module. + + This file defines the FSM for P2P Module. +*/ + +/* +** Log: p2p_fsm.c +** +** 12 20 2012 yuche.tsai +** [ALPS00410124] [Rose][Free Test][KE][rlmUpdateParamsForAP]The device reboot automatically +** and then "Fatal/Kernel" pops up during use data service.(Once) +** Fix possible NULL station record cause KE under AP mode. +** May due to variable uninitial. +** Review: http://mtksap20:8080/go?page=NewReview&reviewid=49970 +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected +**to AP previously,one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 08 21 2012 yuche.tsai +** NULL +** fix disconnect indication. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** Fix p2p bug find on ALPS.JB trunk. +** +** 07 27 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update for driver unload KE issue. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Fix the compile flag of enhancement. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000808] [Volunteer Patch][MT6620][Driver/FW] Device discoverability issue fix + * Change device discoverability methodology. From driver SCAN to FW lock channel. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Add wifi direct connection enhancement method I, II & VI. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000833] [Volunteer Patch][WiFi Direct][Driver] Service Discovery Frame RX Indicate Issue + * Fix Service Discovery Race Condition Issue. + * + * 06 23 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * change parameter name from PeerAddr to BSSID + * + * 06 21 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix an issue of accepting connection of GO. + * + * 06 21 2011 yuche.tsai + * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability + * Drop GAS frame when SD is not enabled. + * + * 06 20 2011 yuche.tsai + * NULL + * Fix compile error. + * + * 06 20 2011 yuche.tsai + * [WCXRP00000799] [Volunteer Patch][MT6620][Driver] Connection Indication Twice Issue. + * Fix connection indication twice issue. + * + * 06 20 2011 cp.wu + * [WCXRP00000798] [MT6620 Wi-Fi][Firmware] Follow-ups for WAPI frequency offset workaround in firmware SCN module + * 1. specify target's BSSID when requesting channel privilege. + * 2. pass BSSID information to firmware domain + * + * 06 20 2011 yuche.tsai + * [WCXRP00000795] [Volunteer Patch][MT6620][Driver] GO can not connect second device issue + * Solve P2P GO can not formation with second device issue. + * + * 06 14 2011 yuche.tsai + * NULL + * Change disconnect feature. + * + * 06 10 2011 yuche.tsai + * [WCXRP00000775] [Volunteer Patch][MT6620][Driver] Dynamic enable SD capability[WCXRP00000776] + * [Need Patch][MT6620][Driver] MT6620 response probe request of P2P device with P2P IE under Hot Spot mode. + * 1. Dynamic enable SD capability after P2P supplicant ready. + * 2. Avoid response probe respone with p2p IE when under hot spot mode. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 06 02 2011 cp.wu + * [WCXRP00000681] [MT5931][Firmware] HIF code size reduction + * eliminate unused parameters for SAA-FSM + * + * 05 26 2011 yuche.tsai + * [WCXRP00000745] Support accepting connection after one Group Connection Lost. + +After Group Formation & lost connection, if MT6620 behave as: + +1. GO: It would keep under GO state until been dissolved by supplicant. + + At this time, other P2P device can use join method to join this group. + +2. GC: It would keep on searching target GO or target device until been dissolved by supplicant. + +At this time, it would ignore other P2P device formation request. + +-- + +Modification: Make driver to accept GO NEGO REQ at this time, to let user decide to accept new connection or not. + + * [Volunteer Patch][MT6620][Driver] + * Driver would indicate connection request, if password ID is not ready but connection request is issued. + * + * 05 18 2011 yuche.tsai + * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. + * A solution for both connection request & IO control. + * + * 05 16 2011 yuche.tsai + * [WCXRP00000728] [Volunteer Patch][MT6620][Driver] Service Discovery Request TX issue. + * Fix SD request can not send out issue. + * + * 05 09 2011 terry.wu + * [WCXRP00000711] [MT6620 Wi-Fi][Driver] Set Initial value of StaType in StaRec for Hotspot Client + * Set initial value of StaType in StaRec for hotspot client. + * + * 05 04 2011 yuche.tsai + * [WCXRP00000697] [Volunteer Patch][MT6620][Driver] + * Bug fix for p2p descriptor is NULL if BSS descriptor is found first. + * + * 05 04 2011 yuche.tsai + * NULL + * Support partial persistent group function. + * + * 05 02 2011 yuche.tsai + * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. + * Clear formation flag after formation timeout. + * + * 04 20 2011 yuche.tsai + * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition + * when add scan & query scan result at the same time. + * Fix side effect while starting ATGO. + * + * 04 20 2011 yuche.tsai + * NULL + * Fix ASSERT issue in FW, side effect of last change. + * + * 04 19 2011 yuche.tsai + * [WCXRP00000668] [Volunteer Patch][MT6620][Driver] Possible race condition + * when add scan & query scan result at the same time. + * Workaround for multiple device connection, before invitation ready. + * + * 04 19 2011 yuche.tsai + * [WCXRP00000665] [Wifi Direct][MT6620 E4] When use Ralink's dongle to establish wifi direct connection with PBC. + * But 6573 always not pop accept option to establish connection. + * Support connection indication when GO NEGO REQ doesn't have configure method, instead it has PasswordID. + * + * 04 18 2011 yuche.tsai + * NULL + * Fix error. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Fix a connection issue. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Fix the channel issue of AP mode. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Connection flow refine for Sigma test. + * + * 04 09 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix Device discoverability related issue. + * + * 04 09 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix bug for Device Discoverability. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Fix compile error. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 03 28 2011 yuche.tsai + * NULL + * Fix a possible issue for retry join when media status connected. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 24 2011 yuche.tsai + * NULL + * Assign AID before change STA_REC state to state 3. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix Response Rate Issue when TX Auth Rsp Frame under P2P Mode. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix issue of connection to one GC. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix ASSERT issue when starting Hot-spot. + * + * 03 22 2011 yuche.tsai + * NULL + * When Target Information is not available, change to passive mode. + * + * 03 22 2011 yuche.tsai + * NULL + * Fix one connection issue while using Keypad to connect a GO. + * + * 03 22 2011 yuche.tsai + * NULL + * 1. Fix two issues that may cause kernel panic. + * + * 03 22 2011 yuche.tsai + * NULL + * Fix GC connect to other device issue. + * + * 03 22 2011 yuche.tsai + * NULL + * 1.Shorten the LISTEN interval. + * 2. Fix IF address issue when we are GO + * 3. Fix LISTEN channel issue. + * + * 03 22 2011 yuche.tsai + * NULL + * Modify formation policy setting. + * + * 03 21 2011 yuche.tsai + * NULL + * Solve Listen State doesn't response probe response issue. + * + * 03 21 2011 yuche.tsai + * NULL + * Change P2P Connection Request Flow. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue + * Indicate the correct Group SSID when join on Group. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000583] [Volunteer Patch][MT6620][Driver] P2P connection of the third peer issue + * Support the third P2P device to join GO/GC group. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000581] [Volunteer Patch][MT6620][Driver] P2P IE in Assoc Req Issue + * Append P2P IE in Assoc Req, so that GC can be discovered in probe response of GO. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000578] [Volunteer Patch][MT6620][Driver] Separate Connection Request from general IOCTL + * Separate connection request from general IOCTL. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 17 2011 yuche.tsai + * NULL + * When AIS is connect to an AP, Hot Spot would be enabled under fixed same channel. + * + * 03 17 2011 yuche.tsai + * NULL + * Solve the Group Info IE in Probe Response incorrect issue. + * + * 03 17 2011 yuche.tsai + * NULL + * Release Channel after Join Complete. + * + * 03 16 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the protected while at P2P start GO, and skip some security check . + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix local configure method issue. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 14 2011 yuche.tsai + * NULL + * . + * + * 03 14 2011 yuche.tsai + * NULL + * Fix password ID issue. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 08 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue[WCXRP00000509] + * [Volunteer Patch][MT6620][Driver] Kernal panic when remove p2p module. + * . + * + * 03 07 2011 yuche.tsai + * [WCXRP00000502] [Volunteer Patch][MT6620][Driver] Fix group ID issue when doing Group Formation. + * . + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 04 2011 wh.su + * [WCXRP00000510] [MT6620 Wi-Fi] [Driver] Fixed the CTIA enter test mode issue + * fixed the p2p action frame type check for device request indication. + * + * 03 02 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Service Discovery RX packet buffer pointer. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Update Service Discovery Related wlanoid function. + * + * 02 21 2011 yuche.tsai + * [WCXRP00000481] [Volunteer Patch][MT6620][FW] Scan hang under concurrent case. + * Fix all BE issue of WSC or P2P IE. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the wsc config method mapping to driver used config method issue. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000479] [Volunteer Patch][MT6620][Driver] Probe Response of P2P using 11b rate. + * Update basic rate to FW, after P2P is initialed. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame during search + * phase do not contain P2P wildcard SSID. + * Use P2P Wildcard SSID when scan type of P2P_WILDCARD_SSID is set. + * + * 02 18 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC IE BE format issue. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 16 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * fixed the probe request send out without WSC IE issue (at P2P). + * + * 02 16 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * If two station connected to the Hot-Spot and one disconnect, FW would get into an infinite loop + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix re-connection issue after RX deauthentication. + * + * 02 15 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Fix conneciton issue after disconnect with AP. + * + * 02 12 2011 yuche.tsai + * [WCXRP00000441] [Volunteer Patch][MT6620][Driver] BoW can not create desired station type when Hot Spot is enabled. + * P2P Create Station Type according to Target BSS capability. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Support Disassoc & Deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Indication Related code. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000429] [Volunteer Patch][MT6620][Driver] Hot Spot Client Limit Issue + * Fix Client Limit Issue. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect + * to target station for AAA module. + * Disconnect every station client when disolve on P2P group. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * 1. Fix Service Disocvery Logical issue. + * 2. Fix a NULL pointer access violation issue when sending deauthentication packet to a class error station. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect + * to target station for AAA module. + * Workaround of disable P2P network. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue + * 1. Fixed SSID wrong length issue. + * 2. Under Hot Spot configuration, there won't be any P2P IE. + * 3. Under Hot Spot configuration, P2P FSM won't get into LISTEN state first. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Modify Start GO flow. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix desire phy type set issue. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Add desire phy type set phase I. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix P2P Disconnect Issue. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Add Service Discovery Function. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix compile error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type Definition. + * + * 01 19 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Add P2P QoS Support. + * + * 01 19 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Null NOA attribute setting when no related parameters. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify AAA flow according to CM's comment. + * + * 01 13 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Resolve Channel ZERO issue. (Uninitialized default channel) + * + * 01 13 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Update P2P State Debug Message. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Fix bug when allocating message buffer. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000353] [Volunteer Patch][MT6620][Driver] Desired Non-HT Rate Set update + * when STA record is created under AP Mode. + * Update Phy Type Set. When legacy client is connected, it can use 11b rate, + * but if the P2P device is connected, 11b rate is not allowed. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. + * 2. Call cnmP2pIsPermit() before active P2P network. + * 3. Add channel selection support for AP mode. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix Bug of reference to NULL pointer. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Modify some behavior of AP mode. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix bug of wrong pointer check. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix Compile Error. + * + * 01 11 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Add station record into client list before change it state from STATE_2 to STATE_3. + * + * 01 05 2011 yuche.tsai + * [WCXRP00000345] [MT6620][Volunteer Patch] P2P may issue a SSID specified scan request, + * but the SSID length is still invalid. + * Specify SSID Type when issue a scan request. + * + * 01 05 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations + * to ease physically continuous memory demands + * correct typo + * + * 01 05 2011 george.huang + * [WCXRP00000343] [MT6620 Wi-Fi] Add TSF reset path for concurrent operation + * modify NOA update path for preventing assertion false alarm. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations + * to ease physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 01 03 2011 wh.su + * [WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * let the p2p ap mode acept a legacy device join. + * + * 12 22 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Fix Compile Error. + * + * 12 15 2010 yuche.tsai + * [WCXRP00000245] 1. Invitation Request/Response. +2. Provision Discovery Request/Response + + * Refine Connection Flow. + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add + * + * 12 08 2010 yuche.tsai + * [WCXRP00000244] [MT6620][Driver] Add station record type for each client when in AP mode. + * Change STA Type under AP mode. We would tell if client is a P2P device or a legacy client + * by checking the P2P IE in assoc req frame. + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * The order of invoking nicUpdateBss() and rlm functions + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation. + * + * 12 02 2010 yuche.tsai + * NULL + * Update P2P Connection Policy for Invitation & Provision Discovery. + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 30 2010 yuche.tsai + * NULL + * Update Configure Method indication & selection for Provision Discovery & GO_NEGO_REQ + * + * 11 30 2010 yuche.tsai + * NULL + * Update RCIP value when RX assoc request frame. + * + * 11 29 2010 yuche.tsai + * NULL + * Update P2P related function for INVITATION & PROVISION DISCOVERY. + * + * 11 26 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Update P2P PS for NOA function. + * + * 11 25 2010 yuche.tsai + * NULL + * Update Code for Invitation Related Function. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] + * Set the Tx lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 05 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * fixed the p2p role code error. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * fixed the ASSERT check error + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 19 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state + * machine[WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * fixed the compiling error. + * + * 10 14 2010 wh.su + * [WCXRP00000102] [MT6620 Wi-Fi] [FW] Add a compiling flag and code for support Direct GO at Android + * adding a code to support Direct GO with a compiling flag . + * + * 10 08 2010 cp.wu + * [WCXRP00000087] [MT6620 Wi-Fi][Driver] Cannot connect to 5GHz AP, driver will cause FW assert. + * correct erroneous logic: specifying eBand with incompatible eSco + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * fixed the compiling error. + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at WinXP. + * + * 09 07 2010 yuche.tsai + * NULL + * Reset Common IE Buffer of P2P INFO when scan request is issued. + * If an action frame other than public action frame is received, return direcly. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 26 2010 yuche.tsai + * NULL + * Add P2P Connection Abort Event Message handler. + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 yuche.tsai + * NULL + * 1. Fix Interface Address from GO Nego Req/Rsp is not correct. + * 2. Fix GO mode does not change media state after station connected. + * 3. Fix STA don't response probe request when there is a connection request. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 20 2010 kevin.huang + * NULL + * Modify AAA Module for changing STA STATE 3 at p2p/bowRunEventAAAComplete() + * + * 08 20 2010 yuche.tsai + * NULL + * Add Glue Layer indication. + * + * 08 17 2010 yuche.tsai + * NULL + * Fix compile warning under Linux. + * + * 08 17 2010 yuche.tsai + * NULL + * Fix some P2P FSM bug. + * + * 08 16 2010 yuche.tsai + * NULL + * Add random Interface Address Generation support. + * + * 08 16 2010 yuche.tsai + * NULL + * Fix some P2P FSM bug. + * + * 08 16 2010 yuche.tsai + * NULL + * Update P2P FSM code for GO Nego. + * + * 08 16 2010 kevin.huang + * NULL + * Refine AAA functions + * + * 08 12 2010 kevin.huang + * NULL + * Refine bssProcessProbeRequest() and bssSendBeaconProbeResponse() + * + * 08 12 2010 yuche.tsai + * NULL + * Join complete indication. + * + * 08 11 2010 yuche.tsai + * NULL + * Add two boolean in connection request. + * Based on these two boolean value, P2P FSM should + * decide to do invitation or group formation or start a GO directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Update P2P FSM, currently P2P Device Discovery is verified. + * + * 08 05 2010 yuche.tsai + * NULL + * Update P2P FSM for group formation. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 03 2010 cp.wu + * NULL + * limit build always needs spin-lock declaration. + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Add P2P FSM code check in. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 yuche.tsai + * + * Update P2P FSM. + * + * 07 09 2010 george.huang + * + * [WPD00001556] Migrate PM variables from FW to driver: for composing QoS Info + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error while enable WIFI_DIRECT support. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Update P2P Function call. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * First draft for migration P2P FSM from FW to Driver. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Rename CFG flag for P2P + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add code to test P2P GO + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add Wi-Fi Direct SSID and P2P GO Test Mode + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Modify code due to BAND_24G define was changed + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Revise data structure to share the same BSS_INFO_T for avoiding coding error + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_ENABLE_WIFI_DIRECT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugP2pState[P2P_STATE_NUM] = { + (PUINT_8) DISP_STRING("P2P_STATE_IDLE"), + (PUINT_8) DISP_STRING("P2P_STATE_SCAN"), + (PUINT_8) DISP_STRING("P2P_STATE_AP_CHANNEL_DETECT"), + (PUINT_8) DISP_STRING("P2P_STATE_REQING_CHANNEL"), + (PUINT_8) DISP_STRING("P2P_STATE_CHNL_ON_HAND"), + (PUINT_8) DISP_STRING("P2P_STATE_GC_JOIN") +}; + +/*lint -restore */ +#else +static UINT_8 apucDebugP2pState[P2P_STATE_NUM] = { + P2P_STATE_IDLE, + P2P_STATE_SCAN, + P2P_STATE_AP_CHANNEL_DETECT, + P2P_STATE_REQING_CHANNEL, + P2P_STATE_CHNL_ON_HAND, + P2P_STATE_GC_JOIN +}; + +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/* p2pStateXXX : Processing P2P FSM related action. + * p2pFSMXXX : Control P2P FSM flow. + * p2pFuncXXX : Function for doing one thing. + */ +VOID p2pFsmInit(IN P_ADAPTER_T prAdapter) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + ASSERT_BREAK(prP2pFsmInfo != NULL); + + LINK_INITIALIZE(&(prP2pFsmInfo->rMsgEventQueue)); + LINK_INITIALIZE(&(prP2pBssInfo->rStaRecOfClientList)); + + prP2pFsmInfo->eCurrentState = prP2pFsmInfo->ePreviousState = P2P_STATE_IDLE; + prP2pFsmInfo->prTargetBss = NULL; + prP2pFsmInfo->fgIsWPSMode = 0; + + cnmTimerInitTimer(prAdapter, + &(prAdapter->rP2pFsmTimeoutTimer), + (PFN_MGMT_TIMEOUT_FUNC) p2pFsmRunEventFsmTimeout, (ULONG) prP2pFsmInfo); + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <2.1> Initiate BSS_INFO_T - Setup HW ID */ + prP2pBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + prP2pBssInfo->ucHwDefaultFixedRateCode = RATE_OFDM_6M; + + prP2pBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prP2pBssInfo->u2BSSBasicRateSet = + rNonHTApModeAttributes[prP2pBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + + prP2pBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prP2pBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + rateGetDataRatesFromRateSet(prP2pBssInfo->u2OperationalRateSet, + prP2pBssInfo->u2BSSBasicRateSet, + prP2pBssInfo->aucAllSupportedRates, &prP2pBssInfo->ucAllSupportedRatesLen); + + prP2pBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, + OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prP2pBssInfo->prBeacon) { + prP2pBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prP2pBssInfo->prBeacon->ucStaRecIndex = 0xFF; /* NULL STA_REC */ + prP2pBssInfo->prBeacon->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } else { + /* Out of memory. */ + ASSERT(FALSE); + } + + prP2pBssInfo->eCurrentOPMode = OP_MODE_NUM; + + prP2pBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prP2pBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; + prP2pBssInfo->ucPrimaryChannel = P2P_DEFAULT_LISTEN_CHANNEL; + prP2pBssInfo->eBand = BAND_2G4; + prP2pBssInfo->eBssSCO = CHNL_EXT_SCN; + + if (prAdapter->rWifiVar.fgSupportQoS) + prP2pBssInfo->fgIsQBSS = TRUE; + else + prP2pBssInfo->fgIsQBSS = FALSE; + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } while (FALSE); + +} /* p2pFsmInit */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to uninitialize the value in P2P_FSM_INFO_T for +* P2P FSM operation +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DEBUGFUNC("p2pFsmUninit()"); + DBGLOG(P2P, INFO, "->p2pFsmUninit()\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, OP_MODE_P2P_DEVICE, TRUE); + + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, P2P_STATE_NUM); + + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + wlanAcquirePowerControl(prAdapter); + + /* Release all pending CMD queue. */ + DBGLOG(P2P, TRACE, "p2pFsmUninit: wlanProcessCommandQueue, num of element:%d\n", + (UINT_32) prAdapter->prGlueInfo->rCmdQueue.u4NumElem); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + + wlanReleasePowerControl(prAdapter); + + /* Release pending mgmt frame, + * mgmt frame may be pending by CMD without resource. + */ + kalClearMgmtFramesByNetType(prAdapter->prGlueInfo, NETWORK_TYPE_P2P_INDEX); + + /* Clear PendingCmdQue */ + wlanReleasePendingCMDbyNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + if (prP2pBssInfo->prBeacon) { + cnmMgtPktFree(prAdapter, prP2pBssInfo->prBeacon); + prP2pBssInfo->prBeacon = NULL; + } + + } while (FALSE); + + return; + +} /* end of p2pFsmUninit() */ + +VOID p2pFsmStateTransition(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + BOOLEAN fgIsTransOut = (BOOLEAN) FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (!IS_BSS_ACTIVE(prP2pBssInfo)) { + if (!cnmP2PIsPermitted(prAdapter)) + return; + + SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + fgIsTransOut = fgIsTransOut ? FALSE : TRUE; + + if (!fgIsTransOut) { +#if DBG + DBGLOG(P2P, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugP2pState[prP2pFsmInfo->eCurrentState], + apucDebugP2pState[eNextState]); +#else + DBGLOG(P2P, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_P2P_IDX, apucDebugP2pState[prP2pFsmInfo->eCurrentState], + apucDebugP2pState[eNextState]); +#endif + + /* Transition into current state. */ + prP2pFsmInfo->ePreviousState = prP2pFsmInfo->eCurrentState; + prP2pFsmInfo->eCurrentState = eNextState; + } + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + if (fgIsTransOut) + p2pStateAbort_IDLE(prAdapter, prP2pFsmInfo, eNextState); + else + fgIsTransOut = p2pStateInit_IDLE(prAdapter, prP2pFsmInfo, prP2pBssInfo, &eNextState); + break; + case P2P_STATE_SCAN: + if (fgIsTransOut) { + /* Scan done / scan canceled. */ + p2pStateAbort_SCAN(prAdapter, prP2pFsmInfo, eNextState); + } else { + /* Initial scan request. */ + p2pStateInit_SCAN(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_AP_CHANNEL_DETECT: + if (fgIsTransOut) { + /* Scan done */ + /* Get sparse channel result. */ + p2pStateAbort_AP_CHANNEL_DETECT(prAdapter, + prP2pFsmInfo, prP2pSpecificBssInfo, eNextState); + } + + else { + /* Initial passive scan request. */ + p2pStateInit_AP_CHANNEL_DETECT(prAdapter, prP2pFsmInfo); + } + + break; + case P2P_STATE_REQING_CHANNEL: + if (fgIsTransOut) { + /* Channel on hand / Channel canceled. */ + p2pStateAbort_REQING_CHANNEL(prAdapter, prP2pFsmInfo, eNextState); + } else { + /* Initial channel request. */ + p2pFuncAcquireCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + break; + case P2P_STATE_CHNL_ON_HAND: + if (fgIsTransOut) { + p2pStateAbort_CHNL_ON_HAND(prAdapter, prP2pFsmInfo, prP2pBssInfo, eNextState); + } else { + /* Initial channel ready. */ + /* Send channel ready event. */ + /* Start a FSM timer. */ + p2pStateInit_CHNL_ON_HAND(prAdapter, prP2pBssInfo, prP2pFsmInfo); + } + + break; + case P2P_STATE_GC_JOIN: + if (fgIsTransOut) { + /* Join complete / join canceled. */ + p2pStateAbort_GC_JOIN(prAdapter, prP2pFsmInfo, &(prP2pFsmInfo->rJoinInfo), eNextState); + } else { + if (prP2pFsmInfo->prTargetBss == NULL) { + ASSERT(FALSE); + } else { + /* Send request to SAA module. */ + p2pStateInit_GC_JOIN(prAdapter, + prP2pFsmInfo, + prP2pBssInfo, + &(prP2pFsmInfo->rJoinInfo), prP2pFsmInfo->prTargetBss); + } + } + + break; + default: + break; + } + + } while (fgIsTransOut); + +} /* p2pFsmStateTransition */ + +VOID p2pFsmRunEventSwitchOPMode(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchOpMode = (P_MSG_P2P_SWITCH_OP_MODE_T) prMsgHdr; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwitchOpMode != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventSwitchOPMode\n"); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prSwitchOpMode->eOpMode >= OP_MODE_NUM) { + ASSERT(FALSE); + break; + } + + /* P2P Device / GC. */ + p2pFuncSwitchOPMode(prAdapter, prP2pBssInfo, prSwitchOpMode->eOpMode, TRUE); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventSwitchOPMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle scan done event during Device Discovery. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventScanDone(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + P_MSG_SCN_SCAN_DONE prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + /* This scan done event is either for "SCAN" phase or "SEARCH" state or "LISTEN" state. + * The scan done for SCAN phase & SEARCH state doesn't imply Device + * Discovery over. + */ + DBGLOG(P2P, TRACE, "P2P Scan Done Event\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + + if (prScanDoneMsg->ucSeqNum != prScanReqInfo->ucSeqNumOfScnMsg) { + /* Scan Done message sequence number mismatch. + * Ignore this event. (P2P FSM issue two scan events.) + */ + /* The scan request has been cancelled. + * Ignore this message. It is possible. + */ + DBGLOG(P2P, TRACE, "P2P Scan Don SeqNum:%d <-> P2P Fsm SCAN Msg:%d\n", + prScanDoneMsg->ucSeqNum, prScanReqInfo->ucSeqNumOfScnMsg); + + break; + } + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_SCAN: + { + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + prScanReqInfo->fgIsAbort = FALSE; + + if (prConnReqInfo->fgIsConnRequest) { + prP2pFsmInfo->prTargetBss = p2pFuncKeepOnConnection(prAdapter, + &prP2pFsmInfo->rConnReqInfo, + &prP2pFsmInfo->rChnlReqInfo, + &prP2pFsmInfo->rScanReqInfo); + if (prP2pFsmInfo->prTargetBss == NULL) + eNextState = P2P_STATE_SCAN; + else + eNextState = P2P_STATE_REQING_CHANNEL; + } else { + eNextState = P2P_STATE_IDLE; + } + + } + break; + case P2P_STATE_AP_CHANNEL_DETECT: + eNextState = P2P_STATE_REQING_CHANNEL; + break; + default: + /* Unexpected channel scan done event without being chanceled. */ + ASSERT(FALSE); + break; + } + + prScanReqInfo->fgIsScanRequest = FALSE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when channel is granted by CNM module from FW. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventChGrant(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_MSG_CH_GRANT_T prMsgChGrant = (P_MSG_CH_GRANT_T) NULL; + UINT_8 ucTokenID = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "P2P Run Event Channel Grant\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prMsgChGrant = (P_MSG_CH_GRANT_T) prMsgHdr; + ucTokenID = prMsgChGrant->ucTokenID; + prP2pFsmInfo->u4GrantInterval = prMsgChGrant->u4GrantInterval; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (ucTokenID == prChnlReqInfo->ucSeqNumOfChReq) { + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_REQING_CHANNEL: + switch (prChnlReqInfo->eChannelReqType) { + case CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL: + eNextState = P2P_STATE_CHNL_ON_HAND; + break; + case CHANNEL_REQ_TYPE_GC_JOIN_REQ: + eNextState = P2P_STATE_GC_JOIN; + break; + case CHANNEL_REQ_TYPE_GO_START_BSS: + eNextState = P2P_STATE_IDLE; + break; + default: + break; + } + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + break; + default: + /* Channel is granted under unexpected state. + * Driver should cancel channel privileagea before leaving the states. + */ + ASSERT(FALSE); + break; + } + + } else { + /* Channel requsted, but released. */ + /* ASSERT(!prChnlReqInfo->fgIsChannelRequested); */ + DBGLOG(P2P, TRACE, "Channel requsted, but released\n"); + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventChGrant */ + +VOID p2pFsmRunEventChannelRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + ENUM_P2P_STATE_T eNextState = P2P_STATE_NUM; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pChnlReqMsg = (P_MSG_P2P_CHNL_REQUEST_T) prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelRequest\n"); + + /* Special case of time renewing for same frequency. */ + if ((prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) && + (prChnlReqInfo->ucReqChnlNum == prP2pChnlReqMsg->rChannelInfo.ucChannelNum) && + (prChnlReqInfo->eBand == prP2pChnlReqMsg->rChannelInfo.eBand) && + (prChnlReqInfo->eChnlSco == prP2pChnlReqMsg->eChnlSco)) { + + ASSERT(prChnlReqInfo->fgIsChannelRequested == TRUE); + ASSERT(prChnlReqInfo->eChannelReqType == CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL); + + prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; + prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; + + /* Re-enter the state. */ + eNextState = P2P_STATE_CHNL_ON_HAND; + } else { + + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + /* Cookie can only be assign after abort.(for indication) */ + prChnlReqInfo->u8Cookie = prP2pChnlReqMsg->u8Cookie; + prChnlReqInfo->ucReqChnlNum = prP2pChnlReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prP2pChnlReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prP2pChnlReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = prP2pChnlReqMsg->u4Duration; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_REMAIN_ON_CHANNEL; + + eNextState = P2P_STATE_REQING_CHANNEL; + } + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, eNextState); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventChannelRequest */ + +VOID p2pFsmRunEventChannelAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prChnlAbortMsg = (P_MSG_P2P_CHNL_ABORT_T) prMsgHdr; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + DBGLOG(P2P, TRACE, "p2pFsmRunEventChannelAbort\n"); + + if ((prChnlAbortMsg->u8Cookie == prChnlReqInfo->u8Cookie) && (prChnlReqInfo->fgIsChannelRequested)) { + + ASSERT((prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL || + (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND))); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventChannelAbort */ + +VOID p2pFsmRunEventScanRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_MSG_P2P_SCAN_REQUEST_T prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + UINT_32 u4ChnlListSize = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pScanReqMsg = (P_MSG_P2P_SCAN_REQUEST_T) prMsgHdr; + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventScanRequest\n"); + + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + ASSERT(prScanReqInfo->fgIsScanRequest == FALSE); + + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + + /* Channel List */ + prScanReqInfo->ucNumChannelList = prP2pScanReqMsg->u4NumChannel; + DBGLOG(P2P, TRACE, "Scan Request Channel List Number: %d\n", prScanReqInfo->ucNumChannelList); + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) { + DBGLOG(P2P, TRACE, "Channel List Number Overloaded: %d, change to: %d\n", + prScanReqInfo->ucNumChannelList, MAXIMUM_OPERATION_CHANNEL_LIST); + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + } + + u4ChnlListSize = sizeof(RF_CHANNEL_INFO_T) * prScanReqInfo->ucNumChannelList; + kalMemCopy(prScanReqInfo->arScanChannelList, prP2pScanReqMsg->arChannelListInfo, u4ChnlListSize); + + /* TODO: I only take the first SSID. Multiple SSID may be needed in the future. */ + /* SSID */ + if (prP2pScanReqMsg->i4SsidNum >= 1) + kalMemCopy(&(prScanReqInfo->rSsidStruct), prP2pScanReqMsg->prSSID, sizeof(P2P_SSID_STRUCT_T)); + else + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + + /* IE Buffer */ + kalMemCopy(prScanReqInfo->aucIEBuf, prP2pScanReqMsg->pucIEBuf, prP2pScanReqMsg->u4IELen); + + prScanReqInfo->u4BufLength = prP2pScanReqMsg->u4IELen; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanRequest */ + +VOID p2pFsmRunEventScanAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventScanAbort\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventScanAbort */ + +VOID p2pFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventAbort\n"); + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_SCAN) { + + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->fgIsAbort = TRUE; + } else if (prP2pFsmInfo->eCurrentState == P2P_STATE_REQING_CHANNEL) { + /* 2012/08/06: frog + * Prevent Start GO. + */ + prP2pBssInfo->eIntendOPMode = OP_MODE_NUM; + } + /* For other state, is there any special action that should be take before leaving? */ + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } else { + /* P2P State IDLE. */ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + if (prChnlReqInfo->fgIsChannelRequested) + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + } + + } while (FALSE); + +} /* p2pFsmRunEventAbort */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle FSM Timeout. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventFsmTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParam) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) ulParam; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + DBGLOG(P2P, TRACE, "P2P FSM Timeout Event\n"); + + switch (prP2pFsmInfo->eCurrentState) { + case P2P_STATE_IDLE: + { + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } else if (IS_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } + break; + +/* case P2P_STATE_SCAN: */ +/* break; */ +/* case P2P_STATE_AP_CHANNEL_DETECT: */ +/* break; */ +/* case P2P_STATE_REQING_CHANNEL: */ +/* break; */ + case P2P_STATE_CHNL_ON_HAND: + switch (prP2pFsmInfo->eListenExted) { + case P2P_DEV_NOT_EXT_LISTEN: + case P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT: + DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", + prP2pFsmInfo->eListenExted); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + break; + case P2P_DEV_EXT_LISTEN_ING: + DBGLOG(P2P, INFO, "p2p timeout, state==P2P_STATE_CHNL_ON_HAND, eListenExted: %d\n", + prP2pFsmInfo->eListenExted); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_CHNL_ON_HAND); + prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_WAITFOR_TIMEOUT; + break; + default: + ASSERT(FALSE); + DBGLOG(P2P, ERROR, + "Current P2P State %d is unexpected for FSM timeout event.\n", + prP2pFsmInfo->eCurrentState); + } + break; +/* case P2P_STATE_GC_JOIN: */ +/* break; */ + default: + break; + } + + } while (FALSE); + +} /* p2pFsmRunEventFsmTimeout */ + +VOID p2pFsmRunEventMgmtFrameTx(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_MSG_P2P_MGMT_TX_REQUEST_T prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventMgmtFrameTx\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prMgmtTxMsg = (P_MSG_P2P_MGMT_TX_REQUEST_T) prMsgHdr; + + p2pFuncTxMgmtFrame(prAdapter, + &prP2pFsmInfo->rMgmtTxInfo, prMgmtTxMsg->prMgmtMsduInfo, prMgmtTxMsg->u8Cookie); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventMgmtTx */ + +VOID p2pFsmRunEventStartAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventStartAP\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) prMsgHdr; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (prP2pStartAPMsg->u4BcnInterval) { + DBGLOG(P2P, TRACE, "Beacon interval updated to :%u\n", prP2pStartAPMsg->u4BcnInterval); + prP2pBssInfo->u2BeaconInterval = (UINT_16) prP2pStartAPMsg->u4BcnInterval; + } else if (prP2pBssInfo->u2BeaconInterval == 0) { + prP2pBssInfo->u2BeaconInterval = DOT11_BEACON_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u4DtimPeriod) { + DBGLOG(P2P, TRACE, "DTIM interval updated to :%u\n", prP2pStartAPMsg->u4DtimPeriod); + prP2pBssInfo->ucDTIMPeriod = (UINT_8) prP2pStartAPMsg->u4DtimPeriod; + } else if (prP2pBssInfo->ucDTIMPeriod == 0) { + prP2pBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + } + + if (prP2pStartAPMsg->u2SsidLen != 0) { + kalMemCopy(prP2pBssInfo->aucSSID, prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen); + kalMemCopy(prP2pSpecificBssInfo->aucGroupSsid, prP2pStartAPMsg->aucSsid, + prP2pStartAPMsg->u2SsidLen); + prP2pBssInfo->ucSSIDLen = prP2pSpecificBssInfo->u2GroupSsidLen = prP2pStartAPMsg->u2SsidLen; + } + + prP2pBssInfo->eHiddenSsidType = prP2pStartAPMsg->ucHiddenSsidType; + + /* TODO: JB */ + /* Privacy & inactive timeout. */ + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + ENUM_P2P_STATE_T eNextState = P2P_STATE_SCAN; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prP2pFsmInfo->eCurrentState != P2P_STATE_SCAN && + prP2pFsmInfo->eCurrentState != P2P_STATE_IDLE) { + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + } + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; + DBGLOG(P2P, INFO, + "NFC:p2pFsmRunEventStartAP,fgIsGOInitialDone[%d]\n", + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone); + + /* 20120118: Moved to p2pFuncSwitchOPMode(). */ + /* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + /* Leave IDLE state. */ + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* sync with firmware */ + /* DBGLOG(P2P, INFO, ("Activate P2P Network.\n")); */ + /* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + /* Key to trigger P2P FSM to allocate channel for AP mode. */ + prP2pBssInfo->eIntendOPMode = OP_MODE_ACCESS_POINT; + + /* Sparse Channel to decide which channel to use. */ + if ((cnmPreferredChannel(prAdapter, + &eBand, + &ucPreferedChnl, + &eSco) == FALSE) && (prP2pConnSettings->ucOperatingChnl == 0)) { + /* Sparse Channel Detection using passive mode. */ + eNextState = P2P_STATE_AP_CHANNEL_DETECT; + } else { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + +#if 1 + /* 2012-01-27: frog - Channel set from upper layer is the first priority. */ + /* Because the channel & beacon is decided by p2p_supplicant. */ + if (prP2pConnSettings->ucOperatingChnl != 0) { + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + } + + else { + ASSERT(ucPreferedChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + } +#else + if (ucPreferedChnl) { + prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prP2pSpecificBssInfo->eRfBand = eBand; + } else { + ASSERT(prP2pConnSettings->ucOperatingChnl != 0); + prP2pSpecificBssInfo->ucPreferredChannel = prP2pConnSettings->ucOperatingChnl; + prP2pSpecificBssInfo->eRfBand = prP2pConnSettings->eBand; + } + +#endif + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + + DBGLOG(P2P, INFO, "p2pFsmRunEventStartAP GO Scan\n"); + } + + /* If channel is specified, use active scan to shorten the scan time. */ + p2pFsmStateTransition(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo, eNextState); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventStartAP */ + +VOID p2pFsmRunEventNetDeviceRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_NETDEV_REGISTER_T prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventNetDeviceRegister\n"); + + prNetDevRegisterMsg = (P_MSG_P2P_NETDEV_REGISTER_T) prMsgHdr; + + if (prNetDevRegisterMsg->fgIsEnable) { + p2pSetMode((prNetDevRegisterMsg->ucMode == 1) ? TRUE : FALSE); + + if (p2pLaunch(prAdapter->prGlueInfo)) + ASSERT(prAdapter->fgIsP2PRegistered); + + } else { + if (prAdapter->fgIsP2PRegistered) + p2pRemove(prAdapter->prGlueInfo); + + } + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventNetDeviceRegister */ + +VOID p2pFsmRunEventUpdateMgmtFrame(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_MGMT_FRAME_UPDATE_T prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventUpdateMgmtFrame\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pMgmtFrameUpdateMsg = (P_MSG_P2P_MGMT_FRAME_UPDATE_T) prMsgHdr; + + switch (prP2pMgmtFrameUpdateMsg->eBufferType) { + case ENUM_FRAME_TYPE_EXTRA_IE_BEACON: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_ASSOC_RSP: + break; + case ENUM_FRAME_TYPE_EXTRA_IE_PROBE_RSP: + break; + case ENUM_FRAME_TYPE_PROBE_RSP_TEMPLATE: + break; + case ENUM_FRAME_TYPE_BEACON_TEMPLATE: + break; + default: + break; + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventUpdateMgmtFrame */ + +VOID p2pFsmRunEventBeaconUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_BEACON_UPDATE_T prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconUpdate\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) prMsgHdr; + + p2pFuncBeaconUpdate(prAdapter, + prP2pBssInfo, + &prP2pFsmInfo->rBcnContentInfo, + prBcnUpdateMsg->pucBcnHdr, + prBcnUpdateMsg->u4BcnHdrLen, + prBcnUpdateMsg->pucBcnBody, prBcnUpdateMsg->u4BcnBodyLen); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) && + (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + /* nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventBeaconUpdate */ + +VOID p2pFsmRunEventStopAP(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventStopAP\n"); + + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + && (prP2pBssInfo->eIntendOPMode == OP_MODE_NUM)) { + /* AP is created, Beacon Update. */ + + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + + DBGLOG(P2P, TRACE, "Stop Beaconing\n"); + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + } + /* 20120118: Moved to p2pFuncSwitchOPMode(). */ + /* UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + /* Enter IDLE state. */ + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + DBGLOG(P2P, INFO, "Re activate P2P Network.\n"); + nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + + nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); + +#if CFG_SUPPORT_WFD + p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); +#endif + + /* p2pFsmRunEventAbort(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo); */ + p2pFsmStateTransition(prAdapter, prAdapter->rWifiVar.prP2pFsmInfo, P2P_STATE_IDLE); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventStopAP */ + +VOID p2pFsmRunEventConnectionRequest(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) prMsgHdr; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionRequest\n"); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + + SET_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Make sure the state is in IDLE state. */ + p2pFsmRunEventAbort(prAdapter, prP2pFsmInfo); + + /* Update connection request information. */ + prConnReqInfo->fgIsConnRequest = TRUE; + COPY_MAC_ADDR(prConnReqInfo->aucBssid, prConnReqMsg->aucBssid); + kalMemCopy(&(prConnReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + kalMemCopy(prConnReqInfo->aucIEBuf, prConnReqMsg->aucIEBuf, prConnReqMsg->u4IELen); + prConnReqInfo->u4BufLength = prConnReqMsg->u4IELen; + + /* Find BSS Descriptor first. */ + prP2pFsmInfo->prTargetBss = scanP2pSearchDesc(prAdapter, prP2pBssInfo, prConnReqInfo); + + if (prP2pFsmInfo->prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest,Trigger New Scan\n"); + + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_SPECIFIED; + prScanReqInfo->arScanChannelList[0].ucChannelNum = prConnReqMsg->rChannelInfo.ucChannelNum; + kalMemCopy(&(prScanReqInfo->rSsidStruct), &(prConnReqMsg->rSsid), sizeof(P2P_SSID_STRUCT_T)); + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prConnReqMsg->rChannelInfo.ucChannelNum; + prChnlReqInfo->eBand = prConnReqMsg->rChannelInfo.eBand; + prChnlReqInfo->eChnlSco = prConnReqMsg->eChnlSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + DBGLOG(P2P, INFO, "p2pFsmRunEventConnectionRequest, Report the Connecting BSS Again.\n"); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_REQING_CHANNEL); + } + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventConnectionRequest */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to handle Connection Request from Supplicant. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventConnectionAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + /* P_STA_RECORD_T prTargetStaRec = (P_STA_RECORD_T)NULL; */ + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventConnectionAbort: Connection Abort.\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) prMsgHdr; + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + { + UINT_8 aucBCBSSID[] = BC_BSSID; + + if (!prP2pBssInfo->prStaRecOfAP) { + DBGLOG(P2P, TRACE, "GO's StaRec is NULL\n"); + break; + } + if (UNEQUAL_MAC_ADDR(prP2pBssInfo->prStaRecOfAP->aucMacAddr, prDisconnMsg->aucTargetID) + && UNEQUAL_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCBSSID)) { + DBGLOG(P2P, TRACE, + "Unequal MAC ADDR [ %pM : %pM ]\n", + prP2pBssInfo->prStaRecOfAP->aucMacAddr, + prDisconnMsg->aucTargetID); + break; + } + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, 0, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); + + /* Stop rejoin timer if it is started. */ + /* TODO: If it has. */ + + p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + /* prTargetStaRec = prP2pBssInfo->prStaRecOfAP; */ + + /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). */ + /* hit prStaRecOfAP == NULL. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + prP2pBssInfo->prStaRecOfAP = NULL; + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + break; + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + /* Search specific client device, and disconnect. */ + /* 1. Send deauthentication frame. */ + /* 2. Indication: Device disconnect. */ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + + DBGLOG(P2P, TRACE, + "Disconnecting with Target ID: %pM\n", + prDisconnMsg->aucTargetID); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prDisconnMsg->aucTargetID)) { + + DBGLOG(P2P, TRACE, + "Disconnecting: %pM\n", + prCurrStaRec->aucMacAddr); + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Glue layer indication. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ + + /* Send deauth & do indication. */ + p2pFuncDisconnect(prAdapter, prCurrStaRec, prDisconnMsg->fgSendDeauth, + prDisconnMsg->u2ReasonCode); + + /* prTargetStaRec = prCurrStaRec; */ + + break; + } + } + + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + } while (FALSE); + + /* 20120830 moved into p2pFuncDisconnect() */ + /* if ((!prDisconnMsg->fgSendDeauth) && (prTargetStaRec)) { */ + /* cnmStaRecFree(prAdapter, prTargetStaRec, TRUE); */ + /* } */ + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventConnectionAbort */ + +VOID p2pFsmRunEventDissolve(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + + /* TODO: */ + + DBGLOG(P2P, TRACE, "p2pFsmRunEventDissolve\n"); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} + +WLAN_STATUS +p2pFsmRunEventDeauthTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + DBGLOG(P2P, INFO, "Deauth TX Done Status: %d, seqNo %d\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Station Record NULL, Index:%d\n", prMsduInfo->ucStaRecIndex); + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + + /**/ cnmStaRecFree(prAdapter, prStaRec, TRUE); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { + DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + } + + /* Because the eConnectionState is changed before Deauth TxDone. Dont Check eConnectionState */ + /* if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { */ + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + /* } */ + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* p2pFsmRunEventDeauthTxDone */ + +WLAN_STATUS +p2pFsmRunEventMgmtFrameTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo = (P_P2P_MGMT_TX_REQ_INFO_T) NULL; + BOOLEAN fgIsSuccess = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prMgmtTxReqInfo = &(prP2pFsmInfo->rMgmtTxInfo); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(P2P, INFO, "Mgmt Frame TX Fail, Status: %d, seq NO. %d, Cookie: 0x%llx\n", + rTxDoneStatus, prMsduInfo->ucTxSeqNum, prMgmtTxReqInfo->u8Cookie); + } else { + fgIsSuccess = TRUE; + DBGLOG(P2P, TRACE, "Mgmt Frame TX Done.\n"); + } + + if (prMgmtTxReqInfo->prMgmtTxMsdu == prMsduInfo) { + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + fgIsSuccess, + prMsduInfo->prPacket, (UINT_32) prMsduInfo->u2FrameLength); + + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + } + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; + +} /* p2pFsmRunEventMgmtFrameTxDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when JOIN complete message event is received from SAA. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventJoinComplete(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; + P_MSG_JOIN_COMP_T prJoinCompMsg = (P_MSG_JOIN_COMP_T) NULL; + P_SW_RFB_T prAssocRspSwRfb = (P_SW_RFB_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + DBGLOG(P2P, TRACE, "P2P Join Complete\n"); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + if (prP2pFsmInfo == NULL) { + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + if (prMsgHdr == NULL) + return; + prJoinCompMsg = (P_MSG_JOIN_COMP_T) prMsgHdr; + prAssocRspSwRfb = prJoinCompMsg->prSwRfb; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + prStaRec = prJoinCompMsg->prStaRec; + + /* Check SEQ NUM */ + if (prJoinCompMsg->ucSeqNum == prJoinInfo->ucSeqNumOfReqMsg) { + ASSERT(prStaRec == prJoinInfo->prTargetStaRec); + prJoinInfo->fgIsJoinComplete = TRUE; + + if (prJoinCompMsg->rJoinStatus == WLAN_STATUS_SUCCESS) { + + /* 4 <1.1> Change FW's Media State immediately. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* 4 <1.2> Deactivate previous AP's STA_RECORD_T in Driver if have. */ + if ((prP2pBssInfo->prStaRecOfAP) && (prP2pBssInfo->prStaRecOfAP != prStaRec)) { + cnmStaRecChangeState(prAdapter, prP2pBssInfo->prStaRecOfAP, + STA_STATE_1); + + cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); + + prP2pBssInfo->prStaRecOfAP = NULL; + } + /* 4 <1.3> Update BSS_INFO_T */ + p2pFuncUpdateBssInfoForJOIN(prAdapter, prP2pFsmInfo->prTargetBss, prStaRec, + prAssocRspSwRfb); + + /* 4 <1.4> Activate current AP's STA_RECORD_T in Driver. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DBGLOG(P2P, INFO, "P2P GC Join Success\n"); + +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* <1.5> Update RSSI if necessary */ + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, + (INT_8) (RCPI_TO_dBm(prStaRec->ucRCPI)), 0); +#endif + + /* 4 <1.6> Indicate Connected Event to Host immediately. */ + /* Require BSSID, Association ID, Beacon Interval.. from AIS_BSS_INFO_T */ + /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_CONNECTED, */ + /* prStaRec->aucMacAddr); */ + if (prP2pFsmInfo->prTargetBss) + scanReportBss2Cfg80211(prAdapter, OP_MODE_P2P_DEVICE, + prP2pFsmInfo->prTargetBss); + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_CONNECT); + + } else { + /* Join Fail */ + /* 4 <2.1> Redo JOIN process with other Auth Type if possible */ + if (p2pFuncRetryJOIN(prAdapter, prStaRec, prJoinInfo) == FALSE) { + P_BSS_DESC_T prBssDesc; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + prBssDesc = prP2pFsmInfo->prTargetBss; + + ASSERT(prBssDesc); + ASSERT(prBssDesc->fgIsConnecting); + + prBssDesc->fgIsConnecting = FALSE; + + if (prStaRec->ucJoinFailureCount >= 3) { + + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + &prP2pFsmInfo->rConnReqInfo, + prJoinInfo->aucIEBuf, + prJoinInfo->u4BufLength, + prStaRec->u2StatusCode, + WLAN_STATUS_MEDIA_CONNECT); + } else { + /* Sometime the GO is not ready to response auth. */ + /* Connect it again */ + prP2pFsmInfo->prTargetBss = NULL; + } + DBGLOG(P2P, INFO, "P2P GC Join Failed\n"); + + } + + } + } + } + + if (prAssocRspSwRfb) + nicRxReturnRFB(prAdapter, prAssocRspSwRfb); + + if (prP2pFsmInfo->eCurrentState == P2P_STATE_GC_JOIN) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + /* Return to IDLE state. */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } else { + /* p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); */ + /* one more scan */ + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_SCAN); + } + } + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + +} /* p2pFsmRunEventJoinComplete */ + +VOID p2pFsmRunEventMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) prMsgHdr; + + p2pFuncMgmtFrameRegister(prAdapter, + prMgmtFrameRegister->u2FrameType, + prMgmtFrameRegister->fgIsRegister, &prP2pFsmInfo->u4P2pPacketFilter); + + } while (FALSE); + + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + + return; + +} /* p2pFsmRunEventMgmtFrameRegister */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxDeauthentication(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2ReasonCode = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + if (prStaRec == NULL) + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + if (!prStaRec) + break; + + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + if (prStaRec->ucStaState == STA_STATE_1) + break; + + DBGLOG(P2P, TRACE, "RX Deauth\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DEAUTH_FRAME_T prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + prStaRec->u2ReasonCode = u2ReasonCode; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDeauthFrame->aucInfoElem, u2IELength, u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + + prP2pBssInfo->prStaRecOfAP = NULL; + DBGLOG(P2P, INFO, "GC RX Deauth Reason: %d\n", u2ReasonCode); + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (authProcessRxDeauthFrame(prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ + + /* Indicate disconnect to Host. */ + DBGLOG(P2P, INFO, "GO RX Deauth Reason: %d\n", u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + /* Findout why someone sent deauthentication frame to us. */ + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "Deauth Reason:%d\n", u2ReasonCode); + + } while (FALSE); +} /* p2pFsmRunEventRxDeauthentication */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is call when RX deauthentication frame from the AIR. +* If we are under STA mode, we would go back to P2P Device. +* If we are under AP mode, we would stay in AP mode until disconnect event from HOST. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxDisassociation(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + UINT_16 u2ReasonCode = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo == NULL) + break; + + if (prStaRec == NULL) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + break; + } + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prStaRec->ucStaState == STA_STATE_1) + break; + + DBGLOG(P2P, TRACE, "RX Disassoc\n"); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_WLAN_DISASSOC_FRAME_T prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + UINT_16 u2IELength = 0; + + ASSERT(prP2pBssInfo->prStaRecOfAP == prStaRec); + + if (prP2pBssInfo->prStaRecOfAP != prStaRec) + break; + + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + REASON_CODE_FIELD_LEN); + + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, + prDisassocFrame->aucInfoElem, + u2IELength, prStaRec->u2ReasonCode, + WLAN_STATUS_MEDIA_DISCONNECT); + + prP2pBssInfo->prStaRecOfAP = NULL; + + DBGLOG(P2P, INFO, "GC RX Disassoc Reason %d\n", prStaRec->u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, prStaRec->u2ReasonCode); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + break; + case OP_MODE_ACCESS_POINT: + /* Delete client from client list. */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prP2pBssInfo->aucBSSID, &u2ReasonCode) == WLAN_STATUS_SUCCESS) { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_STA_RECORD_T prCurrStaRec = (P_STA_RECORD_T) NULL; + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + prCurrStaRec = LINK_ENTRY(prLinkEntry, STA_RECORD_T, rLinkEntry); + + ASSERT(prCurrStaRec); + + if (EQUAL_MAC_ADDR(prCurrStaRec->aucMacAddr, prStaRec->aucMacAddr)) { + + /* Remove STA from client list. */ + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, + &prCurrStaRec->rLinkEntry); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); */ + + /* Indicate disconnect to Host. */ + DBGLOG(P2P, INFO, "GO RX Disassoc Reason %d\n", u2ReasonCode); + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, u2ReasonCode); + + break; + } + } + } + break; + case OP_MODE_P2P_DEVICE: + default: + ASSERT(FALSE); + break; + } + + } while (FALSE); +} /* p2pFsmRunEventRxDisassociation */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called when a probe request frame is received. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is accepted & need cancel scan request. +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFsmRunEventRxProbeResponseFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_BSS_DESC_T prBssDesc) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_WLAN_MAC_MGMT_HEADER_T prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (prBssDesc != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + /* There is a connection request. */ + prMgtHdr = (P_WLAN_MAC_MGMT_HEADER_T) prSwRfb->pvHeader; + + } while (FALSE); + +} /* p2pFsmRunEventRxProbeResponseFrame */ + +VOID p2pFsmRunEventBeaconTimeout(IN P_ADAPTER_T prAdapter) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "p2pFsmRunEventBeaconTimeout: Beacon Timeout\n"); + + /* Only client mode would have beacon lost event. */ + ASSERT(prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* Indicate disconnect to Host. */ + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, REASON_CODE_DISASSOC_INACTIVITY, + WLAN_STATUS_MEDIA_DISCONNECT); + + if (prP2pBssInfo->prStaRecOfAP != NULL) { + P_STA_RECORD_T prStaRec = prP2pBssInfo->prStaRecOfAP; + + prP2pBssInfo->prStaRecOfAP = NULL; + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_DISASSOC_LEAVING_BSS); + + /* 20120830 moved into p2pFuncDisconnect() */ + /* cnmStaRecFree(prAdapter, prP2pBssInfo->prStaRecOfAP, TRUE); */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + SET_NET_PWR_STATE_IDLE(prAdapter, NETWORK_TYPE_P2P_INDEX); + p2pFsmStateTransition(prAdapter, prP2pFsmInfo, P2P_STATE_IDLE); + + } + } + } while (FALSE); + +} /* p2pFsmRunEventBeaconTimeout */ + +VOID p2pFsmRunEventExtendListen(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = NULL; + struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prExtListenMsg = NULL; + + ASSERT_BREAK((prAdapter != NULL) && (prMsgHdr != NULL)); + + prExtListenMsg = (struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *) prMsgHdr; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + ASSERT_BREAK(prP2pFsmInfo); + + if (!prExtListenMsg->wait) { + DBGLOG(P2P, INFO, "reset listen interval\n"); + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + if (prP2pFsmInfo && (prP2pFsmInfo->eListenExted == P2P_DEV_NOT_EXT_LISTEN)) { + DBGLOG(P2P, INFO, "try to ext listen, p2p state: %d\n", prP2pFsmInfo->eCurrentState); + if (prP2pFsmInfo->eCurrentState == P2P_STATE_CHNL_ON_HAND) { + DBGLOG(P2P, INFO, "here to ext listen interval\n"); + prP2pFsmInfo->eListenExted = P2P_DEV_EXT_LISTEN_ING; + } + } + if (prMsgHdr) + cnmMemFree(prAdapter, prMsgHdr); +} /* p2pFsmRunEventUpdateMgmtFrame */ + +#if CFG_SUPPORT_WFD +VOID p2pFsmRunEventWfdSettingUpdate(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + WLAN_STATUS rStatus; + + DBGLOG(P2P, INFO, "p2pFsmRunEventWfdSettingUpdate\n"); + + do { + ASSERT_BREAK((prAdapter != NULL)); + + if (prMsgHdr != NULL) { + prMsgWfdCfgSettings = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) prMsgHdr; + prWfdCfgSettings = prMsgWfdCfgSettings->prWfdCfgSettings; + } else { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + } + + DBGLOG(P2P, INFO, "WFD Enalbe %x info %x state %x flag %x adv %x\n", + prWfdCfgSettings->ucWfdEnable, + prWfdCfgSettings->u2WfdDevInfo, + (UINT_32) prWfdCfgSettings->u4WfdState, + (UINT_32) prWfdCfgSettings->u4WfdFlag, + (UINT_32) prWfdCfgSettings->u4WfdAdvancedFlag); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_WFD_CTRL, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(WFD_CFG_SETTINGS_T), /* u4SetQueryInfoLen */ + (PUINT_8) prWfdCfgSettings, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + } while (FALSE); + + return; + +} + +/* p2pFsmRunEventWfdSettingUpdate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pGenerateP2P_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec != NULL) { + if (IS_STA_P2P_TYPE(prStaRec)) { + /* Do nothing */ + /* TODO: */ + } + } + + } while (FALSE); + + return; + +} /* end of p2pGenerateP2P_IEForAssocReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Probe Request frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pGenerateP2P_IEForProbeReq(IN P_ADAPTER_T prAdapter, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + ASSERT(prAdapter); + ASSERT(pucBuf); + + /* TODO: */ + + return; + +} /* end of p2pGenerateP2P_IEForProbReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pCalculateP2P_IELenForProbeReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + /* TODO: */ + + return 0; + +} /* end of p2pCalculateP2P_IELenForProbeReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Tx Fail of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pRunEventAAATxFail(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prStaRec); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + p2pFuncDisconnect(prAdapter, prStaRec, FALSE, REASON_CODE_UNSPECIFIED); + + /* 20120830 moved into p2puUncDisconnect. */ + /* cnmStaRecFree(prAdapter, prStaRec, TRUE); */ + +} /* p2pRunEventAAATxFail */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS p2pRunEventAAAComplete(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaState; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + eOriMediaState = prP2pBssInfo->eConnectionState; + + if (prStaRec != NULL) + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + else + break; + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + + bssAddStaRecToClientList(prAdapter, prP2pBssInfo, prStaRec); + + prStaRec->u2AssocId = bssAssignAssocID(prStaRec); + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem > P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + rStatus = WLAN_STATUS_RESOURCES; + break; + } + DBGLOG(P2P, INFO, "P2P GO Join Complete\n"); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_CONNECTED); + + /* Update Connected state to FW. */ + if (eOriMediaState != prP2pBssInfo->eConnectionState) + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAAComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will indicate the Event of Successful Completion of AAA Module. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS p2pRunEventAAASuccess(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + /* Glue layer indication. */ + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, TRUE); + + } while (FALSE); + + return rStatus; +} /* p2pRunEventAAASuccess */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS p2pRxPublicActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_P2P_PUBLIC_ACTION_FRAME_T prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + ASSERT(prSwRfb); + ASSERT(prAdapter); + + prPublicActionFrame = (P_P2P_PUBLIC_ACTION_FRAME_T) prSwRfb->pvHeader; + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + DBGLOG(P2P, TRACE, "RX Public Action Frame Token:%d.\n", prPublicActionFrame->ucDialogToken); + + if (prPublicActionFrame->ucCategory != CATEGORY_PUBLIC_ACTION) + return rWlanStatus; + + switch (prPublicActionFrame->ucAction) { + case ACTION_PUBLIC_WIFI_DIRECT: + break; + case ACTION_GAS_INITIAL_REQUEST: + case ACTION_GAS_INITIAL_RESPONSE: + case ACTION_GAS_COMEBACK_REQUEST: + case ACTION_GAS_COMEBACK_RESPONSE: + break; + default: + break; + } + + return rWlanStatus; +} /* p2pRxPublicActionFrame */ + +WLAN_STATUS p2pRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_P2P_ACTION_FRAME_T prP2pActionFrame = (P_P2P_ACTION_FRAME_T) NULL; + UINT_8 aucOui[3] = VENDOR_OUI_WFA_SPECIFIC; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pActionFrame = (P_P2P_ACTION_FRAME_T) prSwRfb->pvHeader; + + if (prP2pActionFrame->ucCategory != CATEGORY_VENDOR_SPECIFIC_ACTION) { + DBGLOG(P2P, TRACE, "RX Action Frame but not vendor specific.\n"); + break; + } + + if ((prP2pActionFrame->ucOuiType != VENDOR_OUI_TYPE_P2P) || + (prP2pActionFrame->aucOui[0] != aucOui[0]) || + (prP2pActionFrame->aucOui[1] != aucOui[1]) || (prP2pActionFrame->aucOui[2] != aucOui[2])) { + DBGLOG(P2P, TRACE, "RX Vendor Specific Action Frame but not P2P Type or not WFA OUI.\n"); + break; + } + + } while (FALSE); + + return rWlanStatus; +} /* p2pRxActionFrame */ + +VOID +p2pProcessEvent_UpdateNOAParam(IN P_ADAPTER_T prAdapter, + UINT_8 ucNetTypeIndex, P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam) +{ + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + UINT_32 i; + BOOLEAN fgNoaAttrExisted = FALSE; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIndex]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + prP2pSpecificBssInfo->fgEnableOppPS = prEventUpdateNoaParam->fgEnableOppPS; + prP2pSpecificBssInfo->u2CTWindow = prEventUpdateNoaParam->u2CTWindow; + prP2pSpecificBssInfo->ucNoAIndex = prEventUpdateNoaParam->ucNoAIndex; + prP2pSpecificBssInfo->ucNoATimingCount = prEventUpdateNoaParam->ucNoATimingCount; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->fgEnableOppPS; + + DBGLOG(P2P, INFO, "Update NoA Count=%d.\n", prEventUpdateNoaParam->ucNoATimingCount); + + ASSERT(prP2pSpecificBssInfo->ucNoATimingCount <= P2P_MAXIMUM_NOA_COUNT); + + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + /* in used */ + prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse = prEventUpdateNoaParam->arEventNoaTiming[i].fgIsInUse; + /* count */ + prP2pSpecificBssInfo->arNoATiming[i].ucCount = prEventUpdateNoaParam->arEventNoaTiming[i].ucCount; + /* duration */ + prP2pSpecificBssInfo->arNoATiming[i].u4Duration = prEventUpdateNoaParam->arEventNoaTiming[i].u4Duration; + /* interval */ + prP2pSpecificBssInfo->arNoATiming[i].u4Interval = prEventUpdateNoaParam->arEventNoaTiming[i].u4Interval; + /* start time */ + prP2pSpecificBssInfo->arNoATiming[i].u4StartTime = + prEventUpdateNoaParam->arEventNoaTiming[i].u4StartTime; + + fgNoaAttrExisted |= prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse; + } + + prP2pSpecificBssInfo->fgIsNoaAttrExisted = fgNoaAttrExisted; + + /* update beacon content by the change */ + bssUpdateBeaconContent(prAdapter, ucNetTypeIndex); +} + +#endif /* CFG_ENABLE_WIFI_DIRECT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c new file mode 100644 index 0000000000000..586a74721b3bf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_func.c @@ -0,0 +1,3796 @@ +#include "precomp.h" +#include + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + +APPEND_VAR_ATTRI_ENTRY_T txAssocRspAttributesTable[] = { + {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS), NULL, p2pFuncAppendAttriStatusForAssocRsp} /* 0 */ + , {(P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING), NULL, p2pFuncAppendAttriExtListenTiming} /* 8 */ +}; + +APPEND_VAR_IE_ENTRY_T txProbeRspIETable[] = { + {(ELEM_HDR_LEN + (RATE_NUM - ELEM_MAX_LEN_SUP_RATES)), NULL, bssGenerateExtSuppRate_IE} /* 50 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_ERP), NULL, rlmRspGenerateErpIE} /* 42 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP), NULL, rlmRspGenerateHtCapIE} /* 45 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP), NULL, rlmRspGenerateHtOpIE} /* 61 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_RSN), NULL, rsnGenerateRSNIE} /* 48 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN), NULL, rlmRspGenerateObssScanIE} /* 74 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP), NULL, rlmRspGenerateExtCapIE} /* 127 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WPA), NULL, rsnGenerateWpaNoneIE} /* 221 */ + , {(ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_PARAM), NULL, mqmGenerateWmmParamIE} /* 221 */ +}; + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Function for requesting scan. There is an option to do ACTIVE or PASSIVE scan. +* +* @param eScanType - Specify the scan type of the scan request. It can be an ACTIVE/PASSIVE +* Scan. +* eChannelSet - Specify the preferred channel set. +* A FULL scan would request a legacy full channel normal scan.(usually ACTIVE). +* A P2P_SOCIAL scan would scan 1+6+11 channels.(usually ACTIVE) +* A SPECIFIC scan would only 1/6/11 channels scan. (Passive Listen/Specific Search) +* ucChannelNum - A specific channel number. (Only when channel is specified) +* eBand - A specific band. (Only when channel is specified) +* +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncRequestScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + + P_MSG_SCN_SCAN_REQ prScanReq = (P_MSG_SCN_SCAN_REQ) NULL; + /*NFC Beam + Indication */ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + BOOLEAN fgIsPureAP = FALSE; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + fgIsPureAP = prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; + + DEBUGFUNC("p2pFuncRequestScan()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanReqInfo != NULL)); + + if (prScanReqInfo->eChannelSet == SCAN_CHANNEL_SPECIFIED) { + ASSERT_BREAK(prScanReqInfo->ucNumChannelList > 0); + DBGLOG(P2P, LOUD, + "P2P Scan Request Channel:%d\n", prScanReqInfo->arScanChannelList[0].ucChannelNum); + } + + prScanReq = (P_MSG_SCN_SCAN_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + if (!prScanReq) { + ASSERT(0); /* Can't trigger SCAN FSM */ + break; + } + + prScanReq->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_REQ; + prScanReq->ucSeqNum = ++prScanReqInfo->ucSeqNumOfScnMsg; + prScanReq->ucNetTypeIndex = (UINT_8) NETWORK_TYPE_P2P_INDEX; + prScanReq->eScanType = prScanReqInfo->eScanType; + prScanReq->eScanChannel = prScanReqInfo->eChannelSet; + prScanReq->u2IELen = 0; + + /* Copy IE for Probe Request. */ + if (prScanReqInfo->u4BufLength > MAX_IE_LENGTH) + prScanReqInfo->u4BufLength = MAX_IE_LENGTH; + kalMemCopy(prScanReq->aucIE, prScanReqInfo->aucIEBuf, prScanReqInfo->u4BufLength); + prScanReq->u2IELen = (UINT_16) prScanReqInfo->u4BufLength; + + prScanReq->u2ChannelDwellTime = prScanReqInfo->u2PassiveDewellTime; + + switch (prScanReqInfo->eChannelSet) { + case SCAN_CHANNEL_SPECIFIED: + { + UINT_32 u4Idx = 0; + P_RF_CHANNEL_INFO_T prDomainInfo = + (P_RF_CHANNEL_INFO_T) prScanReqInfo->arScanChannelList; + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + + + if (prScanReqInfo->ucNumChannelList > MAXIMUM_OPERATION_CHANNEL_LIST) + prScanReqInfo->ucNumChannelList = MAXIMUM_OPERATION_CHANNEL_LIST; + + for (u4Idx = 0; u4Idx < prScanReqInfo->ucNumChannelList; u4Idx++) { + prScanReq->arChnlInfoList[u4Idx].ucChannelNum = prDomainInfo->ucChannelNum; + prScanReq->arChnlInfoList[u4Idx].eBand = prDomainInfo->eBand; + prDomainInfo++; + } + + prScanReq->ucChannelListNum = prScanReqInfo->ucNumChannelList; + + /*NFC Beam + Indication */ + prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; + if (prChnlReqInfo->eChannelReqType == CHANNEL_REQ_TYPE_GO_START_BSS && + prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + !fgIsPureAP) { + prScanReq->ucChannelListNum = 1; + prScanReq->arChnlInfoList[0].ucChannelNum = prChnlReqInfo->ucReqChnlNum; + prScanReq->arChnlInfoList[0].eBand = prChnlReqInfo->eBand; + + DBGLOG(P2P, INFO, + "NFC:GO Skip Scan and Only Froce on %s[%d]\n", + prChnlReqInfo->eBand == 1 ? "2.4G" : "5G", + prChnlReqInfo->ucReqChnlNum); + } + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); + + /* For compatible. */ + if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, + prScanReq->aucSSID, prScanReq->ucSSIDLength)) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + } else if (prScanReq->ucSSIDLength != 0) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + + } + break; + + case SCAN_CHANNEL_FULL: + { + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); + + /* For compatible. */ + if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, + prScanReq->aucSSID, prScanReq->ucSSIDLength)) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + } else if (prScanReq->ucSSIDLength != 0) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + } + break; + + case SCAN_CHANNEL_2G4: + { + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); + + /* For compatible. */ + if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, + prScanReq->aucSSID, prScanReq->ucSSIDLength)) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + } else if (prScanReq->ucSSIDLength != 0) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + } + break; + + case SCAN_CHANNEL_P2P_SOCIAL: + { + UINT_8 aucP2pSsid[] = P2P_WILDCARD_SSID; + + COPY_SSID(prScanReq->aucSSID, + prScanReq->ucSSIDLength, + prScanReqInfo->rSsidStruct.aucSsid, prScanReqInfo->rSsidStruct.ucSsidLen); + + /* For compatible. */ + if (EQUAL_SSID(aucP2pSsid, P2P_WILDCARD_SSID_LEN, + prScanReq->aucSSID, prScanReq->ucSSIDLength)) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_P2P_WILDCARD; + } else if (prScanReq->ucSSIDLength != 0) { + prScanReq->ucSSIDType = SCAN_REQ_SSID_SPECIFIED; + } + } + break; + default: + /* Currently there is no other scan channel set. */ + ASSERT(FALSE); + break; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReq, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncRequestScan */ + +VOID p2pFuncCancelScan(IN P_ADAPTER_T prAdapter, IN P_P2P_SCAN_REQ_INFO_T prScanInfo) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancelMsg = (P_MSG_SCN_SCAN_CANCEL) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prScanInfo != NULL)); + + if (!prScanInfo->fgIsScanRequest) + break; + + if (prScanInfo->ucSeqNumOfScnMsg) { + /* There is a channel privilege on hand. */ + DBGLOG(P2P, TRACE, "P2P Cancel Scan\n"); + + prScanCancelMsg = + (P_MSG_SCN_SCAN_CANCEL) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_CANCEL)); + if (!prScanCancelMsg) { + /* Buffer not enough, can not cancel scan request. */ + DBGLOG(P2P, TRACE, "Buffer not enough, can not cancel scan.\n"); + ASSERT(FALSE); + break; + } + + prScanCancelMsg->rMsgHdr.eMsgId = MID_P2P_SCN_SCAN_CANCEL; + prScanCancelMsg->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prScanCancelMsg->ucSeqNum = prScanInfo->ucSeqNumOfScnMsg++; + prScanCancelMsg->fgIsChannelExt = FALSE; + prScanInfo->fgIsScanRequest = FALSE; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanCancelMsg, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); + +} /* p2pFuncCancelScan */ + +VOID +p2pFuncSwitchOPMode(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_OP_MODE_T eOpMode, IN BOOLEAN fgSyncToFW) +{ + if (!prAdapter) + return; + if (!prAdapter->prGlueInfo) + return; + if (prAdapter->prGlueInfo->ulFlag & GLUE_FLAG_HALT) + return; + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (eOpMode < OP_MODE_NUM)); + + if (prP2pBssInfo->eCurrentOPMode != eOpMode) { + DBGLOG(P2P, TRACE, + "p2pFuncSwitchOPMode: Switch to from %d, to %d.\n", prP2pBssInfo->eCurrentOPMode, + eOpMode); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + p2pFuncDissolve(prAdapter, prP2pBssInfo, TRUE, REASON_CODE_DEAUTH_LEAVING_BSS); + + p2pFsmRunEventStopAP(prAdapter, NULL); + break; + default: + break; + } + + prP2pBssInfo->eIntendOPMode = eOpMode; + prP2pBssInfo->eCurrentOPMode = eOpMode; + switch (eOpMode) { + case OP_MODE_INFRASTRUCTURE: + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to Client.\n"); + case OP_MODE_ACCESS_POINT: +/* if (!IS_BSS_ACTIVE(prP2pBssInfo)) { */ +/* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +/* } */ + + /* Change interface address. */ + if (eOpMode == OP_MODE_ACCESS_POINT) { + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch to AP.\n"); + prP2pBssInfo->ucSSIDLen = 0; + } + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucInterfaceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucInterfaceAddress); + + break; + case OP_MODE_P2P_DEVICE: + { + /* Change device address. */ + DBGLOG(P2P, TRACE, "p2pFuncSwitchOPMode: Switch back to P2P Device.\n"); + +/* if (!IS_BSS_ACTIVE(prP2pBssInfo)) { */ +/* SET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +/* } */ + + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAdapter->rWifiVar.aucDeviceAddress); + + } + break; + default: +/* if (IS_BSS_ACTIVE(prP2pBssInfo)) { */ +/* UNSET_NET_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + +/* nicDeactivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +/* } */ + ASSERT(FALSE); + break; + } + + if (1) { + P2P_DISCONNECT_INFO rP2PDisInfo; + + rP2PDisInfo.ucRole = 2; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_P2P_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(P2P_DISCONNECT_INFO), (PUINT_8)&rP2PDisInfo, NULL, 0); + } + + DBGLOG(P2P, TRACE, + "The device address is changed to %pM\n", + prP2pBssInfo->aucOwnMacAddr); + DBGLOG(P2P, TRACE, "The BSSID is changed to %pM\n", prP2pBssInfo->aucBSSID); + + /* Update BSS INFO to FW. */ + if ((fgSyncToFW) && (eOpMode != OP_MODE_ACCESS_POINT)) + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } while (FALSE); + +} /* p2pFuncSwitchOPMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will start a P2P Group Owner and send Beacon Frames. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncStartGO(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, + IN PUINT_8 pucSsidBuf, + IN UINT_8 ucSsidLen, + IN UINT_8 ucChannelNum, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN BOOLEAN fgIsPureAP) +{ + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL)); + + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 1; + DBGLOG(P2P, INFO, + "p2pFuncStartGO:NFC Done[%d]\n", + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone); + /* AP mode started. */ + p2pFuncSwitchOPMode(prAdapter, prBssInfo, prBssInfo->eIntendOPMode, FALSE); + + prBssInfo->eIntendOPMode = OP_MODE_NUM; + + /* 4 <1.1> Assign SSID */ + COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, pucSsidBuf, ucSsidLen); + + DBGLOG(P2P, TRACE, "GO SSID:%s\n", prBssInfo->aucSSID); + + /* 4 <1.2> Clear current AP's STA_RECORD_T and current AID */ + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + prBssInfo->u2AssocId = 0; + + /* 4 <1.3> Setup Channel, Band and Phy Attributes */ + prBssInfo->ucPrimaryChannel = ucChannelNum; + prBssInfo->eBand = eBand; + prBssInfo->eBssSCO = eSco; + + DBGLOG(P2P, TRACE, "GO Channel:%d\n", ucChannelNum); + + if (prBssInfo->eBand == BAND_5G) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11AN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11A; + } else if (fgIsPureAP) { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11BGN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; + } else { + /* Depend on eBand */ + prBssInfo->ucPhyTypeSet = (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11GN); + /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_11G_P2P; + } + + prBssInfo->ucNonHTBasicPhyType = (UINT_8) + rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].ePhyTypeIndex; + prBssInfo->u2BSSBasicRateSet = rNonHTApModeAttributes[prBssInfo->ucConfigAdHocAPMode].u2BSSBasicRateSet; + prBssInfo->u2OperationalRateSet = + rNonHTPhyAttributes[prBssInfo->ucNonHTBasicPhyType].u2SupportedRateSet; + + if (prBssInfo->ucAllSupportedRatesLen == 0) { + rateGetDataRatesFromRateSet(prBssInfo->u2OperationalRateSet, + prBssInfo->u2BSSBasicRateSet, + prBssInfo->aucAllSupportedRates, + &prBssInfo->ucAllSupportedRatesLen); + } + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2ATIMWindow = 0; + prBssInfo->ucBeaconTimeoutCount = 0; + + /* 3 <2> Update BSS_INFO_T common part */ +#if CFG_SUPPORT_AAA + if (!fgIsPureAP) { + prBssInfo->fgIsProtection = TRUE; /* Always enable protection at P2P GO */ + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); + } else { + if (kalP2PGetCipher(prAdapter->prGlueInfo)) + prBssInfo->fgIsProtection = TRUE; + } + + /* 20120106 frog: I want separate OP_Mode & Beacon TX Function. */ + /* p2pFuncSwitchOPMode(prAdapter, prBssInfo, OP_MODE_ACCESS_POINT, FALSE); */ + + bssInitForAP(prAdapter, prBssInfo, FALSE); + + nicQmUpdateWmmParms(prAdapter, NETWORK_TYPE_P2P_INDEX); +#endif /* CFG_SUPPORT_AAA */ + + /* 3 <3> Set MAC HW */ + /* 4 <3.1> Setup channel and bandwidth */ + rlmBssInitForAPandIbss(prAdapter, prBssInfo); + + /* 4 <3.2> Reset HW TSF Update Mode and Beacon Mode */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <3.3> Update Beacon again for network phy type confirmed. */ + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + +#if 0 /* CFG_SUPPORT_HOTSPOT_OPTIMIZATION */ + { + CMD_HOTSPOT_OPTIMIZATION_CONFIG arHotspotOptimizationCfg; + + arHotspotOptimizationCfg.fgHotspotOptimizationEn = TRUE; + arHotspotOptimizationCfg.u4Level = (0x3) << 8 | 0x5; + wlanoidSendSetQueryP2PCmd(prAdapter, + CMD_ID_SET_HOTSPOT_OPTIMIZATION, + TRUE, + FALSE, + TRUE, + NULL, + NULL, + sizeof(CMD_HOTSPOT_OPTIMIZATION_CONFIG), + (PUINT_8)&arHotspotOptimizationCfg, NULL, 0); + } +#endif + + /* 4 <3.4> Setup BSSID */ + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + + } while (FALSE); + +} /* p2pFuncStartGO() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to inform CNM that channel privilege +* has been released +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncReleaseCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + P_MSG_CH_ABORT_T prMsgChRelease = (P_MSG_CH_ABORT_T) NULL; + + DEBUGFUNC("p2pFuncReleaseCh()"); + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + if (!prChnlReqInfo->fgIsChannelRequested) + break; + + DBGLOG(P2P, TRACE, "P2P Release Channel\n"); + prChnlReqInfo->fgIsChannelRequested = FALSE; + + /* 1. return channel privilege to CNM immediately */ + prMsgChRelease = (P_MSG_CH_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_ABORT_T)); + if (!prMsgChRelease) { + ASSERT(0); /* Can't release Channel to CNM */ + break; + } + + prMsgChRelease->rMsgHdr.eMsgId = MID_MNY_CNM_CH_ABORT; + prMsgChRelease->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChRelease->ucTokenID = prChnlReqInfo->ucSeqNumOfChReq++; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChRelease, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pFuncReleaseCh */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of CHANNEL_REQ_JOIN Initial. Enter CHANNEL_REQ_JOIN State. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncAcquireCh(IN P_ADAPTER_T prAdapter, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + P_MSG_CH_REQ_T prMsgChReq = (P_MSG_CH_REQ_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prChnlReqInfo != NULL)); + + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + + /* send message to CNM for acquiring channel */ + prMsgChReq = (P_MSG_CH_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_CH_REQ_T)); + + if (!prMsgChReq) { + ASSERT(0); /* Can't indicate CNM for channel acquiring */ + break; + } + + prMsgChReq->rMsgHdr.eMsgId = MID_MNY_CNM_CH_REQ; + prMsgChReq->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + prMsgChReq->ucTokenID = ++prChnlReqInfo->ucSeqNumOfChReq; + prMsgChReq->eReqType = CH_REQ_TYPE_JOIN; + if (prChnlReqInfo->u4MaxInterval < P2P_EXT_LISTEN_TIME_MS) + prMsgChReq->u4MaxInterval = P2P_EXT_LISTEN_TIME_MS; + else + prMsgChReq->u4MaxInterval = prChnlReqInfo->u4MaxInterval; + + prMsgChReq->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prMsgChReq->eRfSco = prChnlReqInfo->eChnlSco; + prMsgChReq->eRfBand = prChnlReqInfo->eBand; + + kalMemZero(prMsgChReq->aucBSSID, MAC_ADDR_LEN); + + /* Channel request join BSSID. */ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChReq, MSG_SEND_METHOD_BUF); + + prChnlReqInfo->fgIsChannelRequested = TRUE; + + } while (FALSE); + +} /* p2pFuncAcquireCh */ + +#if 0 +WLAN_STATUS +p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBcnHdr, + IN UINT_32 u4HdrLen, + IN PUINT_8 pucBcnBody, IN UINT_32 u4BodyLen, IN UINT_32 u4DtimPeriod, IN UINT_32 u4BcnInterval) +{ + WLAN_STATUS rResultStatus = WLAN_STATUS_INVALID_DATA; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T) NULL; + PUINT_8 pucTIMBody = (PUINT_8) NULL; + UINT_16 u2FrameLength = 0, UINT_16 u2OldBodyLen = 0; + UINT_8 aucIEBuf[MAX_IE_LENGTH]; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prBcnMsduInfo = prP2pBssInfo->prBeacon ASSERT_BREAK(prBcnMsduInfo != NULL); + + /* TODO: Find TIM IE pointer. */ + prBcnFrame = prBcnMsduInfo->prPacket; + + ASSERT_BREAK(prBcnFrame != NULL); + + do { + /* Ori header. */ + UINT_16 u2IELength = 0, u2Offset = 0; + PUINT_8 pucIEBuf = prBcnFrame->aucInfoElem; + + u2IELength = prBcnMsduInfo->u2FrameLength - prBcnMsduInfo->ucMacHeaderLength; + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + if ((IE_ID(pucIEBuf) == ELEM_ID_TIM) || ((IE_ID(pucIEBuf) > ELEM_ID_IBSS_PARAM_SET))) { + pucTIMBody = pucIEBuf; + break; + } + u2FrameLength += IE_SIZE(pucIEBuf); + } + + if (pucTIMBody == NULL) + pucTIMBody = pucIEBuf; + + /* Body not change. */ + u2OldBodyLen = (UINT_16) ((UINT_32) pucTIMBody - (UINT_32) prBcnFrame->aucInfoElem); + /* Move body. */ + kalMemCmp(aucIEBuf, pucTIMBody, u2OldBodyLen); + } while (FALSE); + + if (pucBcnHdr) { + kalMemCopy(prBcnMsduInfo->prPacket, pucBcnHdr, u4HdrLen); + pucTIMBody = (PUINT_8) ((UINT_32) prBcnMsduInfo->prPacket + u4HdrLen); + prBcnMsduInfo->ucMacHeaderLength = (WLAN_MAC_MGMT_HEADER_LEN + + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)); + u2FrameLength = u4HdrLen; /* Header + Partial Body. */ + } else { + /* Header not change. */ + u2FrameLength += prBcnMsduInfo->ucMacHeaderLength; + } + + if (pucBcnBody) { + kalMemCopy(pucTIMBody, pucBcnBody, u4BodyLen); + u2FrameLength += (UINT_16) u4BodyLen; + } else { + kalMemCopy(pucTIMBody, aucIEBuf, u2OldBodyLen); + u2FrameLength += u2OldBodyLen; + } + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = u2FrameLength; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + prP2pBssInfo->u2BeaconInterval = (UINT_16) u4BcnInterval; + prP2pBssInfo->ucDTIMPeriod = (UINT_8) u4DtimPeriod; + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + prBcnMsduInfo->ucPacketType = 3; + rResultStatus = nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prP2pBssInfo->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + prBcnMsduInfo->u2FrameLength - + OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem)); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + /* AP is created, Beacon Update. */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + nicPmIndicateBssCreated(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } while (FALSE); + return rResultStatus; +} /* p2pFuncBeaconUpdate */ + +#else +WLAN_STATUS + p2pFuncBeaconUpdate(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, + IN P_P2P_BEACON_UPDATE_INFO_T prBcnUpdateInfo, + IN PUINT_8 pucNewBcnHdr, IN UINT_32 u4NewHdrLen, IN PUINT_8 pucNewBcnBody, IN UINT_32 u4NewBodyLen) +{ +WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; +P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; +P_MSDU_INFO_T prBcnMsduInfo = (P_MSDU_INFO_T) NULL; +PUINT_8 pucIEBuf = (PUINT_8) NULL; +PUINT_8 paucIEBuf = (PUINT_8) NULL;/*[MAX_IE_LENGTH]; aucIEBuf*/ + +do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL) && (prBcnUpdateInfo != NULL)); + + prBcnMsduInfo = prP2pBssInfo->prBeacon; + +#if DBG + if (prBcnUpdateInfo->pucBcnHdr != NULL) { + ASSERT((UINT_32) prBcnUpdateInfo->pucBcnHdr == + ((UINT_32) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD)); + } + + if (prBcnUpdateInfo->pucBcnBody != NULL) { + ASSERT((UINT_32) prBcnUpdateInfo->pucBcnBody == + ((UINT_32) prBcnUpdateInfo->pucBcnHdr + (UINT_32) prBcnUpdateInfo->u4BcnHdrLen)); + } +#endif + prBcnFrame = (P_WLAN_BEACON_FRAME_T) ((ULONG) prBcnMsduInfo->prPacket + MAC_TX_RESERVED_FIELD); + + if (!pucNewBcnBody) { + /* Old body. */ + pucNewBcnBody = prBcnUpdateInfo->pucBcnBody; + ASSERT(u4NewBodyLen == 0); + u4NewBodyLen = prBcnUpdateInfo->u4BcnBodyLen; + } else { + prBcnUpdateInfo->u4BcnBodyLen = u4NewBodyLen; + } + + paucIEBuf = kalMemAlloc(MAX_IE_LENGTH, VIR_MEM_TYPE); + if (paucIEBuf == NULL) { + DBGLOG(P2P, TRACE, "p2p alloc paucIEBuf fail\n"); + return WLAN_STATUS_FAILURE; + } + + /* Temp buffer body part. */ + kalMemCopy(paucIEBuf, pucNewBcnBody, u4NewBodyLen); + + if (pucNewBcnHdr) { + kalMemCopy(prBcnFrame, pucNewBcnHdr, u4NewHdrLen); + prBcnUpdateInfo->pucBcnHdr = (PUINT_8) prBcnFrame; + prBcnUpdateInfo->u4BcnHdrLen = u4NewHdrLen; + } + + pucIEBuf = (PUINT_8) ((ULONG) prBcnUpdateInfo->pucBcnHdr + (UINT_32) prBcnUpdateInfo->u4BcnHdrLen); + kalMemCopy(pucIEBuf, paucIEBuf, u4NewBodyLen); + kalMemFree(paucIEBuf, VIR_MEM_TYPE, MAX_IE_LENGTH); + prBcnUpdateInfo->pucBcnBody = pucIEBuf; + + /* Frame Length */ + prBcnMsduInfo->u2FrameLength = (UINT_16) (prBcnUpdateInfo->u4BcnHdrLen + prBcnUpdateInfo->u4BcnBodyLen); + + prBcnMsduInfo->ucPacketType = 3; + prBcnMsduInfo->fgIs802_11 = TRUE; + prBcnMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + /* Update BSS INFO related information. */ + COPY_MAC_ADDR(prP2pBssInfo->aucOwnMacAddr, prBcnFrame->aucSrcAddr); + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prBcnFrame->aucBSSID); + prP2pBssInfo->u2CapInfo = prBcnFrame->u2CapInfo; + + p2pFuncParseBeaconContent(prAdapter, + prP2pBssInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); + +#if 1 + /* bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); */ +#else + nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBcnFrame->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + (prBcnMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem))); +#endif +} while (FALSE); + +return rWlanStatus; +} /* p2pFuncBeaconUpdate */ + +#endif + +/* TODO: We do not apply IE in deauth frame set from upper layer now. */ +WLAN_STATUS +p2pFuncDeauth(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDeauth) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) + break; + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDeauth, u2ReasonCode); + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDeauth */ + +/* TODO: We do not apply IE in disassoc frame set from upper layer now. */ +WLAN_STATUS +p2pFuncDisassoc(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucPeerMacAddr, + IN UINT_16 u2ReasonCode, IN PUINT_8 pucIEBuf, IN UINT_16 u2IELen, IN BOOLEAN fgSendDisassoc) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_FAILURE; + P_STA_RECORD_T prCliStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + BOOLEAN fgIsStaFound = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucPeerMacAddr != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + prCliStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, pucPeerMacAddr); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_ACCESS_POINT: + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + prStaRecOfClientList = &(prP2pBssInfo->rStaRecOfClientList); + + LINK_FOR_EACH(prLinkEntry, prStaRecOfClientList) { + if ((ULONG) prCliStaRec == (ULONG) prLinkEntry) { + LINK_REMOVE_KNOWN_ENTRY(prStaRecOfClientList, &prCliStaRec->rLinkEntry); + fgIsStaFound = TRUE; + /* p2pFuncDisconnect(prAdapter, prCliStaRec, + * fgSendDisassoc, u2ReasonCode); */ + break; + } + } + + } + break; + case OP_MODE_INFRASTRUCTURE: + ASSERT(prCliStaRec == prP2pBssInfo->prStaRecOfAP); + if (prCliStaRec != prP2pBssInfo->prStaRecOfAP) + break; + /* p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); */ + prP2pBssInfo->prStaRecOfAP = NULL; + fgIsStaFound = TRUE; + break; + default: + break; + } + + if (fgIsStaFound) { + + p2pFuncDisconnect(prAdapter, prCliStaRec, fgSendDisassoc, u2ReasonCode); + /* 20120830 moved into p2pFuncDisconnect(). */ + /* cnmStaRecFree(prAdapter, prCliStaRec, TRUE); */ + + } + + rWlanStatus = WLAN_STATUS_SUCCESS; + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncDisassoc */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDissolve(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) +{ + DEBUGFUNC("p2pFuncDissolve()"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + switch (prP2pBssInfo->eCurrentOPMode) { + case OP_MODE_INFRASTRUCTURE: + /* Reset station record status. */ + if (prP2pBssInfo->prStaRecOfAP) { + kalP2PGCIndicateConnectionStatus(prAdapter->prGlueInfo, + NULL, NULL, 0, REASON_CODE_DEAUTH_LEAVING_BSS, + WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY); + + /* 2012/02/14 frog: After formation before join group, prStaRecOfAP is NULL. */ + p2pFuncDisconnect(prAdapter, prP2pBssInfo->prStaRecOfAP, fgSendDeauth, u2ReasonCode); + } + + /* Fix possible KE when RX Beacon & call nicPmIndicateBssConnected(). + * hit prStaRecOfAP == NULL. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + prP2pBssInfo->prStaRecOfAP = NULL; + + break; + case OP_MODE_ACCESS_POINT: + /* Under AP mode, we would net send deauthentication frame to each STA. + * We only stop the Beacon & let all stations timeout. + */ + { + P_LINK_T prStaRecOfClientList = (P_LINK_T) NULL; + + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + NULL, (P_SW_RFB_T) NULL, u2ReasonCode, (PFN_TX_DONE_HANDLER) NULL); + + prStaRecOfClientList = &prP2pBssInfo->rStaRecOfClientList; + + while (!LINK_IS_EMPTY(prStaRecOfClientList)) { + P_STA_RECORD_T prCurrStaRec; + + LINK_REMOVE_HEAD(prStaRecOfClientList, prCurrStaRec, P_STA_RECORD_T); + + /* Indicate to Host. */ + /* kalP2PGOStationUpdate(prAdapter->prGlueInfo, prCurrStaRec, FALSE); */ + + p2pFuncDisconnect(prAdapter, prCurrStaRec, TRUE, u2ReasonCode); + + } + prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone = 0; + } + + break; + default: + return; /* 20110420 -- alreay in Device Mode. */ + } + + /* Make the deauth frame send to FW ASAP. */ + wlanAcquirePowerControl(prAdapter); + wlanProcessCommandQueue(prAdapter, &prAdapter->prGlueInfo->rCmdQueue); + wlanReleasePowerControl(prAdapter); + + kalMdelay(100); + + /* Change Connection Status. */ + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + + } while (FALSE); + +} /* p2pFuncDissolve */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to dissolve from group or one group. (Would not change P2P FSM.) +* 1. GC: Disconnect from AP. (Send Deauth) +* 2. GO: Disconnect all STA +* +* @param[in] prAdapter Pointer to the adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncDisconnect(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN BOOLEAN fgSendDeauth, IN UINT_16 u2ReasonCode) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + ENUM_PARAM_MEDIA_STATE_T eOriMediaStatus; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + eOriMediaStatus = prP2pBssInfo->eConnectionState; + + /* Indicate disconnect. */ + /* TODO: */ + /* kalP2PGOStationUpdate */ + /* kalP2PGCIndicateConnectionStatus */ + /* p2pIndicationOfMediaStateToHost(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED, prStaRec->aucMacAddr); */ + DBGLOG(P2P, INFO, "p2pFuncDisconnect, eCurrentOPMode: %d, sendDeauth: %s\n", + prP2pBssInfo->eCurrentOPMode, fgSendDeauth ? "True" : "False"); + if (prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + kalP2PGOStationUpdate(prAdapter->prGlueInfo, prStaRec, FALSE); + + if (fgSendDeauth) { + /* Send deauth. */ + authSendDeauthFrame(prAdapter, + prStaRec, + (P_SW_RFB_T) NULL, + u2ReasonCode, (PFN_TX_DONE_HANDLER) p2pFsmRunEventDeauthTxDone); + } else { + /* Change station state. */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* Reset Station Record Status. */ + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->rStaRecOfClientList.u4NumElem == 0)) { + DBGLOG(P2P, TRACE, "No More Client, Media Status DISCONNECTED\n"); + p2pChangeMediaState(prAdapter, PARAM_MEDIA_STATE_DISCONNECTED); + } + + if (eOriMediaStatus != prP2pBssInfo->eConnectionState) { + /* Update Disconnected state to FW. */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + } + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) { + /* GO: It would stop Beacon TX. GC: Stop all BSS related PS function. */ + nicPmIndicateBssAbort(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* Reset RLM related field of BSSINFO. */ + rlmBssAborted(prAdapter, prP2pBssInfo); + } + + } while (FALSE); + + return; + +} /* p2pFuncDisconnect */ + +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_VENDOR_SPECIFIC 127 + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +/* P2P public action frames */ +enum p2p_action_frame_type { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +}; + +const char *p2p_to_string(enum p2p_action_frame_type p2p_action) +{ + switch (p2p_action) { + case P2P_GO_NEG_REQ: + return "GO_NEG_REQ"; + case P2P_GO_NEG_RESP: + return "GO_NEG_RESP"; + case P2P_GO_NEG_CONF: + return "GO_NEG_CONF"; + case P2P_INVITATION_REQ: + return "INVITATION_REQ"; + case P2P_INVITATION_RESP: + return "INVITATION_RESP"; + case P2P_DEV_DISC_REQ: + return "DEV_DISC_REQ"; + case P2P_DEV_DISC_RESP: + return "DEV_DISC_RESP"; + case P2P_PROV_DISC_REQ: + return "PROV_DISC_REQ"; + case P2P_PROV_DISC_RESP: + return "PROV_DISC_RESP"; + } + + return "UNKNOWN P2P Public Action"; +} +const char *pa_to_string(int pa_action) +{ + switch (pa_action) { + case WLAN_PA_20_40_BSS_COEX: + return "PA_20_40_BSS_COEX"; + case WLAN_PA_VENDOR_SPECIFIC: + return "PA_VENDOR_SPECIFIC"; + case WLAN_PA_GAS_INITIAL_REQ: + return "PA_GAS_INITIAL_REQ"; + case WLAN_PA_GAS_INITIAL_RESP: + return "PA_GAS_INITIAL_RESP"; + case WLAN_PA_GAS_COMEBACK_REQ: + return "PA_GAS_COMEBACK_REQ"; + case WLAN_PA_GAS_COMEBACK_RESP: + return "PA_GAS_COMEBACK_RESP"; + case WLAN_TDLS_DISCOVERY_RESPONSE: + return "TDLS_DISCOVERY_RESPONSE"; + } + + return "UNKNOWN Public Action"; +} + +const char *action_to_string(int wlan_action) +{ + switch (wlan_action) { + case WLAN_ACTION_SPECTRUM_MGMT: + return "SPECTRUM_MGMT"; + case WLAN_ACTION_QOS: + return "QOS"; + case WLAN_ACTION_DLS: + return "DLS"; + case WLAN_ACTION_BLOCK_ACK: + return "BLOCK_ACK"; + case WLAN_ACTION_PUBLIC: + return "PUBLIC"; + case WLAN_ACTION_RADIO_MEASUREMENT: + return "RADIO_MEASUREMENT"; + case WLAN_ACTION_FT: + return "FT"; + case WLAN_ACTION_HT: + return "HT"; + case WLAN_ACTION_SA_QUERY: + return "SA_QUERY"; + case WLAN_ACTION_PROTECTED_DUAL: + return "PROTECTED_DUAL"; + case WLAN_ACTION_WNM: + return "WNM"; + case WLAN_ACTION_UNPROTECTED_WNM: + return "UNPROTECTED_WNM"; + case WLAN_ACTION_TDLS: + return "TDLS"; + case WLAN_ACTION_SELF_PROTECTED: + return "SELF_PROTECTED"; + case WLAN_ACTION_WMM: + return "WMM"; + case WLAN_ACTION_VENDOR_SPECIFIC: + return "VENDOR_SPECIFIC"; + } + + return "UNKNOWN Action Frame"; +} + +VOID p2pFuncTagActionActionP2PFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + IN P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucP2pAction, IN UINT_64 u8Cookie) +{ + DBGLOG(P2P, INFO, "Found P2P_%s, SA: %pM - DA: %pM, cookie: 0x%llx, SeqNO: %d\n", + p2p_to_string(ucP2pAction), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); +} + +VOID p2pFuncTagActionActionFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + IN P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucAction, IN UINT_64 u8Cookie) +{ + PUINT_8 pucVendor = NULL; + + DBGLOG(P2P, INFO, "Found WLAN_%s, SA: %pM - DA: %pM, cookie: 0x%llx, SeqNo: %d\n", + pa_to_string(ucAction), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucAction == WLAN_PA_VENDOR_SPECIFIC) { + pucVendor = (PUINT_8)prActFrame + 26; + if (*(pucVendor + 0) == 0x50 && + *(pucVendor + 1) == 0x6f && + *(pucVendor + 2) == 0x9a) { + if (*(pucVendor + 3) == 0x09) + /* found p2p IE */ + p2pFuncTagActionActionP2PFrame(prMgmtTxMsdu, + prActFrame, *(pucVendor + 4), u8Cookie); + else if (*(pucVendor + 3) == 0x0a) + /* found WFD IE */ + DBGLOG(P2P, INFO, "Found WFD IE, SA: %pM - DA: %pM\n", + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr); + else + DBGLOG(P2P, INFO, "Found Other vendor 0x%x, SA: %pM - DA: %pM\n", + *(pucVendor + 3), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr); + } + } +} + +VOID p2pFuncTagActionCategoryFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, + P_WLAN_ACTION_FRAME prActFrame, + IN UINT_8 ucCategory, + IN UINT_64 u8Cookie) +{ + + UINT_8 ucAction = 0; + + DBGLOG(P2P, INFO, "Found WLAN_ACTION_%s, SA: %pM - DA: %pM, u8Cookie: 0x%llx, SeqNO: %d\n", + action_to_string(ucCategory), + prActFrame->aucSrcAddr, + prActFrame->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + if (ucCategory == WLAN_ACTION_PUBLIC) { + ucAction = prActFrame->ucAction; + p2pFuncTagActionActionFrame(prMgmtTxMsdu, prActFrame, ucAction, u8Cookie); + + } +} + +/* + * used to debug p2p mgmt frame: + * GO Nego Req + * GO Nego Res + * GO Nego Confirm + * GO Invite Req + * GO Invite Res + * Device Discoverability Req + * Device Discoverability Res + * Provision Discovery Req + * Provision Discovery Res + */ + +VOID +p2pFuncTagMgmtFrame(IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + /* P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T)NULL; */ + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_WLAN_PROBE_RSP_FRAME_T prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T)NULL; + UINT_16 u2TxFrameCtrl; + P_WLAN_ACTION_FRAME prActFrame; + UINT_8 ucCategory; + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + /* + * mgmt frame MASK_FC_TYPE = 0 + * use MASK_FRAME_TYPE is oK for frame type/subtype judge + */ + u2TxFrameCtrl = prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE; + + switch (u2TxFrameCtrl) { + case MAC_FRAME_PROBE_RSP: + + prProbRspHdr = (P_WLAN_PROBE_RSP_FRAME_T) prWlanHdr; + DBGLOG(P2P, INFO, "TX Probe Response Frame, SA: %pM - DA: %pM, cookie: 0x%llx, seqNo: %d\n", + prProbRspHdr->aucSrcAddr, prProbRspHdr->aucDestAddr, + u8Cookie, + prMgmtTxMsdu->ucTxSeqNum); + + break; + + case MAC_FRAME_ACTION: + + prActFrame = (P_WLAN_ACTION_FRAME)prWlanHdr; + ucCategory = prActFrame->ucCategory; + p2pFuncTagActionCategoryFrame(prMgmtTxMsdu, prActFrame, + ucCategory, u8Cookie); + + break; + default: + DBGLOG(P2P, INFO, "MGMT:, un-tagged frame type: 0x%x, A1: %pM, A2: %pM, A3: %pM seqNo: %d\n", + u2TxFrameCtrl, + prWlanHdr->aucAddr1, + prWlanHdr->aucAddr2, + prWlanHdr->aucAddr3, + prMgmtTxMsdu->ucTxSeqNum); + break; + } +} + +WLAN_STATUS +p2pFuncTxMgmtFrame(IN P_ADAPTER_T prAdapter, + IN P_P2P_MGMT_TX_REQ_INFO_T prMgmtTxReqInfo, IN P_MSDU_INFO_T prMgmtTxMsdu, IN UINT_64 u8Cookie) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prTxMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanHdr = (P_WLAN_MAC_HEADER_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + BOOLEAN fgIsProbrsp = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxReqInfo != NULL)); + + if (prMgmtTxReqInfo->fgIsMgmtTxRequested) { + + /* 1. prMgmtTxReqInfo->prMgmtTxMsdu != NULL */ + /* Packet on driver, not done yet, drop it. */ + prTxMsduInfo = prMgmtTxReqInfo->prMgmtTxMsdu; + if (prTxMsduInfo != NULL) { + + kalP2PIndicateMgmtTxStatus(prAdapter->prGlueInfo, + prMgmtTxReqInfo->u8Cookie, + FALSE, + prTxMsduInfo->prPacket, + (UINT_32) prTxMsduInfo->u2FrameLength); + + /* Leave it to TX Done handler. */ + /* cnmMgtPktFree(prAdapter, prTxMsduInfo); */ + prMgmtTxReqInfo->prMgmtTxMsdu = NULL; + DBGLOG(P2P, INFO, "p2pFuncTxMgmtFrame: Drop MGMT cookie: 0x%llx\n", + prMgmtTxReqInfo->u8Cookie); + } + /* 2. prMgmtTxReqInfo->prMgmtTxMsdu == NULL */ + /* Packet transmitted, wait tx done. (cookie issue) */ + /* 20120105 frog - use another u8cookie to store this value. */ + } + + ASSERT(prMgmtTxReqInfo->prMgmtTxMsdu == NULL); + + prWlanHdr = (P_WLAN_MAC_HEADER_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_P2P_INDEX, prWlanHdr->aucAddr1); + prMgmtTxMsdu->ucNetworkType = (UINT_8) NETWORK_TYPE_P2P_INDEX; + + switch (prWlanHdr->u2FrameCtrl & MASK_FRAME_TYPE) { + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "p2pFuncTxMgmtFrame: TX MAC_FRAME_PROBE_RSP\n"); + fgIsProbrsp = TRUE; + prMgmtTxMsdu = p2pFuncProcessP2pProbeRsp(prAdapter, prMgmtTxMsdu); + break; + default: + break; + } + + prMgmtTxReqInfo->u8Cookie = u8Cookie; + prMgmtTxReqInfo->prMgmtTxMsdu = prMgmtTxMsdu; + prMgmtTxReqInfo->fgIsMgmtTxRequested = TRUE; + + prMgmtTxMsdu->eSrc = TX_PACKET_MGMT; + prMgmtTxMsdu->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMgmtTxMsdu->ucStaRecIndex = (prStaRec != NULL) ? (prStaRec->ucIndex) : (0xFF); + if (prStaRec != NULL) + DBGLOG(P2P, TRACE, "Mgmt with station record: %pM.\n", prStaRec->aucMacAddr); + + prMgmtTxMsdu->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; /* TODO: undcertain. */ + prMgmtTxMsdu->fgIs802_1x = FALSE; + prMgmtTxMsdu->fgIs802_11 = TRUE; + prMgmtTxMsdu->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMgmtTxMsdu->pfTxDoneHandler = p2pFsmRunEventMgmtFrameTxDone; + prMgmtTxMsdu->fgIsBasicRate = TRUE; + + p2pFuncTagMgmtFrame(prMgmtTxMsdu, u8Cookie); + + nicTxEnqueueMsdu(prAdapter, prMgmtTxMsdu); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncTxMgmtFrame */ + +VOID p2pFuncSetChannel(IN P_ADAPTER_T prAdapter, IN P_RF_CHANNEL_INFO_T prRfChannelInfo) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prRfChannelInfo != NULL)); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnSettings->ucOperatingChnl = prRfChannelInfo->ucChannelNum; + prP2pConnSettings->eBand = prRfChannelInfo->eBand; + + } while (FALSE); + +} + +/* p2pFuncSetChannel */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Retry JOIN for AUTH_MODE_AUTO_SWITCH +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @retval TRUE We will retry JOIN +* @retval FALSE We will not retry JOIN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncRetryJOIN(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN P_P2P_JOIN_INFO_T prJoinInfo) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; + BOOLEAN fgRetValue = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL) && (prJoinInfo != NULL)); + + /* Retry other AuthType if possible */ + if (!prJoinInfo->ucAvailableAuthTypes) + break; + + if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, INFO, "RETRY JOIN INIT: Retry Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else { + DBGLOG(P2P, ERROR, "RETRY JOIN INIT: Retry Authentication with Unexpected AuthType.\n"); + ASSERT(0); + break; + } + + prJoinInfo->ucAvailableAuthTypes = 0; /* No more available Auth Types */ + + /* Trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + if (!prJoinReqMsg) { + ASSERT(0); /* Can't trigger SAA FSM */ + break; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + fgRetValue = TRUE; + } while (FALSE); + + return fgRetValue; + +} /* end of p2pFuncRetryJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will update the contain of BSS_INFO_T for AIS network once +* the association was completed. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prAssocRspSwRfb Pointer to SW RFB of ASSOC RESP FRAME. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncUpdateBssInfoForJOIN(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prAssocRspSwRfb) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + UINT_16 u2IELength; + PUINT_8 pucIE; + + DEBUGFUNC("p2pUpdateBssInfoForJOIN()"); + + ASSERT(prAdapter); + ASSERT(prStaRec); + ASSERT(prAssocRspSwRfb); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prAssocRspSwRfb->pvHeader; + + DBGLOG(P2P, INFO, "Update P2P_BSS_INFO_T and apply settings to MAC\n"); + + /* 3 <1> Update BSS_INFO_T from AIS_FSM_INFO_T or User Settings */ + /* 4 <1.1> Setup Operation Mode */ + prP2pBssInfo->eCurrentOPMode = OP_MODE_INFRASTRUCTURE; + + /* 4 <1.2> Setup SSID */ + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen); + + if (prBssDesc == NULL) { + /* Target BSS NULL. */ + DBGLOG(P2P, TRACE, "Target BSS NULL\n"); + return; + } + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAssocRspFrame->aucBSSID)) + ASSERT(FALSE); + /* 4 <1.3> Setup Channel, Band */ + prP2pBssInfo->ucPrimaryChannel = prBssDesc->ucChannelNum; + prP2pBssInfo->eBand = prBssDesc->eBand; + + /* 3 <2> Update BSS_INFO_T from STA_RECORD_T */ + /* 4 <2.1> Save current AP's STA_RECORD_T and current AID */ + prP2pBssInfo->prStaRecOfAP = prStaRec; + prP2pBssInfo->u2AssocId = prStaRec->u2AssocId; + + /* 4 <2.2> Setup Capability */ + prP2pBssInfo->u2CapInfo = prStaRec->u2CapInfo; /* Use AP's Cap Info as BSS Cap Info */ + + if (prP2pBssInfo->u2CapInfo & CAP_INFO_SHORT_PREAMBLE) + prP2pBssInfo->fgIsShortPreambleAllowed = TRUE; + else + prP2pBssInfo->fgIsShortPreambleAllowed = FALSE; + + /* 4 <2.3> Setup PHY Attributes and Basic Rate Set/Operational Rate Set */ + prP2pBssInfo->ucPhyTypeSet = prStaRec->ucDesiredPhyTypeSet; + + prP2pBssInfo->ucNonHTBasicPhyType = prStaRec->ucNonHTBasicPhyType; + + prP2pBssInfo->u2OperationalRateSet = prStaRec->u2OperationalRateSet; + prP2pBssInfo->u2BSSBasicRateSet = prStaRec->u2BSSBasicRateSet; + + /* 3 <3> Update BSS_INFO_T from SW_RFB_T (Association Resp Frame) */ + /* 4 <3.1> Setup BSSID */ + COPY_MAC_ADDR(prP2pBssInfo->aucBSSID, prAssocRspFrame->aucBSSID); + + u2IELength = (UINT_16) ((prAssocRspSwRfb->u2PacketLen - prAssocRspSwRfb->u2HeaderLen) - + (OFFSET_OF(WLAN_ASSOC_RSP_FRAME_T, aucInfoElem[0]) - WLAN_MAC_MGMT_HEADER_LEN)); + pucIE = prAssocRspFrame->aucInfoElem; + + /* 4 <3.2> Parse WMM and setup QBSS flag */ + /* Parse WMM related IEs and configure HW CRs accordingly */ + mqmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + prP2pBssInfo->fgIsQBSS = prStaRec->fgIsQoS; + + /* 3 <4> Update BSS_INFO_T from BSS_DESC_T */ + ASSERT(prBssDesc); + + prBssDesc->fgIsConnecting = FALSE; + prBssDesc->fgIsConnected = TRUE; + + /* 4 <4.1> Setup MIB for current BSS */ + prP2pBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + /* NOTE: Defer ucDTIMPeriod updating to when beacon is received after connection */ + prP2pBssInfo->ucDTIMPeriod = 0; + prP2pBssInfo->u2ATIMWindow = 0; + + prP2pBssInfo->ucBeaconTimeoutCount = AIS_BEACON_TIMEOUT_COUNT_INFRA; + + /* 4 <4.2> Update HT information and set channel */ + /* Record HT related parameters in rStaRec and rBssInfo + * Note: it shall be called before nicUpdateBss() + */ + rlmProcessAssocRsp(prAdapter, prAssocRspSwRfb, pucIE, u2IELength); + + /* 4 <4.3> Sync with firmware for BSS-INFO */ + nicUpdateBss(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* 4 <4.4> *DEFER OPERATION* nicPmIndicateBssConnected() will be invoked */ + /* inside scanProcessBeaconAndProbeResp() after 1st beacon is received */ + +} /* end of p2pUpdateBssInfoForJOIN() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Auth Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[in] pprStaRec Pointer to pointer of STA_RECORD_T structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Auth +* @retval FALSE Don't reply the Auth +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +p2pFuncValidateAuth(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PP_STA_RECORD_T pprStaRec, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAuth = TRUE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_WLAN_AUTH_FRAME_T prAuthFrame = (P_WLAN_AUTH_FRAME_T) NULL; + + DBGLOG(P2P, INFO, "p2pValidate Authentication Frame\n"); + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prSwRfb != NULL) && (pprStaRec != NULL) && (pu2StatusCode != NULL)); + + /* P2P 3.2.8 */ + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAuthFrame = (P_WLAN_AUTH_FRAME_T) prSwRfb->pvHeader; + + if ((prP2pBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + || (prP2pBssInfo->eIntendOPMode != OP_MODE_NUM)) { + /* We are not under AP Mode yet. */ + fgReplyAuth = FALSE; + DBGLOG(P2P, WARN, + "Current OP mode is not under AP mode. (%d)\n", prP2pBssInfo->eCurrentOPMode); + break; + } + + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_P2P_INDEX, prAuthFrame->aucSrcAddr); + + if (!prStaRec) { + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_P2P_INDEX); + + /* TODO(Kevin): Error handling of allocation of STA_RECORD_T for + * exhausted case and do removal of unused STA_RECORD_T. + */ + /* Sent a message event to clean un-used STA_RECORD_T. */ + ASSERT(prStaRec); + if (!prStaRec) { + DBGLOG(AAA, INFO, "Station Limit Full. Decline a new Authentication.\n"); + break; + } + + COPY_MAC_ADDR(prStaRec->aucMacAddr, prAuthFrame->aucSrcAddr); + + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + prStaRec->u2BSSBasicRateSet = prP2pBssInfo->u2BSSBasicRateSet; + + prStaRec->u2DesiredNonHTRateSet = RATE_SET_ERP_P2P; + + prStaRec->u2OperationalRateSet = RATE_SET_ERP_P2P; + prStaRec->ucPhyTypeSet = PHY_TYPE_SET_802_11GN; + prStaRec->eStaType = STA_TYPE_P2P_GC; + + /* NOTE(Kevin): Better to change state here, not at TX Done */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } else { + prSwRfb->ucStaRecIdx = prStaRec->ucIndex; + + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_STA_IN_P2P(prStaRec))) { + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + p2pFuncResetStaRecStatus(prAdapter, prStaRec); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + } + + } + + if (prP2pBssInfo->rStaRecOfClientList.u4NumElem >= P2P_MAXIMUM_CLIENT_COUNT || + kalP2PMaxClients(prAdapter->prGlueInfo, prP2pBssInfo->rStaRecOfClientList.u4NumElem)) { + /* GROUP limit full. */ + /* P2P 3.2.8 */ + DBGLOG(P2P, WARN, + "Group Limit Full. (%d)\n", (INT_16) prP2pBssInfo->rStaRecOfClientList.u4NumElem); + + bssRemoveStaRecFromClientList(prAdapter, prP2pBssInfo, prStaRec); + + cnmStaRecFree(prAdapter, prStaRec, FALSE); + fgReplyAuth = TRUE; + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_AP_OVERLOAD; + break; + } + /* Hotspot Blacklist */ + if (prAuthFrame->aucSrcAddr) { + if (kalP2PCmpBlackList(prAdapter->prGlueInfo, prAuthFrame->aucSrcAddr)) { + fgReplyAuth = TRUE; + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_OUTSIDE_STANDARD; + return fgReplyAuth; + } + } + + /* prStaRec->eStaType = STA_TYPE_INFRA_CLIENT; */ + prStaRec->eStaType = STA_TYPE_P2P_GC; + + prStaRec->ucNetTypeIndex = NETWORK_TYPE_P2P_INDEX; + + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + prStaRec->ucJoinFailureCount = 0; + + *pprStaRec = prStaRec; + + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + + } while (FALSE); + + return fgReplyAuth; + +} /* p2pFuncValidateAuth */ + +VOID p2pFuncResetStaRecStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + do { + if ((prAdapter == NULL) || (prStaRec == NULL)) { + ASSERT(FALSE); + break; + } + + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + prStaRec->u2ReasonCode = REASON_CODE_RESERVED; + prStaRec->ucJoinFailureCount = 0; + prStaRec->fgTransmitKeyExist = FALSE; + + prStaRec->fgSetPwrMgtBit = FALSE; + + } while (FALSE); + +} /* p2pFuncResetStaRecStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function is used to initialize the value of the connection settings for +* P2P network +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncInitConnectionSettings(IN P_ADAPTER_T prAdapter, IN P_P2P_CONNECTION_SETTINGS_T prP2PConnSettings) +{ + P_DEVICE_TYPE_T prDevType; + UINT_8 aucDefaultDevName[] = P2P_DEFAULT_DEV_NAME; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; +#if CFG_SUPPORT_CFG_FILE + P_WIFI_VAR_T prWifiVar = NULL; +#endif + + ASSERT(prP2PConnSettings); +#if CFG_SUPPORT_CFG_FILE + prWifiVar = &(prAdapter->rWifiVar); + ASSERT(prWifiVar); +#endif + + /* Setup Default Device Name */ + prP2PConnSettings->ucDevNameLen = P2P_DEFAULT_DEV_NAME_LEN; + kalMemCopy(prP2PConnSettings->aucDevName, aucDefaultDevName, sizeof(aucDefaultDevName)); + + /* Setup Primary Device Type (Big-Endian) */ + prDevType = &prP2PConnSettings->rPrimaryDevTypeBE; + + prDevType->u2CategoryId = HTONS(P2P_DEFAULT_PRIMARY_CATEGORY_ID); + prDevType->u2SubCategoryId = HTONS(P2P_DEFAULT_PRIMARY_SUB_CATEGORY_ID); + + prDevType->aucOui[0] = aucWfaOui[0]; + prDevType->aucOui[1] = aucWfaOui[1]; + prDevType->aucOui[2] = aucWfaOui[2]; + prDevType->aucOui[3] = VENDOR_OUI_TYPE_WPS; + + /* Setup Secondary Device Type */ + prP2PConnSettings->ucSecondaryDevTypeCount = 0; + + /* Setup Default Config Method */ + prP2PConnSettings->eConfigMethodSelType = ENUM_CONFIG_METHOD_SEL_AUTO; + prP2PConnSettings->u2ConfigMethodsSupport = P2P_DEFAULT_CONFIG_METHOD; + prP2PConnSettings->u2TargetConfigMethod = 0; + prP2PConnSettings->u2LocalConfigMethod = 0; + prP2PConnSettings->fgIsPasswordIDRdy = FALSE; + + /* For Device Capability */ + prP2PConnSettings->fgSupportServiceDiscovery = FALSE; + prP2PConnSettings->fgSupportClientDiscoverability = TRUE; + prP2PConnSettings->fgSupportConcurrentOperation = TRUE; + prP2PConnSettings->fgSupportInfraManaged = FALSE; + prP2PConnSettings->fgSupportInvitationProcedure = FALSE; + + /* For Group Capability */ +#if CFG_SUPPORT_PERSISTENT_GROUP + prP2PConnSettings->fgSupportPersistentP2PGroup = TRUE; +#else + prP2PConnSettings->fgSupportPersistentP2PGroup = FALSE; +#endif + prP2PConnSettings->fgSupportIntraBSSDistribution = TRUE; + prP2PConnSettings->fgSupportCrossConnection = TRUE; + prP2PConnSettings->fgSupportPersistentReconnect = FALSE; + + prP2PConnSettings->fgSupportOppPS = FALSE; + prP2PConnSettings->u2CTWindow = P2P_CTWINDOW_DEFAULT; + + /* For Connection Settings. */ + prP2PConnSettings->eAuthMode = AUTH_MODE_OPEN; + + prP2PConnSettings->prTargetP2pDesc = NULL; + prP2PConnSettings->ucSSIDLen = 0; + + /* Misc */ + prP2PConnSettings->fgIsScanReqIssued = FALSE; + prP2PConnSettings->fgIsServiceDiscoverIssued = FALSE; + prP2PConnSettings->fgP2pGroupLimit = FALSE; + prP2PConnSettings->ucOperatingChnl = 0; + prP2PConnSettings->ucListenChnl = 0; + prP2PConnSettings->ucTieBreaker = (UINT_8) (kalRandomNumber() & 0x1); + + prP2PConnSettings->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; +#if CFG_SUPPORT_CFG_FILE + /* prP2PConnSettings->fgIsWPSMode = prWifiVar->ucApWpsMode; */ + prAdapter->rWifiVar.prP2pFsmInfo->fgIsWPSMode = prWifiVar->ucApWpsMode; +#endif +} /* p2pFuncInitConnectionSettings */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Assoc Req Frame and then return +* the status code to AAA to indicate if need to perform following actions +* when the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu2StatusCode The Status Code of Validation Result +* +* @retval TRUE Reply the Assoc Resp +* @retval FALSE Don't reply the Assoc Resp +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_16 pu2StatusCode) +{ + BOOLEAN fgReplyAssocResp = TRUE; + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_WFD_ATTRIBUTE_T prWfdAttribute = (P_WFD_ATTRIBUTE_T) NULL; + BOOLEAN fgNeedFree = FALSE; +#endif + /* UINT_16 u2AttriListLen = 0; */ + UINT_16 u2WfdDevInfo = 0; + P_WFD_DEVICE_INFORMATION_IE_T prAttriWfdDevInfo; + + /* TODO(Kevin): Call P2P functions to check .. + 2. Check we can accept connection from thsi peer + a. If we are in PROVISION state, only accept the peer we do the GO formation previously. + b. If we are in OPERATION state, only accept the other peer when P2P_GROUP_LIMIT is 0. + 3. Check Black List here. + */ + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL) && (pu2StatusCode != NULL)); + + *pu2StatusCode = STATUS_CODE_REQ_DECLINED; + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec == NULL) { + /* Station record should be ready while RX AUTH frame. */ + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + prStaRec->u2DesiredNonHTRateSet &= prP2pBssInfo->u2OperationalRateSet; + prStaRec->ucDesiredPhyTypeSet = prStaRec->ucPhyTypeSet & prP2pBssInfo->ucPhyTypeSet; + + if (prStaRec->ucDesiredPhyTypeSet == 0) { + /* The station only support 11B rate. */ + *pu2StatusCode = STATUS_CODE_ASSOC_DENIED_RATE_NOT_SUPPORTED; + break; + } +#if CFG_SUPPORT_WFD && 1 + /* LOG_FUNC("Skip check WFD IE because some API is not ready\n"); */ + if (!prAdapter->rWifiVar.prP2pFsmInfo) { + fgReplyAssocResp = FALSE; + ASSERT(FALSE); + break; + } + + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + DBGLOG(P2P, INFO, "AssocReq, wfd_en %u wfd_info 0x%x wfd_policy 0x%x wfd_flag 0x%x\n", + prWfdCfgSettings->ucWfdEnable, prWfdCfgSettings->u2WfdDevInfo, + prWfdCfgSettings->u4WfdPolicy, prWfdCfgSettings->u4WfdFlag); /* Eddie */ + if (prWfdCfgSettings->ucWfdEnable) { + if (prWfdCfgSettings->u4WfdPolicy & BIT(6)) { + /* Rejected all. */ + break; + } + + /* fgNeedFree = p2pFuncGetAttriList(prAdapter, */ + /* VENDOR_OUI_TYPE_WFD, */ + /* (PUINT_8)prAssocReqFrame->aucInfoElem, */ + /* (prSwRfb->u2PacketLen - OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), */ + /* (PPUINT_8)&prWfdAttribute, */ + /* &u2AttriListLen); */ + + prAttriWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) + p2pFuncGetSpecAttri(prAdapter, + VENDOR_OUI_TYPE_WFD, + (PUINT_8) prAssocReqFrame->aucInfoElem, + (prSwRfb->u2PacketLen - + OFFSET_OF(WLAN_ASSOC_REQ_FRAME_T, aucInfoElem)), + WFD_ATTRI_ID_DEV_INFO); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(5)) && (prAttriWfdDevInfo != NULL)) { + /* Rejected with WFD IE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(0)) && (prAttriWfdDevInfo == NULL)) { + /* Rejected without WFD IE. */ + break; + } + + if (prAttriWfdDevInfo == NULL) { + /* + * Without WFD IE. + * Do nothing. Accept the connection request. + */ + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + break; + } + + /* prAttriWfdDevInfo = */ + /* (P_WFD_DEVICE_INFORMATION_IE_T)p2pFuncGetSpecAttri(prAdapter, */ + /* VENDOR_OUI_TYPE_WFD, */ + /* (PUINT_8)prWfdAttribute, */ + /* u2AttriListLen, */ + /* WFD_ATTRI_ID_DEV_INFO); */ + /* if (prAttriWfdDevInfo == NULL) { */ + /* No such attribute. */ + /* break; */ + /* } */ + + WLAN_GET_FIELD_BE16(&prAttriWfdDevInfo->u2WfdDevInfo, &u2WfdDevInfo); + DBGLOG(P2P, INFO, "RX Assoc Req WFD Info:0x%x.\n", u2WfdDevInfo); + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(1)) && ((u2WfdDevInfo & 0x3) == 0x0)) { + /* Rejected because of SOURCE. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(2)) && ((u2WfdDevInfo & 0x3) == 0x1)) { + /* Rejected because of Primary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(3)) && ((u2WfdDevInfo & 0x3) == 0x2)) { + /* Rejected because of Secondary Sink. */ + break; + } + + if ((prWfdCfgSettings->u4WfdPolicy & BIT(4)) && ((u2WfdDevInfo & 0x3) == 0x3)) { + /* Rejected because of Source & Primary Sink. */ + break; + } + + /* Check role */ + + if ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) && + ((prWfdCfgSettings->u2WfdDevInfo & BITS(0, 1)) == 0x3)) { + /* P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = + * (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T)NULL; */ + UINT_16 u2DevInfo = prWfdCfgSettings->u2WfdDevInfo; + + /* We may change role here if we are dual role */ + + if ((u2WfdDevInfo & BITS(0, 1)) == 0x00 /* Peer is Source */) { + DBGLOG(P2P, INFO, "WFD: Switch role to primary sink\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + prWfdCfgSettings->u2WfdDevInfo |= 0x1; + + /* event to annonce the role is chanaged to P-Sink */ + + } else if ((u2WfdDevInfo & BITS(0, 1)) == 0x01 /* Peer is P-Sink */) { + DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + /* event to annonce the role is chanaged to Source */ + } else { + DBGLOG(P2P, INFO, "WFD: Peer role is wrong type(dev 0x%x)\n", + (u2DevInfo)); + DBGLOG(P2P, INFO, "WFD: Switch role to source\n"); + + prWfdCfgSettings->u2WfdDevInfo &= ~BITS(0, 1); + /* event to annonce the role is chanaged to Source */ + } + + p2pFsmRunEventWfdSettingUpdate(prAdapter, NULL); + + } /* Dual role p2p->wfd_params->WfdDevInfo */ + + /* WFD_FLAG_DEV_INFO_VALID */ + } + /* ucWfdEnable */ +#endif + *pu2StatusCode = STATUS_CODE_SUCCESSFUL; + } while (FALSE); + +#if CFG_SUPPORT_WFD + if ((prWfdAttribute) && (fgNeedFree)) + kalMemFree(prWfdAttribute, VIR_MEM_TYPE, WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE); +#endif + + return fgReplyAssocResp; + +} /* p2pFuncValidateAssocReq */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check the P2P IE +* +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncParseCheckForP2PInfoElem(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + P_IE_WFA_T prWfaIE = (P_IE_WFA_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pucOuiType != NULL)); + + prWfaIE = (P_IE_WFA_T) pucBuf; + + if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { + break; + } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || + prWfaIE->aucOui[1] != aucWfaOui[1] || prWfaIE->aucOui[2] != aucWfaOui[2]) { + break; + } + + *pucOuiType = prWfaIE->ucOuiType; + + return TRUE; + } while (FALSE); + + return FALSE; +} /* p2pFuncParseCheckForP2PInfoElem */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pFuncValidateProbeReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT PUINT_32 pu4ControlFlags) +{ + BOOLEAN fgIsReplyProbeRsp = FALSE; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + DBGLOG(P2P, TRACE, "p2pFuncValidateProbeReq\n"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_PROBE_REQ) { + + DBGLOG(P2P, TRACE, "report probe req to OS\n"); + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return fgIsReplyProbeRsp; + +} /* end of p2pFuncValidateProbeReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will validate the Rx Probe Request Frame and then return +* result to BSS to indicate if need to send the corresponding Probe Response +* Frame if the specified conditions were matched. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to SW RFB data structure. +* @param[out] pu4ControlFlags Control flags for replying the Probe Response +* +* @retval TRUE Reply the Probe Response +* @retval FALSE Don't reply the Probe Response +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncValidateRxActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + + DEBUGFUNC("p2pFuncValidateProbeReq"); + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + if (prP2pFsmInfo->u4P2pPacketFilter & PARAM_PACKET_FILTER_ACTION_FRAME) { + /* Leave the probe response to p2p_supplicant. */ + kalP2PIndicateRxMgmtFrame(prAdapter->prGlueInfo, prSwRfb); + } + + } while (FALSE); + + return; + +} /* p2pFuncValidateRxMgmtFrame */ + +BOOLEAN p2pFuncIsAPMode(IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + if (prP2pFsmInfo) { + if (prP2pFsmInfo->fgIsWPSMode == 1) + return FALSE; + return prP2pFsmInfo->fgIsApMode; + } else { + return FALSE; + } +} + +/* p2pFuncIsAPMode */ + +VOID +p2pFuncParseBeaconContent(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prP2pBssInfo, IN PUINT_8 pucIEInfo, IN UINT_32 u4IELen) +{ + PUINT_8 pucIE = (PUINT_8) NULL; + UINT_16 u2Offset = 0; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + BOOLEAN ucNewSecMode = FALSE; + BOOLEAN ucOldSecMode = FALSE; + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pBssInfo != NULL)); + + if (u4IELen == 0) + break; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pSpecificBssInfo->u2AttributeLen = 0; + + ASSERT_BREAK(pucIEInfo != NULL); + + pucIE = pucIEInfo; + + ucOldSecMode = kalP2PGetCipher(prAdapter->prGlueInfo); + + IE_FOR_EACH(pucIE, u4IELen, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + { + /* 0 */ /* V */ /* Done */ + /* DBGLOG(P2P, TRACE, ("SSID update\n")); */ + /* SSID is saved when start AP/GO */ + /* SSID IE set in beacon from supplicant will not always be */ + /* the true since hidden SSID case */ + /* + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + + COPY_SSID(prP2pSpecificBssInfo->aucGroupSsid, + prP2pSpecificBssInfo->u2GroupSsidLen, + SSID_IE(pucIE)->aucSSID, + SSID_IE(pucIE)->ucLength); + */ + } + break; + case ELEM_ID_SUP_RATES: + { + /* 1 */ /* V */ /* Done */ + DBGLOG(P2P, TRACE, "Support Rate IE\n"); + kalMemCopy(prP2pBssInfo->aucAllSupportedRates, + SUP_RATES_IE(pucIE)->aucSupportedRates, + SUP_RATES_IE(pucIE)->ucLength); + + prP2pBssInfo->ucAllSupportedRatesLen = SUP_RATES_IE(pucIE)->ucLength; + + DBGLOG_MEM8(P2P, TRACE, SUP_RATES_IE(pucIE)->aucSupportedRates, + SUP_RATES_IE(pucIE)->ucLength); + } + break; + case ELEM_ID_DS_PARAM_SET: + { + /* 3 */ /* V */ /* Done */ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = + prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, "DS PARAM IE\n"); + + ASSERT(prP2pConnSettings->ucOperatingChnl == DS_PARAM_IE(pucIE)->ucCurrChnl); + + if (prP2pConnSettings->eBand != BAND_2G4) { + ASSERT(FALSE); + break; + } + /* prP2pBssInfo->ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; */ + + /* prP2pBssInfo->eBand = BAND_2G4; */ + } + break; + case ELEM_ID_TIM: /* 5 */ /* V */ + DBGLOG(P2P, TRACE, "TIM IE\n"); + TIM_IE(pucIE)->ucDTIMPeriod = prP2pBssInfo->ucDTIMPeriod; + break; + case ELEM_ID_ERP_INFO: /* 42 */ /* V */ + { +#if 1 + /* This IE would dynamic change due to FW detection change is required. */ + DBGLOG(P2P, TRACE, "ERP IE will be over write by driver\n"); + DBGLOG(P2P, TRACE, " ucERP: %x.\n", ERP_INFO_IE(pucIE)->ucERP); + +#else + /* This IE would dynamic change due to FW detection change is required. */ + DBGLOG(P2P, TRACE, "ERP IE.\n"); + + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11GN; + + ASSERT(prP2pBssInfo->eBand == BAND_2G4); + + prP2pBssInfo->fgObssErpProtectMode = + ((ERP_INFO_IE(pucIE)->ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE); + + prP2pBssInfo->fgErpProtectMode = + ((ERP_INFO_IE(pucIE)->ucERP & + (ERP_INFO_USE_PROTECTION | ERP_INFO_NON_ERP_PRESENT)) ? TRUE : FALSE); +#endif + + } + break; + case ELEM_ID_HT_CAP: /* 45 */ /* V */ + { +#if 1 + DBGLOG(P2P, TRACE, "HT CAP IE would be overwritten by driver\n"); + + DBGLOG(P2P, TRACE, + "HT Cap Info:%x, AMPDU Param:%x\n", HT_CAP_IE(pucIE)->u2HtCapInfo, + HT_CAP_IE(pucIE)->ucAmpduParam); + + DBGLOG(P2P, TRACE, + "HT Extended Cap Info%x,TX Beamforming Cap Info%x,Ant Selection Cap Info%x\n", + HT_CAP_IE(pucIE)->u2HtExtendedCap, HT_CAP_IE(pucIE)->u4TxBeamformingCap, + HT_CAP_IE(pucIE)->ucAselCap); +#else + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + + /* u2HtCapInfo */ + if ((HT_CAP_IE(pucIE)->u2HtCapInfo & + (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | + HT_CAP_INFO_DSSS_CCK_IN_40M)) == 0) { + prP2pBssInfo->fgAssoc40mBwAllowed = FALSE; + } else { + prP2pBssInfo->fgAssoc40mBwAllowed = TRUE; + } + + if ((HT_CAP_IE(pucIE)->u2HtCapInfo & + (HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M)) == 0) { + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = TRUE; + } else { + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled = FALSE; + } + + /* ucAmpduParam */ + DBGLOG(P2P, TRACE, + "AMPDU setting from supplicant:0x%x, & default value:0x%x\n", + (UINT_8) HT_CAP_IE(pucIE)->ucAmpduParam, + (UINT_8) AMPDU_PARAM_DEFAULT_VAL); + + /* rSupMcsSet */ + /* Can do nothing. the field is default value from other configuration. */ + /* HT_CAP_IE(pucIE)->rSupMcsSet; */ + + /* u2HtExtendedCap */ + ASSERT(HT_CAP_IE(pucIE)->u2HtExtendedCap == + (HT_EXT_CAP_DEFAULT_VAL & + ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE))); + + /* u4TxBeamformingCap */ + ASSERT(HT_CAP_IE(pucIE)->u4TxBeamformingCap == TX_BEAMFORMING_CAP_DEFAULT_VAL); + + /* ucAselCap */ + ASSERT(HT_CAP_IE(pucIE)->ucAselCap == ASEL_CAP_DEFAULT_VAL); +#endif + } + break; + case ELEM_ID_RSN: /* 48 */ /* V */ + { + RSN_INFO_T rRsnIe; + + DBGLOG(P2P, TRACE, "RSN IE\n"); + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_CCMP); + ucNewSecMode = TRUE; + + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &rRsnIe)) { + prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + prP2pBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prP2pBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; + prP2pBssInfo->u2RsnSelectedCapInfo = rRsnIe.u2RsnCap; + } + } + break; + case ELEM_ID_EXTENDED_SUP_RATES: /* 50 */ /* V */ + /* Be attention, + * ELEM_ID_SUP_RATES should be placed before ELEM_ID_EXTENDED_SUP_RATES. */ + DBGLOG(P2P, TRACE, "Ex Support Rate IE\n"); + kalMemCopy(&(prP2pBssInfo->aucAllSupportedRates[prP2pBssInfo->ucAllSupportedRatesLen]), + EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, + EXT_SUP_RATES_IE(pucIE)->ucLength); + + DBGLOG_MEM8(P2P, TRACE, EXT_SUP_RATES_IE(pucIE)->aucExtSupportedRates, + EXT_SUP_RATES_IE(pucIE)->ucLength); + + prP2pBssInfo->ucAllSupportedRatesLen += EXT_SUP_RATES_IE(pucIE)->ucLength; + break; + case ELEM_ID_HT_OP: + { + /* 61 */ /* V */ /* TODO: */ +#if 1 + DBGLOG(P2P, TRACE, "HT OP IE would be overwritten by driver\n"); + + DBGLOG(P2P, TRACE, + " Primary Channel: %x, Info1: %x, Info2: %x, Info3: %x\n", + HT_OP_IE(pucIE)->ucPrimaryChannel, HT_OP_IE(pucIE)->ucInfo1, + HT_OP_IE(pucIE)->u2Info2, HT_OP_IE(pucIE)->u2Info3); +#else + UINT_16 u2Info2 = 0; + + prP2pBssInfo->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + + DBGLOG(P2P, TRACE, "HT OP IE\n"); + + /* ucPrimaryChannel. */ + ASSERT(HT_OP_IE(pucIE)->ucPrimaryChannel == prP2pBssInfo->ucPrimaryChannel); + + /* ucInfo1 */ + prP2pBssInfo->ucHtOpInfo1 = HT_OP_IE(pucIE)->ucInfo1; + + /* u2Info2 */ + u2Info2 = HT_OP_IE(pucIE)->u2Info2; + + if (u2Info2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) { + ASSERT(prP2pBssInfo->eGfOperationMode != GF_MODE_NORMAL); + u2Info2 &= ~HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (u2Info2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) { + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + u2Info2 &= ~HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + switch (u2Info2 & HT_OP_INFO2_HT_PROTECTION) { + case HT_PROTECT_MODE_NON_HT: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NON_HT; + break; + case HT_PROTECT_MODE_NON_MEMBER: + prP2pBssInfo->eHtProtectMode = HT_PROTECT_MODE_NONE; + prP2pBssInfo->eObssHtProtectMode = HT_PROTECT_MODE_NON_MEMBER; + break; + default: + prP2pBssInfo->eHtProtectMode = HT_OP_IE(pucIE)->u2Info2; + break; + } + + /* u2Info3 */ + prP2pBssInfo->u2HtOpInfo3 = HT_OP_IE(pucIE)->u2Info3; + + /* aucBasicMcsSet */ + DBGLOG_MEM8(P2P, TRACE, HT_OP_IE(pucIE)->aucBasicMcsSet, 16); +#endif + } + break; + case ELEM_ID_OBSS_SCAN_PARAMS: /* 74 */ /* V */ + { + DBGLOG(P2P, TRACE, + "ELEM_ID_OBSS_SCAN_PARAMS IE would be replaced by driver\n"); + } + break; + case ELEM_ID_EXTENDED_CAP: /* 127 */ /* V */ + { + DBGLOG(P2P, TRACE, "ELEM_ID_EXTENDED_CAP IE would be replaced by driver\n"); + } + break; + case ELEM_ID_VENDOR: /* 221 */ /* V */ + DBGLOG(P2P, TRACE, "Vender Specific IE\n"); + if (rsnParseCheckForWFAInfoElem + (prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) + && (u2SubTypeVersion == VERSION_WPA)) { + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_TKIP); + ucNewSecMode = TRUE; + kalMemCopy(prP2pSpecificBssInfo->aucWpaIeBuffer, pucIE, + IE_SIZE(pucIE)); + prP2pSpecificBssInfo->u2WpaIeLen = IE_SIZE(pucIE); + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 0, pucIE, + IE_SIZE(pucIE)); + } + /* WMM here. */ + } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { + /* TODO Store the whole P2P IE & generate later. */ + /* Be aware that there may be one or more P2P IE. */ + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + } + } else { + + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache + [prP2pSpecificBssInfo->u2AttributeLen], pucIE, + IE_SIZE(pucIE)); + + prP2pSpecificBssInfo->u2AttributeLen += IE_SIZE(pucIE); + DBGLOG(P2P, TRACE, "Driver unprocessed Vender Specific IE\n"); + ASSERT(FALSE); + } + + /* TODO: Store other Vender IE except for WMM Param. */ + break; + default: + DBGLOG(P2P, TRACE, "Unprocessed element ID:%d\n", IE_ID(pucIE)); + break; + } + } + + if (!ucNewSecMode && ucOldSecMode) + kalP2PSetCipher(prAdapter->prGlueInfo, IW_AUTH_CIPHER_NONE); + + } while (FALSE); + +} /* p2pFuncParseBeaconContent */ + +P_BSS_DESC_T +p2pFuncKeepOnConnection(IN P_ADAPTER_T prAdapter, + IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo, + IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo, IN P_P2P_SCAN_REQ_INFO_T prScanReqInfo) +{ + P_BSS_DESC_T prTargetBss = (P_BSS_DESC_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prConnReqInfo != NULL) && (prChnlReqInfo != NULL) && (prScanReqInfo != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + if (prP2pBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + break; + /* Update connection request information. */ + ASSERT(prConnReqInfo->fgIsConnRequest == TRUE); + + /* Find BSS Descriptor first. */ + prTargetBss = scanP2pSearchDesc(prAdapter, prP2pBssInfo, prConnReqInfo); + + if (prTargetBss == NULL) { + /* Update scan parameter... to scan target device. */ + prScanReqInfo->ucNumChannelList = 1; + prScanReqInfo->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_FULL; + prScanReqInfo->u4BufLength = 0; /* Prevent other P2P ID in IE. */ + prScanReqInfo->fgIsAbort = TRUE; + } else { + prChnlReqInfo->u8Cookie = 0; + prChnlReqInfo->ucReqChnlNum = prTargetBss->ucChannelNum; + prChnlReqInfo->eBand = prTargetBss->eBand; + prChnlReqInfo->eChnlSco = prTargetBss->eSco; + prChnlReqInfo->u4MaxInterval = AIS_JOIN_CH_REQUEST_INTERVAL; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GC_JOIN_REQ; + } + + } while (FALSE); + + return prTargetBss; +} /* p2pFuncKeepOnConnection */ + +/* Currently Only for ASSOC Response Frame. */ +VOID p2pFuncStoreAssocRspIEBuffer(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_JOIN_INFO_T prJoinInfo = (P_P2P_JOIN_INFO_T) NULL; + P_WLAN_ASSOC_RSP_FRAME_T prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) NULL; + INT_16 i2IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prSwRfb != NULL)); + + prAssocRspFrame = (P_WLAN_ASSOC_RSP_FRAME_T) prSwRfb->pvHeader; + + if (prAssocRspFrame->u2FrameCtrl != MAC_FRAME_ASSOC_RSP) + break; + + i2IELen = prSwRfb->u2PacketLen - (WLAN_MAC_HEADER_LEN + + CAP_INFO_FIELD_LEN + STATUS_CODE_FIELD_LEN + AID_FIELD_LEN); + + if (i2IELen <= 0) + break; + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + prJoinInfo = &(prP2pFsmInfo->rJoinInfo); + prJoinInfo->u4BufLength = (UINT_32) i2IELen; + + kalMemCopy(prJoinInfo->aucIEBuf, prAssocRspFrame->aucInfoElem, prJoinInfo->u4BufLength); + + } while (FALSE); + +} /* p2pFuncStoreAssocRspIEBuffer */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set Packet Filter. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] pvSetBuffer Pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_SUPPORTED +* \retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pFuncMgmtFrameRegister(IN P_ADAPTER_T prAdapter, + IN UINT_16 u2FrameType, IN BOOLEAN fgIsRegistered, OUT PUINT_32 pu4P2pPacketFilter) +{ + UINT_32 u4NewPacketFilter = 0; + + DEBUGFUNC("p2pFuncMgmtFrameRegister"); + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (pu4P2pPacketFilter) + u4NewPacketFilter = *pu4P2pPacketFilter; + + switch (u2FrameType) { + case MAC_FRAME_PROBE_REQ: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (fgIsRegistered) { + u4NewPacketFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + u4NewPacketFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, TRACE, "Ask frog to add code for mgmt:%x\n", u2FrameType); + break; + } + + if (pu4P2pPacketFilter) + *pu4P2pPacketFilter = u4NewPacketFilter; + + /* u4NewPacketFilter |= prAdapter->u4OsPacketFilter; */ + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + prAdapter->u4OsPacketFilter |= u4NewPacketFilter; + + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8) &prAdapter->u4OsPacketFilter, + &u4NewPacketFilter, sizeof(u4NewPacketFilter) + ); + + } while (FALSE); + +} /* p2pFuncMgmtFrameRegister */ + +VOID p2pFuncUpdateMgmtFrameRegister(IN P_ADAPTER_T prAdapter, IN UINT_32 u4OsFilter) +{ + + do { + + prAdapter->rWifiVar.prP2pFsmInfo->u4P2pPacketFilter = u4OsFilter; + + if ((prAdapter->u4OsPacketFilter & PARAM_PACKET_FILTER_P2P_MASK) ^ u4OsFilter) { + + prAdapter->u4OsPacketFilter &= ~PARAM_PACKET_FILTER_P2P_MASK; + + prAdapter->u4OsPacketFilter |= (u4OsFilter & PARAM_PACKET_FILTER_P2P_MASK); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RX_FILTER, + TRUE, + FALSE, + FALSE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(UINT_32), + (PUINT_8) &prAdapter->u4OsPacketFilter, &u4OsFilter, sizeof(u4OsFilter) + ); + DBGLOG(P2P, TRACE, "P2P Set PACKET filter:0x%x\n", prAdapter->u4OsPacketFilter); + } + + } while (FALSE); + +} /* p2pFuncUpdateMgmtFrameRegister */ + +VOID p2pFuncGetStationInfo(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucMacAddr, OUT P_P2P_STATION_INFO_T prStaInfo) +{ + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucMacAddr != NULL) && (prStaInfo != NULL)); + + prStaInfo->u4InactiveTime = 0; + prStaInfo->u4RxBytes = 0; + prStaInfo->u4TxBytes = 0; + prStaInfo->u4RxPackets = 0; + prStaInfo->u4TxPackets = 0; + /* TODO: */ + + } while (FALSE); + +} /* p2pFuncGetStationInfo */ + +BOOLEAN +p2pFuncGetAttriList(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, + IN PUINT_8 pucIE, IN UINT_16 u2IELength, OUT PPUINT_8 ppucAttriList, OUT PUINT_16 pu2AttriListLen) +{ + BOOLEAN fgIsAllocMem = FALSE; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_16 u2Offset = 0; + P_IE_P2P_T prIe = (P_IE_P2P_T) NULL; + PUINT_8 pucAttriListStart = (PUINT_8) NULL; + UINT_16 u2AttriListLen = 0, u2BufferSize = 0; + BOOLEAN fgBackupAttributes = FALSE; + UINT_16 u2CopyLen; + + ASSERT(prAdapter); + ASSERT(pucIE); + ASSERT(ppucAttriList); + ASSERT(pu2AttriListLen); + + if (ppucAttriList) + *ppucAttriList = NULL; + if (pu2AttriListLen) + *pu2AttriListLen = 0; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + } else if ((ucOuiType != VENDOR_OUI_TYPE_P2P) +#if CFG_SUPPORT_WFD + && (ucOuiType != VENDOR_OUI_TYPE_WFD) +#endif + ) { + DBGLOG(P2P, INFO, "Not supported OUI Type to parsing 0x%x\n", ucOuiType); + return fgIsAllocMem; + } + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + if (ELEM_ID_VENDOR != IE_ID(pucIE)) + continue; + + prIe = (P_IE_P2P_T) pucIE; + + if (prIe->ucLength <= P2P_OUI_TYPE_LEN) + continue; + + if ((prIe->aucOui[0] == aucWfaOui[0]) && + (prIe->aucOui[1] == aucWfaOui[1]) && + (prIe->aucOui[2] == aucWfaOui[2]) && (ucOuiType == prIe->ucOuiType)) { + + if (!pucAttriListStart) { + pucAttriListStart = &prIe->aucP2PAttributes[0]; + if (prIe->ucLength > P2P_OUI_TYPE_LEN) + u2AttriListLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); + else + ASSERT(FALSE); + continue; + } +/* More than 2 attributes. */ + + if (FALSE == fgBackupAttributes) { + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = + prAdapter->rWifiVar.prP2pSpecificBssInfo; + + fgBackupAttributes = TRUE; + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + kalMemCopy(&prP2pSpecificBssInfo->aucAttributesCache[0], + pucAttriListStart, u2AttriListLen); + + pucAttriListStart = + &prP2pSpecificBssInfo->aucAttributesCache[0]; + + u2BufferSize = P2P_MAXIMUM_ATTRIBUTE_LEN; + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalMemCopy(&prP2pSpecificBssInfo->aucWscAttributesCache + [0], pucAttriListStart, u2AttriListLen); + pucAttriListStart = + &prP2pSpecificBssInfo->aucWscAttributesCache[0]; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + PUINT_8 pucTmpBuf = (PUINT_8) NULL; + + pucTmpBuf = (PUINT_8) + kalMemAlloc(WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE, + VIR_MEM_TYPE); + + if (pucTmpBuf != NULL) { + fgIsAllocMem = TRUE; + } else { + /* Can't alloca memory for WFD IE relocate. */ + ASSERT(FALSE); + break; + } + + kalMemCopy(pucTmpBuf, + pucAttriListStart, u2AttriListLen); + + pucAttriListStart = pucTmpBuf; + + u2BufferSize = WPS_MAXIMUM_ATTRIBUTES_CACHE_SIZE; + } +#endif + else + fgBackupAttributes = FALSE; + } + + u2CopyLen = (UINT_16) (prIe->ucLength - P2P_OUI_TYPE_LEN); + + if ((u2AttriListLen + u2CopyLen) > u2BufferSize) { + u2CopyLen = u2BufferSize - u2AttriListLen; + DBGLOG(P2P, WARN, + "Length of received P2P attributes > maximum cache size.\n"); + } + + if (u2CopyLen) { + kalMemCopy((PUINT_8) + ((ULONG) pucAttriListStart + + (UINT_32) u2AttriListLen), + &prIe->aucP2PAttributes[0], u2CopyLen); + + u2AttriListLen += u2CopyLen; + } + } /* prIe->aucOui */ + } /* IE_FOR_EACH */ + + if (pucAttriListStart) { + PUINT_8 pucAttribute = pucAttriListStart; + + DBGLOG(P2P, LOUD, "Checking Attribute Length.\n"); + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset); + } else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + /* Do nothing */ + } else if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + /* Big Endian: WSC, WFD. */ + WSC_ATTRI_FOR_EACH(pucAttribute, u2AttriListLen, u2Offset) { + DBGLOG(P2P, LOUD, "Attribute ID:%d, Length:%d.\n", + WSC_ATTRI_ID(pucAttribute), WSC_ATTRI_LEN(pucAttribute)); + } + } else { + } + + ASSERT(u2Offset == u2AttriListLen); + + if (ppucAttriList) + *ppucAttriList = pucAttriListStart; + if (pu2AttriListLen) + *pu2AttriListLen = u2AttriListLen; + + } else { + if (ppucAttriList) + *ppucAttriList = (PUINT_8) NULL; + if (pu2AttriListLen) + *pu2AttriListLen = 0; + } + + return fgIsAllocMem; +} /* p2pFuncGetAttriList */ + +P_MSDU_INFO_T p2pFuncProcessP2pProbeRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMgmtTxMsdu) +{ + P_MSDU_INFO_T prRetMsduInfo = prMgmtTxMsdu; + P_WLAN_PROBE_RSP_FRAME_T prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + UINT_16 u2Offset = 0, u2IELength = 0, u2ProbeRspHdrLen = 0; + BOOLEAN fgIsP2PIE = FALSE, fgIsWSCIE = FALSE; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + UINT_16 u2EstimateSize = 0, u2EstimatedExtraIELen = 0; + UINT_32 u4IeArraySize = 0, u4Idx = 0; + UINT_8 ucOuiType = 0; + UINT_16 u2SubTypeVersion = 0; + + BOOLEAN fgIsPureAP = prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMgmtTxMsdu != NULL)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + /* 3 Make sure this is probe response frame. */ + prProbeRspFrame = (P_WLAN_PROBE_RSP_FRAME_T) ((ULONG) prMgmtTxMsdu->prPacket + MAC_TX_RESERVED_FIELD); + ASSERT_BREAK((prProbeRspFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_PROBE_RSP); + + if (prP2pBssInfo->u2BeaconInterval) + prProbeRspFrame->u2BeaconInterval = prP2pBssInfo->u2BeaconInterval; + + /* 3 Get the importent P2P IE. */ + u2ProbeRspHdrLen = + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + pucIEBuf = prProbeRspFrame->aucInfoElem; + u2IELength = prMgmtTxMsdu->u2FrameLength - u2ProbeRspHdrLen; + +#if CFG_SUPPORT_WFD + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen = 0; +#endif + + IE_FOR_EACH(pucIEBuf, u2IELength, u2Offset) { + switch (IE_ID(pucIEBuf)) { + case ELEM_ID_SSID: + { + + COPY_SSID(prP2pBssInfo->aucSSID, + prP2pBssInfo->ucSSIDLen, + SSID_IE(pucIEBuf)->aucSSID, SSID_IE(pucIEBuf)->ucLength); + } + break; + case ELEM_ID_VENDOR: +#if !CFG_SUPPORT_WFD + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 2, pucIEBuf, + IE_SIZE(pucIEBuf)); + fgIsWSCIE = TRUE; + } + + } else if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIEBuf, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + /* 2 Note(frog): I use WSC IE buffer for Probe Request to + * store the P2P IE for Probe Response. */ + kalP2PUpdateWSC_IE(prAdapter->prGlueInfo, 1, pucIEBuf, + IE_SIZE(pucIEBuf)); + fgIsP2PIE = TRUE; + } + + } else { + if ((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen + + IE_SIZE(pucIEBuf)) < 512) { + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, + pucIEBuf, IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += + IE_SIZE(pucIEBuf); + } + } +#else + /* Eddie May be WFD */ + if (rsnParseCheckForWFAInfoElem + (prAdapter, pucIEBuf, &ucOuiType, &u2SubTypeVersion)) { + if (ucOuiType == VENDOR_OUI_TYPE_WMM) + break; + + } + if ((prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen + IE_SIZE(pucIEBuf)) < + 1024) { + kalMemCopy(prAdapter->prGlueInfo->prP2PInfo->aucVenderIE + + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen, pucIEBuf, + IE_SIZE(pucIEBuf)); + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen += IE_SIZE(pucIEBuf); + } +#endif + break; + default: + break; + } + + } + + /* 3 Check the total size & current frame. */ + u2EstimateSize = WLAN_MAC_MGMT_HEADER_LEN + + TIMESTAMP_FIELD_LEN + + BEACON_INTERVAL_FIELD_LEN + + CAP_INFO_FIELD_LEN + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SSID) + + (ELEM_HDR_LEN + ELEM_MAX_LEN_SUP_RATES) + (ELEM_HDR_LEN + ELEM_MAX_LEN_DS_PARAMETER_SET); + + u2EstimatedExtraIELen = 0; + + u4IeArraySize = sizeof(txProbeRspIETable) / sizeof(APPEND_VAR_IE_ENTRY_T); + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].u2EstimatedFixedIELen) { + u2EstimatedExtraIELen += txProbeRspIETable[u4Idx].u2EstimatedFixedIELen; + } + + else { + ASSERT(txProbeRspIETable[u4Idx].pfnCalculateVariableIELen); + + u2EstimatedExtraIELen += + (UINT_16) (txProbeRspIETable[u4Idx].pfnCalculateVariableIELen + (prAdapter, NETWORK_TYPE_P2P_INDEX, NULL)); + } + + } + + if (fgIsWSCIE) + u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); + + if (fgIsP2PIE) { + u2EstimatedExtraIELen += kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); + u2EstimatedExtraIELen += p2pFuncCalculateP2P_IE_NoA(prAdapter, 0, NULL); + } +#if CFG_SUPPORT_WFD + u2EstimatedExtraIELen += prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; +#endif + + u2EstimateSize += u2EstimatedExtraIELen; + if (u2EstimateSize > (prRetMsduInfo->u2FrameLength)) { + prRetMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimateSize); + + if (prRetMsduInfo == NULL) { + DBGLOG(P2P, WARN, "No packet for sending new probe response, use original one\n"); + prRetMsduInfo = prMgmtTxMsdu; + break; + } + + prRetMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + } + /* 3 Compose / Re-compose probe response frame. */ + bssComposeBeaconProbeRespFrameHeaderAndFF((PUINT_8) + ((ULONG) (prRetMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prProbeRspFrame->aucDestAddr, prProbeRspFrame->aucSrcAddr, + prProbeRspFrame->aucBSSID, prProbeRspFrame->u2BeaconInterval, + fgIsPureAP ? prP2pBssInfo-> + u2CapInfo : prProbeRspFrame->u2CapInfo); + + prRetMsduInfo->u2FrameLength = + (WLAN_MAC_MGMT_HEADER_LEN + TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN); + + bssBuildBeaconProbeRespFrameCommonIEs(prRetMsduInfo, prP2pBssInfo, prProbeRspFrame->aucDestAddr); + + for (u4Idx = 0; u4Idx < u4IeArraySize; u4Idx++) { + if (txProbeRspIETable[u4Idx].pfnAppendIE) + txProbeRspIETable[u4Idx].pfnAppendIE(prAdapter, prRetMsduInfo); + + } + + if (fgIsWSCIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 2, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (UINT_32) prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 2); + } + + if (fgIsP2PIE) { + kalP2PGenWSC_IE(prAdapter->prGlueInfo, + 1, + (PUINT_8) ((ULONG) prRetMsduInfo->prPacket + + (UINT_32) prRetMsduInfo->u2FrameLength)); + + prRetMsduInfo->u2FrameLength += (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 1); + p2pFuncGenerateP2P_IE_NoA(prAdapter, prRetMsduInfo); + } +#if CFG_SUPPORT_WFD + if (prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen > 0) { + kalMemCopy((PUINT_8) ((ULONG) prRetMsduInfo->prPacket + (UINT_32) prRetMsduInfo->u2FrameLength), + prAdapter->prGlueInfo->prP2PInfo->aucVenderIE, + prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen); + prRetMsduInfo->u2FrameLength += (UINT_16) prAdapter->prGlueInfo->prP2PInfo->u2VenderIELen; + } +#endif + + } while (FALSE); + + if (prRetMsduInfo != prMgmtTxMsdu) + cnmMgtPktFree(prAdapter, prMgmtTxMsdu); + + return prRetMsduInfo; +} /* p2pFuncProcessP2pProbeRsp */ + +#if 0 /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +UINT_32 +p2pFuncCalculateExtra_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateExtra_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (PUINT_8) ((UINT_32) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucBeaconIECache, prP2pSpeBssInfo->u2IELenForBCN); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2IELenForBCN; + + } while (FALSE); + +} /* p2pFuncGenerateExtra_IEForBeacon */ + +#else +UINT_32 +p2pFuncCalculateP2p_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + UINT_32 u4IELen = 0; + + do { + ASSERT_BREAK((prAdapter != NULL) && (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4IELen = prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + + return u4IELen; +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateP2p_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpeBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + if (!prAdapter->fgIsP2PRegistered) + break; + + prP2pSpeBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + break; + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prP2pSpeBssInfo->aucAttributesCache, prP2pSpeBssInfo->u2AttributeLen); + + prMsduInfo->u2FrameLength += prP2pSpeBssInfo->u2AttributeLen; + + } while (FALSE); + +} /* p2pFuncGenerateP2p_IEForBeacon */ + +UINT_32 +p2pFuncCalculateWSC_IELenForBeacon(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForBeacon */ + +VOID p2pFuncGenerateWSC_IEForBeacon(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) + return; + + u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + +} /* p2pFuncGenerateP2p_IEForBeacon */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate P2P IE length for Beacon frame. +* +* @param[in] eNetTypeIndex Specify which network +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of P2P IE added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 +p2pFuncCalculateP2p_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + eNetTypeIndex, + prStaRec, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pFuncGenerateP2p_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) + break; + + if (IS_STA_P2P_TYPE(prStaRec)) { + DBGLOG(P2P, TRACE, "Generate NULL P2P IE for Assoc Rsp.\n"); + + p2pFuncGenerateP2P_IE(prAdapter, + TRUE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspAttributesTable, + sizeof(txAssocRspAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + } else { + + DBGLOG(P2P, TRACE, "Legacy device, no P2P IE.\n"); + } + + } while (FALSE); + + return; + +} /* p2pFuncGenerateP2p_IEForAssocRsp */ + +UINT_32 +p2pFuncCalculateWSC_IELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + DBGLOG(P2P, TRACE, "p2pFuncCalculateWSC_IELenForAssocRsp\n"); + if (eNetTypeIndex != NETWORK_TYPE_P2P_INDEX) + return 0; + + return kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); +} /* p2pFuncCalculateP2p_IELenForAssocRsp */ + +VOID p2pFuncGenerateWSC_IEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + UINT_16 u2IELen = 0; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_P2P_INDEX) + return; + DBGLOG(P2P, TRACE, "p2pFuncGenerateWSC_IEForAssocRsp\n"); + + u2IELen = (UINT_16) kalP2PCalWSC_IELen(prAdapter->prGlueInfo, 0); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* TODO: Check P2P FSM State. */ + kalP2PGenWSC_IE(prAdapter->prGlueInfo, 0, pucBuffer); + + prMsduInfo->u2FrameLength += u2IELen; + +} + +/* p2pFuncGenerateP2p_IEForAssocRsp */ + +UINT_32 +p2pFuncCalculateP2P_IELen(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN P_STA_RECORD_T prStaRec, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + + UINT_32 u4OverallAttriLen, u4Dummy; + UINT_16 u2EstimatedFixedAttriLen; + UINT_32 i; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + u2EstimatedFixedAttriLen = arAppendAttriTable[i].u2EstimatedFixedAttriLen; + + if (u2EstimatedFixedAttriLen) { + u4OverallAttriLen += u2EstimatedFixedAttriLen; + } else { + ASSERT(arAppendAttriTable[i].pfnCalculateVariableAttriLen); + + u4OverallAttriLen += arAppendAttriTable[i].pfnCalculateVariableAttriLen(prAdapter, prStaRec); + } + } + + u4Dummy = u4OverallAttriLen; + u4OverallAttriLen += P2P_IE_OUI_HDR; + + for (; (u4Dummy > P2P_MAXIMUM_ATTRIBUTE_LEN);) { + u4OverallAttriLen += P2P_IE_OUI_HDR; + u4Dummy -= P2P_MAXIMUM_ATTRIBUTE_LEN; + } + + return u4OverallAttriLen; +} /* p2pFuncCalculateP2P_IELen */ + +VOID +p2pFuncGenerateP2P_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + PUINT_8 pucBuffer = (PUINT_8) NULL; + P_IE_P2P_T prIeP2P = (P_IE_P2P_T) NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= P2P_IE_OUI_HDR); + + prIeP2P = (P_IE_P2P_T) pucBuffer; + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + (*pu2Offset) += P2P_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = + arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, + u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeP2P->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = + (PUINT_8) ((ULONG) prIeP2P + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeP2P = (P_IE_P2P_T) ((ULONG) prIeP2P + + (ELEM_HDR_LEN + + (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN))); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeP2P->ucId = ELEM_ID_P2P; + + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + kalMemCopy(prIeP2P->aucP2PAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += P2P_IE_OUI_HDR; + } + + } + + } + + prIeP2P->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); + +} /* p2pFuncGenerateP2P_IE */ + +UINT_32 +p2pFuncAppendAttriStatusForAssocRsp(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + PUINT_8 pucBuffer; + P_P2P_ATTRI_STATUS_T prAttriStatus; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_32 u4AttriLen = 0; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For assoc request P2P IE check in driver & return status in P2P IE. */ + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT(pucBuffer); + prAttriStatus = (P_P2P_ATTRI_STATUS_T) pucBuffer; + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); + + prAttriStatus->ucId = P2P_ATTRI_ID_STATUS; + WLAN_SET_FIELD_16(&prAttriStatus->u2Length, P2P_ATTRI_MAX_LEN_STATUS); + + prAttriStatus->ucStatusCode = P2P_STATUS_FAIL_PREVIOUS_PROTOCOL_ERR; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_STATUS); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriStatusForAssocRsp */ + +UINT_32 +p2pFuncAppendAttriExtListenTiming(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + P_P2P_ATTRI_EXT_LISTEN_TIMING_T prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + PUINT_8 pucBuffer = NULL; + + ASSERT(prAdapter); + ASSERT(pucBuf); + + if (fgIsAssocFrame) + return u4AttriLen; + /* TODO: For extend listen timing. */ + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + u4AttriLen = (P2P_ATTRI_HDR_LEN + P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + + ASSERT(u2BufSize >= ((*pu2Offset) + (UINT_16) u4AttriLen)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT(pucBuffer); + + prP2pExtListenTiming = (P_P2P_ATTRI_EXT_LISTEN_TIMING_T) pucBuffer; + + prP2pExtListenTiming->ucId = P2P_ATTRI_ID_EXT_LISTEN_TIMING; + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2Length, P2P_ATTRI_MAX_LEN_EXT_LISTEN_TIMING); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailInterval, prP2pSpecificBssInfo->u2AvailabilityInterval); + WLAN_SET_FIELD_16(&prP2pExtListenTiming->u2AvailPeriod, prP2pSpecificBssInfo->u2AvailabilityPeriod); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} /* p2pFuncAppendAttriExtListenTiming */ + +P_IE_HDR_T +p2pFuncGetSpecIE(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_8 ucElemID, IN PBOOLEAN pfgIsMore) +{ + P_IE_HDR_T prTargetIE = (P_IE_HDR_T) NULL; + PUINT_8 pucIE = (PUINT_8) NULL; + UINT_16 u2Offset = 0; + + if (pfgIsMore) + *pfgIsMore = FALSE; + + do { + ASSERT_BREAK((prAdapter != NULL) + && (pucIEBuf != NULL)); + + pucIE = pucIEBuf; + + IE_FOR_EACH(pucIE, u2BufferLen, u2Offset) { + if (IE_ID(pucIE) == ucElemID) { + if ((prTargetIE) && (pfgIsMore)) { + + *pfgIsMore = TRUE; + break; + } + prTargetIE = (P_IE_HDR_T) pucIE; + + if (pfgIsMore == NULL) + break; + + } + } + + } while (FALSE); + + return prTargetIE; +} /* p2pFuncGetSpecIE */ + +P_ATTRIBUTE_HDR_T +p2pFuncGetSpecAttri(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucOuiType, IN PUINT_8 pucIEBuf, IN UINT_16 u2BufferLen, IN UINT_16 u2AttriID) +{ + P_IE_P2P_T prP2pIE = (P_IE_P2P_T) NULL; + P_ATTRIBUTE_HDR_T prTargetAttri = (P_ATTRIBUTE_HDR_T) NULL; + BOOLEAN fgIsMore = FALSE; + PUINT_8 pucIE = (PUINT_8) NULL, pucAttri = (PUINT_8) NULL; + UINT_16 u2OffsetAttri = 0; + UINT_16 u2BufferLenLeft = 0; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + + DBGLOG(P2P, INFO, "Check AssocReq Oui type %u attri %u for len %u\n", ucOuiType, u2AttriID, u2BufferLen); + + ASSERT(prAdapter); + ASSERT(pucIEBuf); + + u2BufferLenLeft = u2BufferLen; + pucIE = pucIEBuf; + do { + fgIsMore = FALSE; + prP2pIE = (P_IE_P2P_T) p2pFuncGetSpecIE(prAdapter, + pucIE, u2BufferLenLeft, ELEM_ID_VENDOR, &fgIsMore); + if (prP2pIE == NULL) + continue; + + ASSERT((ULONG) prP2pIE >= (ULONG) pucIE); + + u2BufferLenLeft = u2BufferLen - (UINT_16) (((ULONG) prP2pIE) - ((ULONG) pucIEBuf)); + + DBGLOG(P2P, INFO, "Find vendor id %u len %u oui %u more %u LeftLen %u\n", + IE_ID(prP2pIE), IE_LEN(prP2pIE), prP2pIE->ucOuiType, fgIsMore, + u2BufferLenLeft); + + if ((IE_LEN(prP2pIE) > P2P_OUI_TYPE_LEN) && (prP2pIE->ucOuiType == ucOuiType)) { + switch (ucOuiType) { + case VENDOR_OUI_TYPE_WPS: + aucWfaOui[0] = 0x00; + aucWfaOui[1] = 0x50; + aucWfaOui[2] = 0xF2; + break; + case VENDOR_OUI_TYPE_P2P: + break; + case VENDOR_OUI_TYPE_WPA: + case VENDOR_OUI_TYPE_WMM: + case VENDOR_OUI_TYPE_WFD: + default: + break; + } + + if ((prP2pIE->aucOui[0] != aucWfaOui[0]) + || (prP2pIE->aucOui[1] != aucWfaOui[1]) + || (prP2pIE->aucOui[2] != aucWfaOui[2])) + continue; + + u2OffsetAttri = 0; + pucAttri = prP2pIE->aucP2PAttributes; + + if (ucOuiType == VENDOR_OUI_TYPE_WPS) { + WSC_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* LOG_FUNC("WSC: attri id=%u len=%u\n", + * WSC_ATTRI_ID(pucAttri), + * WSC_ATTRI_LEN(pucAttri)); */ + if (WSC_ATTRI_ID(pucAttri) == u2AttriID) { + prTargetAttri = + (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + + } else if (ucOuiType == VENDOR_OUI_TYPE_P2P) { + P2P_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* LOG_FUNC("P2P: attri id=%u len=%u\n", + * ATTRI_ID(pucAttri), ATTRI_LEN(pucAttri)); */ + if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { + prTargetAttri = (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + } +#if CFG_SUPPORT_WFD + else if (ucOuiType == VENDOR_OUI_TYPE_WFD) { + WFD_ATTRI_FOR_EACH(pucAttri, + (IE_LEN(prP2pIE) - P2P_OUI_TYPE_LEN), u2OffsetAttri) { + /* DBGLOG(P2P, INFO, ("WFD: attri id=%u + * len=%u\n",WFD_ATTRI_ID(pucAttri), + * WFD_ATTRI_LEN(pucAttri))); */ + if (ATTRI_ID(pucAttri) == (UINT_8) u2AttriID) { + prTargetAttri = + (P_ATTRIBUTE_HDR_T) pucAttri; + break; + } + } + } +#endif + /* Do nothing */ + /* Possible or else. */ + } /* ucOuiType */ + /* P2P_OUI_TYPE_LEN */ + pucIE = (PUINT_8) (((ULONG) prP2pIE) + IE_SIZE(prP2pIE)); + /* prP2pIE */ + } while (prP2pIE && fgIsMore && u2BufferLenLeft); + + return prTargetAttri; +} + +/* p2pFuncGetSpecAttri */ + +WLAN_STATUS +p2pFuncGenerateBeaconProbeRsp(IN P_ADAPTER_T prAdapter, + IN P_BSS_INFO_T prBssInfo, IN P_MSDU_INFO_T prMsduInfo, IN BOOLEAN fgIsProbeRsp) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_WLAN_BEACON_FRAME_T prBcnFrame = (P_WLAN_BEACON_FRAME_T) NULL; +/* P_APPEND_VAR_IE_ENTRY_T prAppendIeTable = (P_APPEND_VAR_IE_ENTRY_T)NULL; */ + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prBssInfo != NULL) && (prMsduInfo != NULL)); + +/* txBcnIETable */ + +/* txProbeRspIETable */ + + prBcnFrame = (P_WLAN_BEACON_FRAME_T) prMsduInfo->prPacket; + + return nicUpdateBeaconIETemplate(prAdapter, + IE_UPD_METHOD_UPDATE_ALL, + NETWORK_TYPE_P2P_INDEX, + prBssInfo->u2CapInfo, + (PUINT_8) prBcnFrame->aucInfoElem, + prMsduInfo->u2FrameLength - OFFSET_OF(WLAN_BEACON_FRAME_T, + aucInfoElem)); + + } while (FALSE); + + return rWlanStatus; +} /* p2pFuncGenerateBeaconProbeRsp */ + +WLAN_STATUS +p2pFuncComposeBeaconProbeRspTemplate(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBcnBuffer, + IN UINT_32 u4BcnBufLen, + IN BOOLEAN fgIsProbeRsp, + IN P_P2P_PROBE_RSP_UPDATE_INFO_T prP2pProbeRspInfo, IN BOOLEAN fgSynToFW) +{ + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + P_WLAN_MAC_HEADER_T prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + PUINT_8 pucBuffer = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBcnBuffer != NULL)); + + prWlanBcnFrame = (P_WLAN_MAC_HEADER_T) pucBcnBuffer; + + if ((prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_BEACON) && (!fgIsProbeRsp)) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + else if (prWlanBcnFrame->u2FrameCtrl != MAC_FRAME_PROBE_RSP) { + rWlanStatus = WLAN_STATUS_INVALID_DATA; + break; + } + + if (fgIsProbeRsp) { + ASSERT_BREAK(prP2pProbeRspInfo != NULL); + + if (prP2pProbeRspInfo->prProbeRspMsduTemplate) + cnmMgtPktFree(prAdapter, prP2pProbeRspInfo->prProbeRspMsduTemplate); + + prP2pProbeRspInfo->prProbeRspMsduTemplate = cnmMgtPktAlloc(prAdapter, u4BcnBufLen); + + prMsduInfo = prP2pProbeRspInfo->prProbeRspMsduTemplate; + + prMsduInfo->eSrc = TX_PACKET_MGMT; + prMsduInfo->ucStaRecIndex = 0xFF; + prMsduInfo->ucNetworkType = NETWORK_TYPE_P2P_INDEX; + + } else { + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prMsduInfo = prP2pBssInfo->prBeacon; + + if (prMsduInfo == NULL) { + rWlanStatus = WLAN_STATUS_FAILURE; + break; + } + + if (u4BcnBufLen > (OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH)) { + /* Unexpected error, buffer overflow. */ + ASSERT(FALSE); + break; + } + + } + + pucBuffer = (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucBuffer, pucBcnBuffer, u4BcnBufLen); + + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = (UINT_16) u4BcnBufLen; + + if (fgSynToFW && prP2pBssInfo) + rWlanStatus = p2pFuncGenerateBeaconProbeRsp(prAdapter, prP2pBssInfo, prMsduInfo, fgIsProbeRsp); + + } while (FALSE); + + return rWlanStatus; + +} /* p2pFuncComposeBeaconTemplate */ + +#if CFG_SUPPORT_WFD +WLAN_STATUS wfdAdjustResource(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) +{ +#if 1 + /* The API shall be called in tx_thread */ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); + if (fgEnable) { + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + if (QM_GUARANTEED_TC0_RESOURCE > 2) { + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE - 2; + prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; + } + if (QM_GUARANTEED_TC1_RESOURCE > 2) { + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE - 2; + prQM->au4GuaranteedTcResource[TC2_INDEX] += 2; + } + } else { + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; + prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + } +#endif + return WLAN_STATUS_SUCCESS; +} + +WLAN_STATUS wfdAdjustThread(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnable) +{ +#define WFD_TX_THREAD_PRIORITY 70 + DBGLOG(P2P, INFO, "wfdAdjustResource %d\n", fgEnable); + if (prAdapter->prGlueInfo->main_thread != NULL) { + if (fgEnable) { +#ifdef LINUX + /* TODO the change schedule API shall be provided by OS glue layer */ + /* Or the API shall be put in os glue layer */ + struct sched_param param = {.sched_priority = WFD_TX_THREAD_PRIORITY }; + + sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_RR, ¶m); +#endif + } else { +#ifdef LINUX + /* TODO the change schedule API shall be provided by OS glue layer */ + struct sched_param param = {.sched_priority = 0 }; + + sched_setscheduler(prAdapter->prGlueInfo->main_thread, SCHED_NORMAL, ¶m); +#endif + } + } else { + + DBGLOG(P2P, WARN, "main_thread is null, please check if the wlanRemove is called in advance\n"); + } + return WLAN_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_WFD */ + +WLAN_STATUS wfdChangeMediaState(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx, ENUM_PARAM_MEDIA_STATE_T eConnectionState) +{ +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered == FALSE) + return WLAN_STATUS_SUCCESS; + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + + if ((prWfdCfgSettings->ucWfdEnable) && ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID))) { + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == + PARAM_MEDIA_STATE_CONNECTED) { + wfdAdjustResource(prAdapter, TRUE); + wfdAdjustThread(prAdapter, TRUE); + } else { + wfdAdjustResource(prAdapter, FALSE); + wfdAdjustThread(prAdapter, FALSE); + } + + } +#endif + return WLAN_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c new file mode 100644 index 0000000000000..991861f736082 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_ie.c @@ -0,0 +1,612 @@ +#include "p2p_precomp.h" + +#if CFG_SUPPORT_WFD +#if CFG_SUPPORT_WFD_COMPOSE_IE +#if 0 +APPEND_VAR_ATTRI_ENTRY_T txProbeRspWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_EXT_CAPABILITY), NULL, wfdFuncAppendAttriExtCapability} /* 7 */ + , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txBeaconWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ +}; + +APPEND_VAR_ATTRI_ENTRY_T txAssocReqWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ +}; +#endif + +APPEND_VAR_ATTRI_ENTRY_T txAssocRspWFDAttributesTable[] = { + {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_DEV_INFO), NULL, wfdFuncAppendAttriDevInfo} /* 0 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_ASSOC_BSSID), NULL, wfdFuncAppendAttriAssocBssid} /* 1 */ + , {(WFD_ATTRI_HDR_LEN + WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO), NULL, wfdFuncAppendAttriCoupledSinkInfo} /* 6 */ + , {0, wfdFuncCalculateAttriLenSessionInfo, wfdFuncAppendAttriSessionInfo} /* 9 */ + +}; + +#endif + +UINT_32 +p2pCalculate_IEForAssocReq(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + UINT_32 u4RetValue = 0; + + do { + ASSERT_BREAK((eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) && (prAdapter != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + u4RetValue = prConnReqInfo->u4BufLength; + + /* ADD HT Capability */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP); + + /* ADD WMM Information Element */ + u4RetValue += (ELEM_HDR_LEN + ELEM_MAX_LEN_WMM_INFO); + + } while (FALSE); + + return u4RetValue; +} /* p2pCalculate_IEForAssocReq */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to generate P2P IE for Beacon frame. +* +* @param[in] prMsduInfo Pointer to the composed MSDU_INFO_T. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pGenerate_IEForAssocReq(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo = (P_P2P_CONNECTION_REQ_INFO_T) NULL; + PUINT_8 pucIEBuf = (PUINT_8) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prMsduInfo != NULL)); + + prP2pFsmInfo = prAdapter->rWifiVar.prP2pFsmInfo; + + prConnReqInfo = &(prP2pFsmInfo->rConnReqInfo); + + pucIEBuf = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + kalMemCopy(pucIEBuf, prConnReqInfo->aucIEBuf, prConnReqInfo->u4BufLength); + + prMsduInfo->u2FrameLength += prConnReqInfo->u4BufLength; + + rlmReqGenerateHtCapIE(prAdapter, prMsduInfo); + mqmGenerateWmmInfoIE(prAdapter, prMsduInfo); + + } while (FALSE); + + return; + +} /* p2pGenerate_IEForAssocReq */ + +UINT_32 +wfdFuncAppendAttriDevInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_DEVICE_INFORMATION_IE_T prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdDevInfo = (P_WFD_DEVICE_INFORMATION_IE_T) pucBuffer; + + prWfdDevInfo->ucElemID = WFD_ATTRI_ID_DEV_INFO; + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevInfo, prWfdCfgSettings->u2WfdDevInfo); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2SessionMgmtCtrlPort, prWfdCfgSettings->u2WfdControlPort); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2WfdDevMaxSpeed, prWfdCfgSettings->u2WfdMaximumTp); + + WLAN_SET_FIELD_BE16(&prWfdDevInfo->u2Length, WFD_ATTRI_MAX_LEN_DEV_INFO); + + u4AttriLen = WFD_ATTRI_MAX_LEN_DEV_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriDevInfo */ + +UINT_32 +wfdFuncAppendAttriAssocBssid(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_ASSOCIATED_BSSID_IE_T prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_BSS_INFO_T prAisBssInfo = (P_BSS_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if (prWfdCfgSettings->ucWfdEnable == 0) + break; + + /* AIS network. */ + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if ((!IS_NET_ACTIVE(prAdapter, NETWORK_TYPE_AIS_INDEX)) || + (prAisBssInfo->eConnectionState != PARAM_MEDIA_STATE_CONNECTED)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdAssocBssid = (P_WFD_ASSOCIATED_BSSID_IE_T) pucBuffer; + + prWfdAssocBssid->ucElemID = WFD_ATTRI_ID_ASSOC_BSSID; + + WLAN_SET_FIELD_BE16(&prWfdAssocBssid->u2Length, WFD_ATTRI_MAX_LEN_ASSOC_BSSID); + + COPY_MAC_ADDR(prWfdAssocBssid->aucAssocBssid, prAisBssInfo->aucBSSID); + + u4AttriLen = WFD_ATTRI_MAX_LEN_ASSOC_BSSID + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriAssocBssid */ + +UINT_32 +wfdFuncAppendAttriCoupledSinkInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_COUPLE_SINK_INFORMATION_IE_T prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_SINK_INFO_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdCoupleSinkInfo = (P_WFD_COUPLE_SINK_INFORMATION_IE_T) pucBuffer; + + prWfdCoupleSinkInfo->ucElemID = WFD_ATTRI_ID_COUPLED_SINK_INFO; + + WLAN_SET_FIELD_BE16(&prWfdCoupleSinkInfo->u2Length, WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO); + + COPY_MAC_ADDR(prWfdCoupleSinkInfo->aucCoupleSinkMac, prWfdCfgSettings->aucWfdCoupleSinkAddress); + + prWfdCoupleSinkInfo->ucCoupleSinkStatusBp = prWfdCfgSettings->ucWfdCoupleSinkStatus; + + u4AttriLen = WFD_ATTRI_MAX_LEN_COUPLED_SINK_INFO + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriCoupledSinkInfo */ + +UINT_32 +wfdFuncAppendAttriExtCapability(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_EXTENDED_CAPABILITY_IE_T prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || + ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_EXT_CAPABILITY_VALID) == 0)) { + break; + } + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdExtCapability = (P_WFD_EXTENDED_CAPABILITY_IE_T) pucBuffer; + + prWfdExtCapability->ucElemID = WFD_ATTRI_ID_EXT_CAPABILITY; + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2Length, WFD_ATTRI_MAX_LEN_EXT_CAPABILITY); + + WLAN_SET_FIELD_BE16(&prWfdExtCapability->u2WfdExtCapabilityBp, prWfdCfgSettings->u2WfdExtendCap); + + u4AttriLen = WFD_ATTRI_MAX_LEN_EXT_CAPABILITY + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriExtCapability */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to calculate length of Channel List Attribute +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return The length of Attribute added +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 wfdFuncCalculateAttriLenSessionInfo(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + UINT_16 u2AttriLen = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prStaRec != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + if (prWfdCfgSettings->ucWfdEnable == 0) + break; + + u2AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + return (UINT_32) u2AttriLen; + +} /* wfdFuncCalculateAttriLenSessionInfo */ + +UINT_32 +wfdFuncAppendAttriSessionInfo(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, IN PUINT_16 pu2Offset, IN PUINT_8 pucBuf, IN UINT_16 u2BufSize) +{ + UINT_32 u4AttriLen = 0; + PUINT_8 pucBuffer = NULL; + P_WFD_SESSION_INFORMATION_IE_T prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) NULL; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL) && (pu2Offset != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + ASSERT_BREAK((prWfdCfgSettings != NULL)); + + if ((prWfdCfgSettings->ucWfdEnable == 0) || (prWfdCfgSettings->u2WfdSessionInformationIELen == 0)) + break; + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (UINT_32) (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + prWfdSessionInfo = (P_WFD_SESSION_INFORMATION_IE_T) pucBuffer; + + prWfdSessionInfo->ucElemID = WFD_ATTRI_ID_SESSION_INFO; + + /* TODO: Check endian issue? */ + kalMemCopy(prWfdSessionInfo->pucWfdDevInfoDesc, prWfdCfgSettings->aucWfdSessionInformationIE, + prWfdCfgSettings->u2WfdSessionInformationIELen); + + WLAN_SET_FIELD_16(&prWfdSessionInfo->u2Length, prWfdCfgSettings->u2WfdSessionInformationIELen); + + u4AttriLen = prWfdCfgSettings->u2WfdSessionInformationIELen + WFD_ATTRI_HDR_LEN; + + } while (FALSE); + + (*pu2Offset) += (UINT_16) u4AttriLen; + + return u4AttriLen; +} + +/* wfdFuncAppendAttriSessionInfo */ + +#if CFG_SUPPORT_WFD_COMPOSE_IE +VOID +wfdFuncGenerateWfd_IE(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgIsAssocFrame, + IN PUINT_16 pu2Offset, + IN PUINT_8 pucBuf, + IN UINT_16 u2BufSize, + IN APPEND_VAR_ATTRI_ENTRY_T arAppendAttriTable[], IN UINT_32 u4AttriTableSize) +{ + + PUINT_8 pucBuffer = (PUINT_8) NULL; + P_IE_WFD_T prIeWFD = (P_IE_WFD_T) NULL; + UINT_32 u4OverallAttriLen; + UINT_32 u4AttriLen; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_8 aucTempBuffer[P2P_MAXIMUM_ATTRIBUTE_LEN]; + UINT_32 i; + + do { + ASSERT_BREAK((prAdapter != NULL) && (pucBuf != NULL)); + + pucBuffer = (PUINT_8) ((ULONG) pucBuf + (*pu2Offset)); + + ASSERT_BREAK(pucBuffer != NULL); + + /* Check buffer length is still enough. */ + ASSERT_BREAK((u2BufSize - (*pu2Offset)) >= WFD_IE_OUI_HDR); + + prIeWFD = (P_IE_WFD_T) pucBuffer; + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + (*pu2Offset) += WFD_IE_OUI_HDR; + + /* Overall length of all Attributes */ + u4OverallAttriLen = 0; + + for (i = 0; i < u4AttriTableSize; i++) { + + if (arAppendAttriTable[i].pfnAppendAttri) { + u4AttriLen = + arAppendAttriTable[i].pfnAppendAttri(prAdapter, fgIsAssocFrame, pu2Offset, pucBuf, + u2BufSize); + + u4OverallAttriLen += u4AttriLen; + + if (u4OverallAttriLen > P2P_MAXIMUM_ATTRIBUTE_LEN) { + u4OverallAttriLen -= P2P_MAXIMUM_ATTRIBUTE_LEN; + + prIeWFD->ucLength = (VENDOR_OUI_TYPE_LEN + P2P_MAXIMUM_ATTRIBUTE_LEN); + + pucBuffer = + (PUINT_8) ((ULONG) prIeWFD + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + prIeWFD = + (P_IE_WFD_T) ((ULONG) prIeWFD + + (WFD_IE_OUI_HDR + P2P_MAXIMUM_ATTRIBUTE_LEN)); + + kalMemCopy(aucTempBuffer, pucBuffer, u4OverallAttriLen); + + prIeWFD->ucId = ELEM_ID_WFD; + + prIeWFD->aucOui[0] = aucWfaOui[0]; + prIeWFD->aucOui[1] = aucWfaOui[1]; + prIeWFD->aucOui[2] = aucWfaOui[2]; + prIeWFD->ucOuiType = VENDOR_OUI_TYPE_WFD; + + kalMemCopy(prIeWFD->aucWFDAttributes, aucTempBuffer, u4OverallAttriLen); + (*pu2Offset) += WFD_IE_OUI_HDR; + } + + } + + } + + prIeWFD->ucLength = (UINT_8) (VENDOR_OUI_TYPE_LEN + u4OverallAttriLen); + + } while (FALSE); + +} /* wfdFuncGenerateWfd_IE */ + +#endif /* CFG_SUPPORT_WFD_COMPOSE_IE */ + +UINT_32 +wfdFuncCalculateWfdIELenForAssocRsp(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, IN P_STA_RECORD_T prStaRec) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + if (!IS_STA_P2P_TYPE(prStaRec) || (prWfdCfgSettings->ucWfdEnable == 0)) + return 0; + + return p2pFuncCalculateP2P_IELen(prAdapter, + eNetTypeIndex, + prStaRec, + txAssocRspWFDAttributesTable, + sizeof(txAssocRspWFDAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + +#else + return 0; +#endif +} /* wfdFuncCalculateWfdIELenForAssocRsp */ + +VOID wfdFuncGenerateWfdIEForAssocRsp(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + +#if CFG_SUPPORT_WFD_COMPOSE_IE + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_STA_RECORD_T prStaRec; + + do { + ASSERT_BREAK((prMsduInfo != NULL) && (prAdapter != NULL)); + + prWfdCfgSettings = &(prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + ASSERT(FALSE); + } else if (IS_STA_P2P_TYPE(prStaRec)) { + + if (prWfdCfgSettings->ucWfdEnable == 0) + break; + if ((prWfdCfgSettings->u4WfdFlag & WFD_FLAGS_DEV_INFO_VALID) == 0) + break; + + wfdFuncGenerateWfd_IE(prAdapter, + FALSE, + &prMsduInfo->u2FrameLength, + prMsduInfo->prPacket, + 1500, + txAssocRspWFDAttributesTable, + sizeof(txAssocRspWFDAttributesTable) / sizeof(APPEND_VAR_ATTRI_ENTRY_T)); + } + } while (FALSE); + + return; +#else + + return; +#endif +} /* wfdFuncGenerateWfdIEForAssocRsp */ + +VOID p2pFuncComposeNoaAttribute(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + + P_IE_P2P_T prIeP2P; + P_P2P_ATTRI_NOA_T prNoaAttr = NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + P_NOA_DESCRIPTOR_T prNoaDesc = NULL; + + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA_SPECIFIC; + UINT_32 u4AttributeLen; + UINT_32 u4NumOfNoaDesc = 0; + UINT_32 i = 0; + /*P2P IE format */ + prIeP2P = (P_IE_P2P_T) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + prIeP2P->ucId = ELEM_ID_P2P; + prIeP2P->aucOui[0] = aucWfaOui[0]; + prIeP2P->aucOui[1] = aucWfaOui[1]; + prIeP2P->aucOui[2] = aucWfaOui[2]; + prIeP2P->ucOuiType = VENDOR_OUI_TYPE_P2P; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + /*P2P Attribute--NoA */ + prNoaAttr = (P_P2P_ATTRI_NOA_T) prIeP2P->aucP2PAttributes; + + prNoaAttr->ucId = P2P_ATTRI_ID_NOTICE_OF_ABSENCE; + prNoaAttr->ucIndex = prP2pSpecificBssInfo->ucNoAIndex; + /*OPP*/ if (prP2pSpecificBssInfo->fgEnableOppPS) { + prNoaAttr->ucCTWOppPSParam = P2P_CTW_OPPPS_PARAM_OPPPS_FIELD | + (prP2pSpecificBssInfo->u2CTWindow & P2P_CTW_OPPPS_PARAM_CTWINDOW_MASK); + } else { + prNoaAttr->ucCTWOppPSParam = 0; + } + /*NoA Description */ + DBGLOG(P2P, INFO, "Compose NoA count=%d.\n", prP2pSpecificBssInfo->ucNoATimingCount); + for (i = 0; i < prP2pSpecificBssInfo->ucNoATimingCount; i++) { + if (prP2pSpecificBssInfo->arNoATiming[i].fgIsInUse) { + + prNoaDesc = (P_NOA_DESCRIPTOR_T) &prNoaAttr->aucNoADesc[u4NumOfNoaDesc]; + + prNoaDesc->ucCountType = prP2pSpecificBssInfo->arNoATiming[i].ucCount; + prNoaDesc->u4Duration = prP2pSpecificBssInfo->arNoATiming[i].u4Duration; + prNoaDesc->u4Interval = prP2pSpecificBssInfo->arNoATiming[i].u4Interval; + prNoaDesc->u4StartTime = prP2pSpecificBssInfo->arNoATiming[i].u4StartTime; + + u4NumOfNoaDesc++; + } + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + prNoaAttr->u2Length = 2 + u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T); + u4NumOfNoaDesc++; + + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + u4AttributeLen = P2P_ATTRI_HDR_LEN + prNoaAttr->u2Length; + + prIeP2P->ucLength = VENDOR_OUI_TYPE_LEN + u4AttributeLen; + prMsduInfo->u2FrameLength += (ELEM_HDR_LEN + prIeP2P->ucLength); + +} + +UINT_32 p2pFuncCalculateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN UINT_32 ucBssIdx, IN P_STA_RECORD_T prStaRec) +{ + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = NULL; + UINT_8 ucIdx; + UINT_32 u4NumOfNoaDesc = 0; + + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) + return 0; + + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + for (ucIdx = 0; ucIdx < prP2pSpecificBssInfo->ucNoATimingCount; ucIdx++) { + if (prP2pSpecificBssInfo->arNoATiming[ucIdx].fgIsInUse) + u4NumOfNoaDesc++; + } + + /* include "index" + "OppPs Params" + "NOA descriptors" */ + /* include "Attribute ID" + "Length" + "index" + "OppPs Params" + "NOA descriptors" */ + + return P2P_ATTRI_LEN_NOTICE_OF_ABSENCE + (u4NumOfNoaDesc * sizeof(NOA_DESCRIPTOR_T)); +} + +VOID p2pFuncGenerateP2P_IE_NoA(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + if (p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo)) { /* Hotspot */ + return; + } + + /* Compose NoA attribute */ + p2pFuncComposeNoaAttribute(prAdapter, + prMsduInfo /*prMsduInfo->ucBssIndex, prIeP2P->aucP2PAttributes, &u4AttributeLen */); + +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c new file mode 100644 index 0000000000000..f25df82d9ca76 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm.c @@ -0,0 +1,905 @@ +/* +** Id: @(#) p2p_rlm.c@@ +*/ + +/*! \file "p2p_rlm.c" + \brief + +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init AP Bss +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssInitForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ENUM_BAND_T eBand; + UINT_8 ucChannel; + ENUM_CHNL_EXT_T eSCO; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + /* Operation band, channel shall be ready before invoking this function. + * Bandwidth may be ready if other network is connected + */ + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + prBssInfo->eBssSCO = CHNL_EXT_SCN; + + if (RLM_AP_IS_BW_40_ALLOWED(prAdapter, prBssInfo)) { + /* In this case, the first BSS's SCO is 40MHz and known, so AP can + * apply 40MHz bandwidth, but the first BSS's SCO may be changed + * later if its Beacon lost timeout occurs + */ + if (cnmPreferredChannel(prAdapter, &eBand, &ucChannel, &eSCO) && + eSCO != CHNL_EXT_SCN && ucChannel == prBssInfo->ucPrimaryChannel && eBand == prBssInfo->eBand) { + prBssInfo->eBssSCO = eSCO; + } else if (cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex)) { + prBssInfo->eBssSCO = rlmDecideScoForAP(prAdapter, prBssInfo); + } + + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + prBssInfo->fg40mBwAllowed = TRUE; + prBssInfo->fgAssoc40mBwAllowed = TRUE; + + prBssInfo->ucHtOpInfo1 = (UINT_8) + (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); + + rlmUpdateBwByChListForAP(prAdapter, prBssInfo); + } + } + + DBGLOG(RLM, INFO, "WLAN AP SCO=%d\n", prBssInfo->eBssSCO); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateObssScanIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_IE_OBSS_SCAN_PARAM_T prObssScanIe; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11N(prBssInfo) && !RLM_NET_IS_BOW(prBssInfo) && + prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) && + prBssInfo->eBand == BAND_2G4 && prBssInfo->eBssSCO != CHNL_EXT_SCN) { + + prObssScanIe = (P_IE_OBSS_SCAN_PARAM_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add 20/40 BSS coexistence IE */ + prObssScanIe->ucId = ELEM_ID_OBSS_SCAN_PARAMS; + prObssScanIe->ucLength = sizeof(IE_OBSS_SCAN_PARAM_T) - ELEM_HDR_LEN; + + prObssScanIe->u2ScanPassiveDwell = dot11OBSSScanPassiveDwell; + prObssScanIe->u2ScanActiveDwell = dot11OBSSScanActiveDwell; + prObssScanIe->u2TriggerScanInterval = dot11BSSWidthTriggerScanInterval; + prObssScanIe->u2ScanPassiveTotalPerChnl = dot11OBSSScanPassiveTotalPerChannel; + prObssScanIe->u2ScanActiveTotalPerChnl = dot11OBSSScanActiveTotalPerChannel; + prObssScanIe->u2WidthTransDelayFactor = dot11BSSWidthChannelTransitionDelayFactor; + prObssScanIe->u2ScanActivityThres = dot11OBSSScanActivityThreshold; + + ASSERT(IE_SIZE(prObssScanIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_OBSS_SCAN)); + + prMsduInfo->u2FrameLength += IE_SIZE(prObssScanIe); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P GO. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmUpdateBwByChListForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + UINT_8 ucLevel; + BOOLEAN fgBwChange; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + fgBwChange = FALSE; + + if (prBssInfo->eBssSCO == CHNL_EXT_SCN) + return fgBwChange; + + ucLevel = rlmObssChnlLevel(prBssInfo, prBssInfo->eBand, prBssInfo->ucPrimaryChannel, prBssInfo->eBssSCO); + + if (ucLevel == CHNL_LEVEL0) { + /* Forced to 20MHz, so extended channel is SCN and STA width is zero */ + prBssInfo->fgObssActionForcedTo20M = TRUE; + + if (prBssInfo->ucHtOpInfo1 != (UINT_8) CHNL_EXT_SCN) { + prBssInfo->ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + fgBwChange = TRUE; + } + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, OBSS_20_40M_TIMEOUT * MSEC_PER_SEC); + } + + /* Clear up all channel lists */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + return fgBwChange; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessPublicAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_20_40_COEXIST_FRAME prRxFrame; + P_IE_20_40_COEXIST_T prCoexist; + P_IE_INTOLERANT_CHNL_REPORT_T prChnlReport; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + PUINT_8 pucIE; + UINT_16 u2IELength, u2Offset; + UINT_8 i, j; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_PUBLIC_20_40_COEXIST || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < (WLAN_MAC_MGMT_HEADER_LEN + 5) || + HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) != NETWORK_TYPE_P2P_INDEX) { + return; + } + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || + prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT || prBssInfo->eBssSCO == CHNL_EXT_SCN) { + return; + } + + prCoexist = &prRxFrame->rBssCoexist; + if (prCoexist->ucData & (BSS_COEXIST_40M_INTOLERANT | BSS_COEXIST_20M_REQ)) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == prBssInfo->ucPrimaryChannel) + break; + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_20mReqChnlList[i] = prBssInfo->ucPrimaryChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + + /* Process intolerant channel report IE */ + pucIE = (PUINT_8) &prRxFrame->rChnlReport; + u2IELength = prSwRfb->u2PacketLen - (WLAN_MAC_MGMT_HEADER_LEN + 5); + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_20_40_INTOLERANT_CHNL_REPORT: + prChnlReport = (P_IE_INTOLERANT_CHNL_REPORT_T) pucIE; + + if (prChnlReport->ucLength <= 1) + break; + + /* To do: process regulatory class. Now we assume 2.4G band */ + + for (j = 0; j < prChnlReport->ucLength - 1; j++) { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == prChnlReport->aucChannelList[j]) + break; + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = prChnlReport->aucChannelList[j]; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + } + break; + + default: + break; + } + } /* end of IE_FOR_EACH */ + + if (rlmUpdateBwByChListForAP(prAdapter, prBssInfo)) { + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); + rlmSyncOperationParams(prAdapter, prBssInfo); + } + + /* Check if OBSS scan exemption response should be sent */ + if (prCoexist->ucData & BSS_COEXIST_OBSS_SCAN_EXEMPTION_REQ) + rlmObssScanExemptionRsp(prAdapter, prBssInfo, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessHtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_NOTIFY_CHNL_WIDTH_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_ACTION_NOTIFY_CHNL_WIDTH_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prRxFrame->ucAction != ACTION_HT_NOTIFY_CHANNEL_WIDTH || + !prStaRec || prStaRec->ucStaState != STA_STATE_3 || + prSwRfb->u2PacketLen < sizeof(ACTION_NOTIFY_CHNL_WIDTH_FRAME)) { + return; + } + + /* To do: depending regulation class 13 and 14 based on spec + * Note: (ucChannelWidth==1) shall restored back to original capability, + * not current setting to 40MHz BW here + */ + if (prRxFrame->ucChannelWidth == 0) + prStaRec->u2HtCapInfo &= ~HT_CAP_INFO_SUP_CHNL_WIDTH; + else if (prRxFrame->ucChannelWidth == 1) + prStaRec->u2HtCapInfo |= HT_CAP_INFO_SUP_CHNL_WIDTH; + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmHandleObssStatusEventPkt(P_ADAPTER_T prAdapter, P_EVENT_AP_OBSS_STATUS_T prObssStatus) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prObssStatus); + ASSERT(prObssStatus->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prObssStatus->ucNetTypeIndex]; + ASSERT(prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT); + + prBssInfo->fgObssErpProtectMode = (BOOLEAN) prObssStatus->ucObssErpProtectMode; + prBssInfo->eObssHtProtectMode = (ENUM_HT_PROTECT_MODE_T) prObssStatus->ucObssHtProtectMode; + prBssInfo->eObssGfOperationMode = (ENUM_GF_MODE_T) prObssStatus->ucObssGfOperationMode; + prBssInfo->fgObssRifsOperationMode = (BOOLEAN) prObssStatus->ucObssRifsOperationMode; + prBssInfo->fgObssBeaconForcedTo20M = (BOOLEAN) prObssStatus->ucObssBeaconForcedTo20M; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, TRUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is only for AP mode in NETWORK_TYPE_P2P_INDEX. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmUpdateParamsForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, BOOLEAN fgUpdateBeacon) +{ + P_LINK_T prStaList; + P_STA_RECORD_T prStaRec; + BOOLEAN fgErpProtectMode, fgSta40mIntolerant; + BOOLEAN fgUseShortPreamble, fgUseShortSlotTime; + ENUM_HT_PROTECT_MODE_T eHtProtectMode; + ENUM_GF_MODE_T eGfOperationMode; + UINT_8 ucHtOpInfo1; +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + P_GLUE_INFO_T prGlueInfo; +#endif + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + if (!IS_BSS_ACTIVE(prBssInfo) || prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT) + return; + + fgErpProtectMode = FALSE; + eHtProtectMode = HT_PROTECT_MODE_NONE; + eGfOperationMode = GF_MODE_NORMAL; + fgSta40mIntolerant = FALSE; + fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + fgUseShortSlotTime = TRUE; + ucHtOpInfo1 = (UINT_8) CHNL_EXT_SCN; + + prStaList = &prBssInfo->rStaRecOfClientList; + + LINK_FOR_EACH_ENTRY(prStaRec, prStaList, rLinkEntry, STA_RECORD_T) { + /* ASSERT(prStaRec); */ + if (!prStaRec) { + DBGLOG(P2P, TRACE, "prStaRec is NULL in rlmUpdateParamsForAP()\n"); + break; + } + if (prStaRec->fgIsInUse && prStaRec->ucStaState == STA_STATE_3 && + prStaRec->ucNetTypeIndex == prBssInfo->ucNetTypeIndex) { + if (!(prStaRec->ucPhyTypeSet & (PHY_TYPE_SET_802_11GN | PHY_TYPE_SET_802_11A))) { + /* B-only mode, so mode 1 (ERP protection) */ + fgErpProtectMode = TRUE; + } + + if (!(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* BG-only or A-only */ + eHtProtectMode = HT_PROTECT_MODE_NON_HT; + } else if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) { + /* 20MHz-only */ + /* + The HT Protection field may be set to 20 MHz protection + mode only if the following are true: + \A1X All STAs detected (by any means) in the primary channel + and all STAs detected (by any means) in the secondary + channel are HT STAs and all STAs that are members of + this BSS are HT STAs, and + \A1X This BSS is a 20/40 MHz BSS, and + \A1X There is at least one 20 MHz HT STA associated with this BSS. + */ + if (eHtProtectMode == HT_PROTECT_MODE_NONE && prBssInfo->fgAssoc40mBwAllowed) + eHtProtectMode = HT_PROTECT_MODE_20M; + } + + if (!(prStaRec->u2HtCapInfo & HT_CAP_INFO_HT_GF)) + eGfOperationMode = GF_MODE_PROTECT; + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)) + fgUseShortPreamble = FALSE; + + if (!(prStaRec->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME)) + fgUseShortSlotTime = FALSE; + + if (prStaRec->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fgSta40mIntolerant = TRUE; + } + } /* end of LINK_FOR_EACH_ENTRY */ + + /* Check if HT operation IE about 20/40M bandwidth shall be updated */ + if (prBssInfo->eBssSCO != CHNL_EXT_SCN) { + if (/*!LINK_IS_EMPTY(prStaList) && */ !fgSta40mIntolerant && + !prBssInfo->fgObssActionForcedTo20M && !prBssInfo->fgObssBeaconForcedTo20M) { + + ucHtOpInfo1 = (UINT_8) + (((UINT_32) prBssInfo->eBssSCO) | HT_OP_INFO1_STA_CHNL_WIDTH); + } + } +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + prGlueInfo = prAdapter->prGlueInfo; + if (prGlueInfo->prP2PInfo->u4PsLevel & BITS(8, 15)) + fgErpProtectMode = TRUE; +#endif + + /* Check if any new parameter may be updated */ + if (prBssInfo->fgErpProtectMode != fgErpProtectMode || + prBssInfo->eHtProtectMode != eHtProtectMode || + prBssInfo->eGfOperationMode != eGfOperationMode || + prBssInfo->ucHtOpInfo1 != ucHtOpInfo1 || + prBssInfo->fgUseShortPreamble != fgUseShortPreamble || + prBssInfo->fgUseShortSlotTime != fgUseShortSlotTime) { + + prBssInfo->fgErpProtectMode = fgErpProtectMode; + prBssInfo->eHtProtectMode = eHtProtectMode; + prBssInfo->eGfOperationMode = eGfOperationMode; + prBssInfo->ucHtOpInfo1 = ucHtOpInfo1; + prBssInfo->fgUseShortPreamble = fgUseShortPreamble; + prBssInfo->fgUseShortSlotTime = fgUseShortSlotTime; + + if (fgUseShortSlotTime) + prBssInfo->u2CapInfo |= CAP_INFO_SHORT_SLOT_TIME; + else + prBssInfo->u2CapInfo &= ~CAP_INFO_SHORT_SLOT_TIME; + + rlmSyncOperationParams(prAdapter, prBssInfo); + fgUpdateBeacon = TRUE; + } + + /* Update Beacon content if related IE content is changed */ + if (fgUpdateBeacon) + bssUpdateBeaconContent(prAdapter, prBssInfo->ucNetTypeIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initial the channel list from the domain information. +* This function is called after P2P initial and Domain information changed. +* Make sure the device is disconnected while changing domain information. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFuncInitialChannelList(IN P_ADAPTER_T prAdapter) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_DOMAIN_INFO_ENTRY prDomainInfoEntry = (P_DOMAIN_INFO_ENTRY) NULL; + P_DOMAIN_SUBBAND_INFO prDomainSubBand = (P_DOMAIN_SUBBAND_INFO) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0, u4IdxII = 0; + UINT_8 ucBufferSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE; +#if 0 + UINT_8 ucSocialChnlSupport = 0, ucAutoChnl = 0; +#endif + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; +#if 0 + ucAutoChnl = prP2pConnSetting->ucOperatingChnl; +#endif + + prDomainInfoEntry = rlmDomainGetDomainInfo(prAdapter); + + ASSERT_BREAK((prDomainInfoEntry != NULL) && (prP2pConnSetting != NULL)); + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + for (u4Idx = 0; u4Idx < MAX_SUBBAND_NUM; u4Idx++) { + prDomainSubBand = &prDomainInfoEntry->rSubBand[u4Idx]; + + if (((prDomainSubBand->ucBand == BAND_5G) && (!prAdapter->fgEnable5GBand)) || + (prDomainSubBand->ucBand == BAND_NULL)) { + continue; + } + + if (ucBufferSize < (P2P_ATTRI_LEN_CHANNEL_ENTRY + prDomainSubBand->ucNumChannels)) { + /* Buffer is not enough to include all supported channels. */ + break; /* for */ + } + + prChannelEntryField->ucRegulatoryClass = prDomainSubBand->ucRegClass; + prChannelEntryField->ucNumberOfChannels = prDomainSubBand->ucNumChannels; + + for (u4IdxII = 0; u4IdxII < prDomainSubBand->ucNumChannels; u4IdxII++) { + prChannelEntryField->aucChannelList[u4IdxII] = prDomainSubBand->ucFirstChannelNum + + (u4IdxII * prDomainSubBand->ucChannelSpan); + +#if 0 + switch (prChannelEntryField->aucChannelList[u4IdxII]) { + case 1: + ucSocialChnlSupport = 1; + break; + case 6: + ucSocialChnlSupport = 6; + break; + case 11: + ucSocialChnlSupport = 11; + break; + default: + break; + } + +#endif + } + + if (ucBufferSize >= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels)) + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + else + break; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) + prChannelEntryField->ucNumberOfChannels); + + } + +#if 0 + if (prP2pConnSetting->ucListenChnl == 0) { + prP2pConnSetting->ucListenChnl = P2P_DEFAULT_LISTEN_CHANNEL; + + if (ucSocialChnlSupport != 0) { + /* 1. User Not Set LISTEN channel. + * 2. Social channel is not empty. + */ + prP2pConnSetting->ucListenChnl = ucSocialChnlSupport; + } + } +#endif + + /* TODO: 20110921 frog - */ + /* If LISTEN channel is not set, + * a random supported channel would be set. + * If no social channel is supported, DEFAULT channel would be set. + */ + + prP2pConnSetting->ucRfChannelListSize = P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE - ucBufferSize; + +#if 0 + if (prP2pConnSetting->ucOperatingChnl == 0) { /* User not set OPERATE channel. */ + + if (scnQuerySparseChannel(prAdapter, NULL, &ucAutoChnl)) + break; /* while */ + + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + if (prChannelEntryField->ucNumberOfChannels != 0) { + ucAutoChnl = prChannelEntryField->aucChannelList[0]; + break; /* while */ + } + + else { + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((UINT_32) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (UINT_32)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= + (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + } + + } + + } +#endif + /* We assume user would not set a channel not in the channel list. + * If so, the operating channel still depends on target device supporting capability. + */ + + /* TODO: 20110921 frog - */ + /* If the Operating channel is not set, a channel from supported channel list is set automatically. + * If there is no supported channel in channel list, a DEFAULT channel is set. + */ + + } while (FALSE); + +#if 0 + prP2pConnSetting->ucOperatingChnl = ucAutoChnl; +#endif + +} /* rlmFuncInitialChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find a common channel list from the local channel list info & target channel list info. +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return boolean value if probe response frame is +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmFuncCommonChannelList(IN P_ADAPTER_T prAdapter, + IN P_CHANNEL_ENTRY_FIELD_T prChannelEntryII, IN UINT_8 ucChannelListSize) +{ + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) NULL, prChannelEntryIII = + (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_8 aucCommonChannelList[P2P_MAX_SUPPORTED_CHANNEL_LIST_SIZE] = {0}; + UINT_8 ucOriChnlSize = 0, ucNewChnlSize = 0; + + do { + + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) aucCommonChannelList; + + while (ucChannelListSize > 0) { + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + ucOriChnlSize = prP2pConnSetting->ucRfChannelListSize; + + while (ucOriChnlSize > 0) { + if (prChannelEntryI->ucRegulatoryClass == prChannelEntryII->ucRegulatoryClass) { + prChannelEntryIII->ucRegulatoryClass = prChannelEntryI->ucRegulatoryClass; + /* TODO: Currently we assume that the regulatory class the same, + * the channels are the same. */ + kalMemCopy(prChannelEntryIII->aucChannelList, prChannelEntryII->aucChannelList, + prChannelEntryII->ucNumberOfChannels); + prChannelEntryIII->ucNumberOfChannels = prChannelEntryII->ucNumberOfChannels; + + ucNewChnlSize += + P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryIII->ucNumberOfChannels; + + prChannelEntryIII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryIII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG)prChannelEntryIII->ucNumberOfChannels); + } + + ucOriChnlSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryI->ucNumberOfChannels); + + prChannelEntryI = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryI + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) + prChannelEntryI->ucNumberOfChannels); + + } + + ucChannelListSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryII->ucNumberOfChannels); + + prChannelEntryII = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryII + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntryII->ucNumberOfChannels); + + } + + kalMemCopy(prP2pConnSetting->aucChannelEntriesField, aucCommonChannelList, ucNewChnlSize); + prP2pConnSetting->ucRfChannelListSize = ucNewChnlSize; + + } while (FALSE); + +} /* rlmFuncCommonChannelList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmFuncFindOperatingClass(IN P_ADAPTER_T prAdapter, IN UINT_8 ucChannelNum) +{ + UINT_8 ucRegulatoryClass = 0, ucBufferSize = 0; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_CHANNEL_ENTRY_FIELD_T prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) NULL; + UINT_32 u4Idx = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while (ucBufferSize != 0) { + + for (u4Idx = 0; u4Idx < prChannelEntryField->ucNumberOfChannels; u4Idx++) { + if (prChannelEntryField->aucChannelList[u4Idx] == ucChannelNum) { + ucRegulatoryClass = prChannelEntryField->ucRegulatoryClass; + break; + } + + } + + if (ucRegulatoryClass != 0) + break; /* while */ + + prChannelEntryField = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntryField + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG)prChannelEntryField->ucNumberOfChannels); + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntryField->ucNumberOfChannels); + + } + + } while (FALSE); + + return ucRegulatoryClass; +} /* rlmFuncFindOperatingClass */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmFuncFindAvailableChannel(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucCheckChnl, + IN PUINT_8 pucSuggestChannel, IN BOOLEAN fgIsSocialChannel, IN BOOLEAN fgIsDefaultChannel) +{ + BOOLEAN fgIsResultAvailable = FALSE; + P_CHANNEL_ENTRY_FIELD_T prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSetting = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_8 ucBufferSize = 0, ucIdx = 0, ucChannelSelected = 0; + + do { + ASSERT_BREAK(prAdapter != NULL); + + if (fgIsDefaultChannel) + ucChannelSelected = P2P_DEFAULT_LISTEN_CHANNEL; + + prP2pConnSetting = prAdapter->rWifiVar.prP2PConnSettings; + ucBufferSize = prP2pConnSetting->ucRfChannelListSize; + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) prP2pConnSetting->aucChannelEntriesField; + + while ((ucBufferSize != 0) && (!fgIsResultAvailable)) { + + for (ucIdx = 0; ucIdx < prChannelEntry->ucNumberOfChannels; ucIdx++) { + if ((!fgIsSocialChannel) || + (prChannelEntry->aucChannelList[ucIdx] == 1) || + (prChannelEntry->aucChannelList[ucIdx] == 6) || + (prChannelEntry->aucChannelList[ucIdx] == 11)) { + + if (prChannelEntry->aucChannelList[ucIdx] <= 11) { + /* 2.4G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } else if ((prChannelEntry->aucChannelList[ucIdx] < 52) && + (prChannelEntry->aucChannelList[ucIdx] > 14)) { + /* 2.4G + 5G. */ + ucChannelSelected = prChannelEntry->aucChannelList[ucIdx]; + } + + if (ucChannelSelected == ucCheckChnl) { + fgIsResultAvailable = TRUE; + break; + } + } + + } + + ucBufferSize -= (P2P_ATTRI_LEN_CHANNEL_ENTRY + prChannelEntry->ucNumberOfChannels); + + prChannelEntry = (P_CHANNEL_ENTRY_FIELD_T) ((ULONG) prChannelEntry + + P2P_ATTRI_LEN_CHANNEL_ENTRY + + (ULONG) prChannelEntry->ucNumberOfChannels); + + } + + if ((!fgIsResultAvailable) && (pucSuggestChannel != NULL)) { + DBGLOG(P2P, TRACE, + "The request channel %d is not available, sugguested channel:%d\n", ucCheckChnl, + ucChannelSelected); + /* Given a suggested channel. */ + *pucSuggestChannel = ucChannelSelected; + } + + } while (FALSE); + + return fgIsResultAvailable; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +ENUM_CHNL_EXT_T rlmDecideScoForAP(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + UINT_8 ucSecondChannel, i, j; + ENUM_CHNL_EXT_T eSCO; + + eSCO = CHNL_EXT_SCN; + + if (prBssInfo->eBand == BAND_2G4) { + if (prBssInfo->ucPrimaryChannel != 14) + eSCO = (prBssInfo->ucPrimaryChannel > 7) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + } else { + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + if (prSubband->ucBand == prBssInfo->eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == prBssInfo->ucPrimaryChannel) { + eSCO = (j & 1) ? CHNL_EXT_SCB : CHNL_EXT_SCA; + break; + } + } + + if (j < prSubband->ucNumChannels) + break; /* Found */ + } + } + } + + /* Check if it is boundary channel and 40MHz BW is permitted */ + if (eSCO != CHNL_EXT_SCN) { + ucSecondChannel = (eSCO == CHNL_EXT_SCA) ? + (prBssInfo->ucPrimaryChannel + 4) : (prBssInfo->ucPrimaryChannel - 4); + + if (!rlmDomainIsLegalChannel(prAdapter, prBssInfo->eBand, ucSecondChannel)) + eSCO = CHNL_EXT_SCN; + } + + return eSCO; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c new file mode 100644 index 0000000000000..154f1e5db0f73 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_rlm_obss.c @@ -0,0 +1,313 @@ +/* +** Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_cfg80211.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + using cfg80211 interface + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#include "precomp.h" + +static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Different concurrent network has itself channel lists, and +* concurrent networks should have been recorded in channel lists. +* If role of active P2P is GO, assume associated AP of AIS will +* record our Beacon for P2P GO because of same channel. +* +* Note: If we have scenario of different channel in the future, +* the internal FW communication channel shall be established. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmObssChnlLevel(P_BSS_INFO_T prBssInfo, ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 ucChannelLevel; + + ASSERT(prBssInfo); + + if (eBand == BAND_2G4) { + ucChannelLevel = rlmObssChnlLevelIn2G4(prBssInfo, ucPriChannel, eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } else if (eBand == BAND_5G) { + ucChannelLevel = rlmObssChnlLevelIn5G(prBssInfo, ucPriChannel, eExtend); + + /* (TBD) If concurrent networks permit different channel, extra + * channel judgement should be added. Please refer to + * previous version of this file. + */ + } else { + ucChannelLevel = CHNL_LEVEL0; + } + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmObssChnlLevelIn2G4(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel, ucCenterChannel; + UINT_8 ucAffectedChnl_L, ucAffectedChnl_H; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) { + ucCenterChannel = ucPriChannel + 2; + ucSecChannel = ucPriChannel + 4; + } else if (eExtend == CHNL_EXT_SCB) { + ucCenterChannel = ucPriChannel - 2; + ucSecChannel = ucPriChannel - 4; + } else { + return CHNL_LEVEL0; + } + ASSERT(ucCenterChannel >= 1 && ucCenterChannel <= 14); + + /* Calculated low/upper channels in affected freq range */ + ucAffectedChnl_L = (ucCenterChannel <= AFFECTED_CHNL_OFFSET) ? 1 : (ucCenterChannel - AFFECTED_CHNL_OFFSET); + + ucAffectedChnl_H = (ucCenterChannel >= (14 - AFFECTED_CHNL_OFFSET)) ? + 14 : (ucCenterChannel + AFFECTED_CHNL_OFFSET); + + /* Check intolerant (Non-HT) channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_NonHtChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_NonHtChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_NonHtChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 20M BW request channel list */ + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_20mReqChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_20mReqChnlList[i] <= ucAffectedChnl_H)) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G primary channel list */ + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_PriChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_PriChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_PriChnlList[i] != ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + + /* Check 2.4G secondary channel list */ + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if ((prBssInfo->auc2G_SecChnlList[i] >= ucAffectedChnl_L && + prBssInfo->auc2G_SecChnlList[i] <= ucAffectedChnl_H) && + prBssInfo->auc2G_SecChnlList[i] != ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_2G4_level_end; + } + } + +L_2G4_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmObssChnlLevelIn5G(P_BSS_INFO_T prBssInfo, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 i, ucChannelLevel; + UINT_8 ucSecChannel; + + ASSERT(prBssInfo); + + ucChannelLevel = CHNL_LEVEL2; + + /* Calculate center channel for 2.4G band */ + if (eExtend == CHNL_EXT_SCA) + ucSecChannel = ucPriChannel + 4; + else if (eExtend == CHNL_EXT_SCB) + ucSecChannel = ucPriChannel - 4; + else + return CHNL_LEVEL0; + ASSERT(ucSecChannel >= 36); + + /* Check 5G primary channel list */ + ASSERT(prBssInfo->auc5G_PriChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_PriChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_PriChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } else if (prBssInfo->auc5G_PriChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check non-HT channel list */ + ASSERT(prBssInfo->auc5G_NonHtChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_NonHtChnlList[i] == ucSecChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } else if (prBssInfo->auc5G_NonHtChnlList[i] == ucPriChannel) { + ucChannelLevel = CHNL_LEVEL1; + } + } + + /* Check secondary channel list */ + ASSERT(prBssInfo->auc5G_SecChnlList[0] <= CHNL_LIST_SZ_5G); + for (i = 1; i <= prBssInfo->auc5G_SecChnlList[0] && i <= CHNL_LIST_SZ_5G; i++) { + if (prBssInfo->auc5G_SecChnlList[i] == ucPriChannel) { + + ucChannelLevel = CHNL_LEVEL0; + goto L_5G_level_end; + } + } + +L_5G_level_end: + + return ucChannelLevel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssScanExemptionRsp(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb) +{ + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + + /* To do: need an algorithm to do judgement. Now always reject request */ + + prMsduInfo = (P_MSDU_INFO_T)cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfo == NULL) + return; + + DBGLOG(RLM, INFO, "Send 20/40 coexistence rsp frame!\n"); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) prMsduInfo->prPacket; + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, ((P_ACTION_20_40_COEXIST_FRAME) prSwRfb->pvHeader)->aucSrcAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = 0; + + ASSERT((WLAN_MAC_HEADER_LEN + 5) <= PUBLIC_ACTION_MAX_LEN); + + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfo->ucStaRecIndex = prSwRfb->ucStaRecIdx; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_HTC_LEN + 5; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c new file mode 100644 index 0000000000000..b5bd23965fe35 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_scan.c @@ -0,0 +1,756 @@ +/* +** Id: @(#) p2p_scan.c@@ +*/ + +/*! \file "p2p_scan.c" + \brief This file defines the p2p scan profile and the processing function of + scan result for SCAN Module. + + The SCAN Profile selection is part of SCAN MODULE and responsible for defining + SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. + In this file we also define the process of SCAN Result including adding, searching + and removing SCAN record from the list. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +P_P2P_DEVICE_DESC_T +scanSearchTargetP2pDesc(IN P_ADAPTER_T prAdapter, IN UINT_8 aucDeviceID[], IN PP_BSS_DESC_T pprBssDesc) +{ + + P_P2P_DEVICE_DESC_T prTargetP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T) NULL; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucDeviceID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* Loop for each prBssDesc */ + prTargetP2pDesc = scanFindP2pDeviceDesc(prAdapter, prBssDesc, aucDeviceID, TRUE, FALSE); + + if (prTargetP2pDesc != NULL) + break; + } + + if ((pprBssDesc) && (prTargetP2pDesc != NULL)) { + /* Only valid if prTargetP2pDesc is not NULL. */ + *pprBssDesc = prBssDesc; + } + + return prTargetP2pDesc; +} /* scanSearchTargetP2pDesc */ + +VOID scanInvalidAllP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (prTargetDesc->fgDevInfoValid) + prTargetDesc->fgDevInfoValid = FALSE; + } + +} /* scanRenewP2pClientDevice */ + +VOID scanRemoveInvalidP2pClientDevice(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL, prNexEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + LINK_FOR_EACH_SAFE(prLinkEntry, prNexEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (!prTargetDesc->fgDevInfoValid) { + LINK_REMOVE_KNOWN_ENTRY(&prBssDesc->rP2pDeviceList, prLinkEntry); + if ((prP2pConnSettings) && (prP2pConnSettings->prTargetP2pDesc == prTargetDesc)) + prP2pConnSettings->prTargetP2pDesc = NULL; + kalMemFree(prTargetDesc, VIR_MEM_TYPE, sizeof(P2P_DEVICE_DESC_T)); + } + } + +} /* scanRenewP2pClientDevice */ + +P_P2P_DEVICE_DESC_T +scanFindP2pDeviceDesc(IN P_ADAPTER_T prAdapter, + IN P_BSS_DESC_T prBssDesc, + IN UINT_8 aucMacAddr[], IN BOOLEAN fgIsDeviceAddr, IN BOOLEAN fgAddIfNoFound) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prBssDesc != NULL) && (aucMacAddr != NULL)); + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + if (fgIsDeviceAddr) { + if (EQUAL_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr)) + break; + } else { + if (EQUAL_MAC_ADDR(prTargetDesc->aucInterfaceAddr, aucMacAddr)) + break; + } + + prTargetDesc = NULL; + } + + if ((fgAddIfNoFound) && (prTargetDesc == NULL)) { + /* Target Not Found. */ + /* TODO: Use memory pool in the future. */ + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, aucMacAddr); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + } else { + ASSERT(FALSE); + } + } + + } while (FALSE); + + return prTargetDesc; +} /* scanFindP2pDeviceDesc */ + +P_P2P_DEVICE_DESC_T scanGetP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(prBssDesc); + + if (prBssDesc->prP2pDesc == NULL) { + + prTargetDesc = kalMemAlloc(sizeof(P2P_DEVICE_DESC_T), VIR_MEM_TYPE); + + if (prTargetDesc) { + kalMemZero(prTargetDesc, sizeof(P2P_DEVICE_DESC_T)); + LINK_ENTRY_INITIALIZE(&(prTargetDesc->rLinkEntry)); + LINK_INSERT_TAIL(&prBssDesc->rP2pDeviceList, &prTargetDesc->rLinkEntry); + prTargetDesc->fgDevInfoValid = TRUE; + prBssDesc->prP2pDesc = prTargetDesc; + /* We are not sure the SrcAddr is Device Address or Interface Address. */ + COPY_MAC_ADDR(prTargetDesc->aucDeviceAddr, prBssDesc->aucSrcAddr); + COPY_MAC_ADDR(prTargetDesc->aucInterfaceAddr, prBssDesc->aucSrcAddr); + } else { + + ASSERT(FALSE); + } + } else { + prTargetDesc = prBssDesc->prP2pDesc; + } + + return prTargetDesc; + +} /* scanFindP2pDeviceDesc */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scanUpdateP2pDeviceDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_P2P_DEVICE_DESC_T prP2pDesc = (P_P2P_DEVICE_DESC_T) NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + BOOLEAN fgUpdateDevInfo = FALSE; + + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; + + ASSERT(prAdapter); + + prP2pDesc = scanGetP2pDeviceDesc(prAdapter, prBssDesc); + + if (!prP2pDesc) { + ASSERT(FALSE); + return fgUpdateDevInfo; + } + + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, + &u2AttributeLen); + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: /* Beacon, Probe Response */ + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + + prP2pDesc->ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + prP2pDesc->ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: /* Beacon */ + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == P2P_ATTRI_MAX_LEN_P2P_DEV_ID); + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: /* Probe Response */ + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + UINT_16 u2NameLen = 0, u2Id = 0; + + fgUpdateDevInfo = TRUE; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; + + kalMemCopy(prP2pDesc->aucDeviceAddr, prP2pAttriDevInfo->aucDevAddr, MAC_ADDR_LEN); + + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &prP2pDesc->rPriDevType; + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= + P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); + /* TODO: Fixme if secondary device type is more than 2. */ + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> + arSecondaryDevTypeListBE[u4Idx].u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prP2pAttriDevInfo-> + arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = + (P_DEVICE_NAME_TLV_T) ((PUINT_8) prP2pAttriDevInfo->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &u2NameLen); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Id, &u2Id); + ASSERT(u2Id == WPS_ATTRI_ID_DEVICE_NAME); + if (u2NameLen > WPS_ATTRI_MAX_LEN_DEVICE_NAME) + u2NameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + prP2pDesc->u2NameLength = u2NameLen; + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: /* Probe Response */ + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; + break; + case P2P_ATTRI_ID_NOTICE_OF_ABSENCE: + break; + case P2P_ATTRI_ID_EXT_LISTEN_TIMING: + /* TODO: Not implement yet. */ + /* ASSERT(FALSE); */ + break; + default: + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = + (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + scanInvalidAllP2pClientDevice(prAdapter, prBssDesc); + + /* GO/Device itself. */ + prP2pDesc->fgDevInfoValid = TRUE; + + prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + while (u2AttributeLen > 0) { + prP2pDesc = + scanFindP2pDeviceDesc(prAdapter, prBssDesc, prClientInfoDesc->aucDevAddr, TRUE, TRUE); + + if (!prP2pDesc) { + ASSERT(FALSE); + break; /* while */ + } + + prP2pDesc->fgDevInfoValid = TRUE; + + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + if (u2AttributeLen < 25) { + DBGLOG(P2P, WARN, "Length incorrect warning.\n"); + break; + } + COPY_MAC_ADDR(prP2pDesc->aucInterfaceAddr, prClientInfoDesc->aucIfAddr); + + prP2pDesc->ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + + WLAN_GET_FIELD_BE16(&prClientInfoDesc->u2ConfigMethodsBE, &prP2pDesc->u2ConfigMethod); + + prP2pDevType = &(prP2pDesc->rPriDevType); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT); + prP2pDesc->ucSecDevTypeNum = 0; + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + if (u4Idx < P2P_GC_MAX_CACHED_SEC_DEV_TYPE_COUNT) { + prP2pDevType = &(prP2pDesc->arSecDevType[u4Idx]); + WLAN_GET_FIELD_BE16(&prClientInfoDesc-> + arSecondaryDevTypeListBE[u4Idx].u2CategoryId, + &prP2pDevType->u2CategoryID); + WLAN_GET_FIELD_BE16(&prClientInfoDesc-> + arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId, + &prP2pDevType->u2SubCategoryID); + prP2pDesc->ucSecDevTypeNum++; + } + + } + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + WLAN_GET_FIELD_BE16(&prP2pDevName->u2Length, &prP2pDesc->u2NameLength); + if (prP2pDesc->u2NameLength > WPS_ATTRI_MAX_LEN_DEVICE_NAME) + prP2pDesc->u2NameLength = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + + kalMemCopy(prP2pDesc->aucName, prP2pDevName->aucName, prP2pDesc->u2NameLength); + + u2AttributeLen -= (prClientInfoDesc->ucLength + P2P_CLIENT_INFO_DESC_HDR_LEN); + prClientInfoDesc = + (P_P2P_CLIENT_INFO_DESC_T) ((UINT_32) prClientInfoDesc + + (UINT_32) prClientInfoDesc->ucLength + + P2P_CLIENT_INFO_DESC_HDR_LEN); + } + + scanRemoveInvalidP2pClientDevice(prAdapter, prBssDesc); + } + + return fgUpdateDevInfo; +} /* end of scanAddP2pDeviceInfo() */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to Event Packet +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS scanSendDeviceDiscoverEvent(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) +{ + EVENT_P2P_DEV_DISCOVER_RESULT_T rEventDevInfo; +#if 1 + P_LINK_ENTRY_T prLinkEntry = (P_LINK_ENTRY_T) NULL; + P_P2P_DEVICE_DESC_T prTargetDesc = (P_P2P_DEVICE_DESC_T) NULL; + + LINK_FOR_EACH(prLinkEntry, &prBssDesc->rP2pDeviceList) { + prTargetDesc = LINK_ENTRY(prLinkEntry, P2P_DEVICE_DESC_T, rLinkEntry); + + COPY_MAC_ADDR(rEventDevInfo.aucDeviceAddr, prTargetDesc->aucDeviceAddr); + COPY_MAC_ADDR(rEventDevInfo.aucInterfaceAddr, prTargetDesc->aucInterfaceAddr); + + rEventDevInfo.ucDeviceCapabilityBitmap = prTargetDesc->ucDeviceCapabilityBitmap; + rEventDevInfo.ucGroupCapabilityBitmap = prTargetDesc->ucGroupCapabilityBitmap; + rEventDevInfo.u2ConfigMethod = prTargetDesc->u2ConfigMethod; + + kalMemCopy(&rEventDevInfo.rPriDevType, &prTargetDesc->rPriDevType, sizeof(P2P_DEVICE_TYPE_T)); + + kalMemCopy(rEventDevInfo.arSecDevType, + prTargetDesc->arSecDevType, (prTargetDesc->ucSecDevTypeNum * sizeof(P2P_DEVICE_TYPE_T))); + + rEventDevInfo.ucSecDevTypeNum = prTargetDesc->ucSecDevTypeNum; + + rEventDevInfo.u2NameLength = prTargetDesc->u2NameLength; + kalMemCopy(rEventDevInfo.aucName, prTargetDesc->aucName, prTargetDesc->u2NameLength); + + COPY_MAC_ADDR(rEventDevInfo.aucBSSID, prBssDesc->aucBSSID); + + if (prTargetDesc == prBssDesc->prP2pDesc) + nicRxAddP2pDevice(prAdapter, &rEventDevInfo, prBssDesc->aucIEBuf, prBssDesc->u2IELength); + else + nicRxAddP2pDevice(prAdapter, &rEventDevInfo, NULL, 0); + } + + kalP2PIndicateFound(prAdapter->prGlueInfo); + +#else + + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_ATTRIBUTE_T prP2pAttribute = (P_P2P_ATTRIBUTE_T) NULL; + UINT_16 u2AttributeLen = 0; + UINT_32 u4Idx = 0; + P_P2P_ATTRI_GROUP_INFO_T prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) NULL; + P_DEVICE_NAME_TLV_T prP2pDevName = (P_DEVICE_NAME_TLV_T) NULL; + + ASSERT(prAdapter); + + prP2pSpecificBssInfo = &prAdapter->rWifiVar.rP2pSpecificBssInfo; + +#if 1 + p2pGetP2PAttriList(prAdapter, prBssDesc->aucIEBuf, prBssDesc->u2IELength, (PPUINT_8) & prP2pAttribute, + &u2AttributeLen); +#else + prP2pAttribute = (P_P2P_ATTRIBUTE_T) &prP2pSpecificBssInfo->aucAttributesCache[0]; + u2AttributeLen = prP2pSpecificBssInfo->u2AttributeLen; +#endif + rEventDevInfo.fgDevInfoValid = FALSE; + + while (u2AttributeLen >= P2P_ATTRI_HDR_LEN) { + switch (prP2pAttribute->ucId) { + case P2P_ATTRI_ID_P2P_CAPABILITY: + { + P_P2P_ATTRI_CAPABILITY_T prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) NULL; + + prP2pAttriCapability = (P_P2P_ATTRI_CAPABILITY_T) prP2pAttribute; + ASSERT(prP2pAttriCapability->u2Length == 2); + rEventDevInfo.ucDeviceCapabilityBitmap = prP2pAttriCapability->ucDeviceCap; + rEventDevInfo.ucGroupCapabilityBitmap = prP2pAttriCapability->ucGroupCap; + } + break; + case P2P_ATTRI_ID_P2P_DEV_ID: + { + P_P2P_ATTRI_DEV_ID_T prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) NULL; + + prP2pAttriDevID = (P_P2P_ATTRI_DEV_ID_T) prP2pAttribute; + ASSERT(prP2pAttriDevID->u2Length == 6); + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevID->aucDevAddr, MAC_ADDR_LEN); + } + break; + case P2P_ATTRI_ID_P2P_DEV_INFO: + { + P_P2P_ATTRI_DEV_INFO_T prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + prP2pAttriDevInfo = (P_P2P_ATTRI_DEV_INFO_T) prP2pAttribute; + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prP2pAttriDevInfo->aucDevAddr, + MAC_ADDR_LEN); + rEventDevInfo.u2ConfigMethod = prP2pAttriDevInfo->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prP2pAttriDevInfo->ucNumOfSecondaryDevType <= 2); + /* TODO: Fixme if secondary device type is more than 2. */ + for (u4Idx = 0; u4Idx < prP2pAttriDevInfo->ucNumOfSecondaryDevType; u4Idx++) { + /* TODO: Current sub device type can only support 2. */ + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = prP2pAttriDevInfo->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = + prP2pAttriDevInfo->rPrimaryDevTypeBE.u2SubCategoryId; + } + + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prP2pAttriDevInfo->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); + /* TODO: Fixme if device name length is longer than 32 bytes. */ + kalMemCopy(rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + } + break; + case P2P_ATTRI_ID_P2P_GROUP_INFO: + prP2pAttriGroupInfo = (P_P2P_ATTRI_GROUP_INFO_T) prP2pAttribute; + break; + } + + u2AttributeLen -= (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN); + + prP2pAttribute = + (P_P2P_ATTRIBUTE_T) ((UINT_32) prP2pAttribute + (prP2pAttribute->u2Length + P2P_ATTRI_HDR_LEN)); + + } + + nicRxAddP2pDevice(prAdapter, &rEventDevInfo); + + if (prP2pAttriGroupInfo != NULL) { + P_P2P_CLIENT_INFO_DESC_T prClientInfoDesc = (P_P2P_CLIENT_INFO_DESC_T) NULL; + P_P2P_DEVICE_TYPE_T prP2pDevType = (P_P2P_DEVICE_TYPE_T) NULL; + + prClientInfoDesc = prP2pAttriGroupInfo->arClientDesc; + u2AttributeLen = prP2pAttriGroupInfo->u2Length; + + while (u2AttributeLen > 0) { + /* Basic size for P2P client info descriptor. */ + ASSERT(u2AttributeLen >= 25); + rEventDevInfo.fgDevInfoValid = TRUE; + kalMemCopy(rEventDevInfo.aucCommunicateAddr, prClientInfoDesc->aucIfAddr, MAC_ADDR_LEN); + rEventDevInfo.ucDeviceCapabilityBitmap = prClientInfoDesc->ucDeviceCap; + rEventDevInfo.u2ConfigMethod = prClientInfoDesc->u2ConfigMethodsBE; + + prP2pDevType = &rEventDevInfo.rPriDevType; + prP2pDevType->u2CategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2CategoryId; + prP2pDevType->u2SubCategoryID = prClientInfoDesc->rPrimaryDevTypeBE.u2SubCategoryId; + + ASSERT(prClientInfoDesc->ucNumOfSecondaryDevType <= 2); + /* TODO: Fixme if secondary device type is more than 2. */ + for (u4Idx = 0; u4Idx < prClientInfoDesc->ucNumOfSecondaryDevType; u4Idx++) { + /* TODO: Current sub device type can only support 2. */ + prP2pDevType = &rEventDevInfo.arSecDevType[u4Idx]; + prP2pDevType->u2CategoryID = + prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2CategoryId; + prP2pDevType->u2SubCategoryID = + prClientInfoDesc->arSecondaryDevTypeListBE[u4Idx].u2SubCategoryId; + } + + prP2pDevName = + (P_DEVICE_NAME_TLV_T) (prClientInfoDesc->arSecondaryDevTypeListBE + + (u4Idx * sizeof(DEVICE_TYPE_T))); + ASSERT(prP2pDevName->u2Id == 0x1011); + ASSERT(prP2pDevName->u2Length <= 32); + /* TODO: Fixme if device name length is longer than 32 bytes. */ + kalMemCopy(&rEventDevInfo.aucName, prP2pDevName->aucName, prP2pDevName->u2Length); + + nicRxAddP2pDevice(prAdapter, &rEventDevInfo); + + u2AttributeLen -= prP2pAttriGroupInfo->u2Length; + prP2pAttriGroupInfo = prP2pAttriGroupInfo + prP2pAttriGroupInfo->u2Length + 1; + } + + } +#endif + return WLAN_STATUS_SUCCESS; +} /* scanSendDeviceDiscoverEvent */ + +VOID +scanP2pProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, + IN P_WLAN_STATUS prStatus, + IN P_BSS_DESC_T prBssDesc, IN P_WLAN_BEACON_FRAME_T prWlanBeaconFrame) +{ + BOOLEAN fgIsSkipThisBeacon; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + fgIsSkipThisBeacon = FALSE; + if (prBssDesc->fgIsP2PPresent) { + if ((prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && /* P2P GC */ + (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && /* Connected */ + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { /* TX Beacon */ + + fgIsSkipThisBeacon = TRUE; + } + + if ((!prP2pBssInfo->ucDTIMPeriod) && /* First time. */ + fgIsSkipThisBeacon && (EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen))) { /* SSID Match */ + prP2pBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_P2P_INDEX); + } + + do { + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT_BREAK((prSwRfb != NULL) && (prBssDesc != NULL)); + + if (((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) != MAC_FRAME_PROBE_RSP)) { + /* Only report Probe Response frame to supplicant. */ + /* Probe response collect much more information. */ + + if (fgIsSkipThisBeacon || prBssDesc->eBand == BAND_2G4) + break; + } + + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + prBssDesc->fgIsP2PReport = TRUE; + + DBGLOG(P2P, INFO, "indicate %s [%d]\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, + &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + } while (FALSE); + } +} + +VOID scnEventReturnChannel(IN P_ADAPTER_T prAdapter, IN UINT_8 ucScnSeqNum) +{ + + CMD_SCAN_CANCEL rCmdScanCancel; + + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = ucScnSeqNum; + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8)&rCmdScanCancel, NULL, 0); + +} /* scnEventReturnChannel */ + +VOID scanRemoveAllP2pBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + + prBSSDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + scanRemoveP2pBssDesc(prAdapter, prBssDesc); + } +} /* scanRemoveAllP2pBssDesc */ + +VOID scanRemoveP2pBssDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + + +} /* scanRemoveP2pBssDesc */ + +P_BSS_DESC_T +scanP2pSearchDesc(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_CONNECTION_REQ_INFO_T prConnReqInfo) +{ + P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL, prBssDesc = (P_BSS_DESC_T) NULL; + P_LINK_T prBssDescList = (P_LINK_T) NULL; + + do { + if ((prAdapter == NULL) || (prP2pBssInfo == NULL) || (prConnReqInfo == NULL)) + break; + + prBssDescList = &(prAdapter->rWifiVar.rScanInfo.rBSSDescList); + + DBGLOG(P2P, LOUD, "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); + DBGLOG(P2P, LOUD, "Connecting to SSID:%s, length:%d\n", + prConnReqInfo->rSsidStruct.aucSsid, prConnReqInfo->rSsidStruct.ucSsidLen); + + LINK_FOR_EACH_ENTRY(prBssDesc, prBssDescList, rLinkEntry, BSS_DESC_T) { + DBGLOG(P2P, LOUD, "Checking BSS: %pM\n", prBssDesc->aucBSSID); + + if (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE) { + DBGLOG(P2P, LOUD, "Ignore mismatch BSS type.\n"); + continue; + } + + if (UNEQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnReqInfo->aucBssid)) { + DBGLOG(P2P, LOUD, "Ignore mismatch BSSID.\n"); + continue; + } + + /* SSID should be the same? SSID is vary for each connection. so... */ + if (UNEQUAL_SSID(prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen, + prBssDesc->aucSSID, prBssDesc->ucSSIDLen)) { + + DBGLOG(P2P, TRACE, + "Connecting to BSSID: %pM\n", prConnReqInfo->aucBssid); + DBGLOG(P2P, TRACE, + "Connecting to SSID:%s, length:%d\n", prConnReqInfo->rSsidStruct.aucSsid, + prConnReqInfo->rSsidStruct.ucSsidLen); + DBGLOG(P2P, TRACE, + "Checking SSID:%s, length:%d\n", prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + DBGLOG(P2P, TRACE, "Ignore mismatch SSID, (But BSSID match).\n"); + ASSERT(FALSE); + continue; + } + + if (!prBssDesc->fgIsP2PPresent) { + DBGLOG(P2P, ERROR, "SSID, BSSID, BSSTYPE match, but no P2P IE present.\n"); + continue; + } + + /* Final decision. */ + prCandidateBssDesc = prBssDesc; + break; + } + + } while (FALSE); + + return prCandidateBssDesc; +} /* scanP2pSearchDesc */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c new file mode 100644 index 0000000000000..befb9978f4735 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/p2p_state.c @@ -0,0 +1,466 @@ +#include "p2p_precomp.h" + +BOOLEAN +p2pStateInit_IDLE(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_BSS_INFO_T prP2pBssInfo, OUT P_ENUM_P2P_STATE_T peNextState) +{ + BOOLEAN fgIsTransOut = FALSE; +/* P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T)NULL; */ + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && (prP2pBssInfo != NULL) && (peNextState != NULL)); + + if ((prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) + && IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + fgIsTransOut = TRUE; + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + + DBGLOG(P2P, INFO, "p2pStateInit_IDLE GO Scan\n"); + *peNextState = P2P_STATE_REQING_CHANNEL; + + } else { +#if 0 + else + if (IS_NET_PWR_STATE_ACTIVE(prAdapter, NETWORK_TYPE_P2P_INDEX)) { + + ASSERT((prP2pBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) || + (prP2pBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE)); + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + /* Start a timer for return channel. */ + DBGLOG(P2P, TRACE, "start a GO channel timer.\n"); + } + + } +#endif + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), 5000); + } + + } while (FALSE); + + return fgIsTransOut; +} /* p2pStateInit_IDLE */ + +VOID p2pStateAbort_IDLE(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &prP2pFsmInfo->rChnlReqInfo; + + if (prChnlReqInfo->fgIsChannelRequested) { + /* Release channel before timeout. */ + p2pFuncReleaseCh(prAdapter, prChnlReqInfo); + } + + /* Stop timer for leaving this state. */ + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + } while (FALSE); + +} /* p2pStateAbort_IDLE */ + +VOID p2pStateInit_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Store the original channel info. */ + prChnlReqInfo->ucOriChnlNum = prP2pBssInfo->ucPrimaryChannel; + prChnlReqInfo->eOriBand = prP2pBssInfo->eBand; + prChnlReqInfo->eOriChnlSco = prP2pBssInfo->eBssSCO; + + /* RX Probe Request would check primary channel. */ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucReqChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eChnlSco; + + DBGLOG(P2P, TRACE, "start a channel on hand timer.\n"); + if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING) { + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), + prChnlReqInfo->u4MaxInterval); + + kalP2PIndicateChannelReady(prAdapter->prGlueInfo, + prChnlReqInfo->u8Cookie, + prChnlReqInfo->ucReqChnlNum, + prChnlReqInfo->eBand, prChnlReqInfo->eChnlSco, prChnlReqInfo->u4MaxInterval); + } else + cnmTimerStartTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer), + (P2P_EXT_LISTEN_TIME_MS - prChnlReqInfo->u4MaxInterval)); + } while (FALSE); + +} /* p2pStateInit_CHNL_ON_HAND */ + +VOID +p2pStateAbort_CHNL_ON_HAND(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + /* Restore the original channel info. */ + prP2pBssInfo->ucPrimaryChannel = prChnlReqInfo->ucOriChnlNum; + prP2pBssInfo->eBand = prChnlReqInfo->eOriBand; + prP2pBssInfo->eBssSCO = prChnlReqInfo->eOriChnlSco; + + DBGLOG(P2P, INFO, "p2p state trans abort chann on hand, eListenExted: %d, eNextState: %d\n", + prP2pFsmInfo->eListenExted, eNextState); + if (prP2pFsmInfo->eListenExted != P2P_DEV_EXT_LISTEN_ING || + eNextState != P2P_STATE_CHNL_ON_HAND) { + /* Here maybe have a bug, when it's extlistening, a new remain_on_channel + was sent to driver? need to verify */ + prP2pFsmInfo->eListenExted = P2P_DEV_NOT_EXT_LISTEN; + /* Indicate channel return. */ + kalP2PIndicateChannelExpired(prAdapter->prGlueInfo, &prP2pFsmInfo->rChnlReqInfo); + + /* Return Channel. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + } while (FALSE); +} /* p2pStateAbort_CHNL_ON_HAND */ + +VOID +p2pStateAbort_REQING_CHANNEL(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (eNextState < P2P_STATE_NUM)); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + if (eNextState == P2P_STATE_IDLE) { + if (prP2pBssInfo->eIntendOPMode == OP_MODE_ACCESS_POINT) { + /* Intend to be AP. */ + /* Setup for AP mode. */ + p2pFuncStartGO(prAdapter, + prP2pBssInfo, + prP2pSpecificBssInfo->aucGroupSsid, + prP2pSpecificBssInfo->u2GroupSsidLen, + prP2pSpecificBssInfo->ucPreferredChannel, + prP2pSpecificBssInfo->eRfBand, + prP2pSpecificBssInfo->eRfSco, prP2pFsmInfo->fgIsApMode); + + } else { + /* Return Channel. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + } + + } + + } while (FALSE); + +} /* p2pStateInit_AP_CHANNEL_DETECT */ + +VOID p2pStateInit_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &(prP2pFsmInfo->rScanReqInfo); + + prScanReqInfo->eScanType = SCAN_TYPE_PASSIVE_SCAN; + prScanReqInfo->eChannelSet = SCAN_CHANNEL_2G4; + prScanReqInfo->u2PassiveDewellTime = 50; /* 50ms for passive channel load detection */ + prScanReqInfo->fgIsAbort = TRUE; + prScanReqInfo->fgIsScanRequest = TRUE; + prScanReqInfo->ucNumChannelList = 0; + prScanReqInfo->u4BufLength = 0; + prScanReqInfo->rSsidStruct.ucSsidLen = 0; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + +} /* p2pStateInit_AP_CHANNEL_DETECT */ + +VOID +p2pStateAbort_AP_CHANNEL_DETECT(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = (P_P2P_CHNL_REQ_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + + if (eNextState == P2P_STATE_REQING_CHANNEL) { + UINT_8 ucPreferedChnl = 0; + ENUM_BAND_T eBand = BAND_NULL; + ENUM_CHNL_EXT_T eSco = CHNL_EXT_SCN; + + prChnlReqInfo = &(prP2pFsmInfo->rChnlReqInfo); + + /* Determine the channel for AP. */ + if (cnmPreferredChannel(prAdapter, &eBand, &ucPreferedChnl, &eSco) == FALSE) { + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + ucPreferedChnl = prP2pConnSettings->ucOperatingChnl; + if (ucPreferedChnl == 0) { + + if (scnQuerySparseChannel(prAdapter, &eBand, &ucPreferedChnl) == FALSE) { + + /* What to do? */ + ASSERT(FALSE); + /* TODO: Pick up a valid channel from channel list. */ + ucPreferedChnl = 1; + eBand = BAND_2G4; + } + } + } + + prChnlReqInfo->eChannelReqType = CHANNEL_REQ_TYPE_GO_START_BSS; + + DBGLOG(P2P, INFO, "p2pStateAbort_AP_CHANNEL_DETECT GO Scan\n"); + prChnlReqInfo->ucReqChnlNum = prP2pSpecificBssInfo->ucPreferredChannel = ucPreferedChnl; + prChnlReqInfo->eBand = prP2pSpecificBssInfo->eRfBand = eBand; + prChnlReqInfo->eChnlSco = prP2pSpecificBssInfo->eRfSco = eSco; + } else { + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + } + + } while (FALSE); + +} /* p2pStateAbort_AP_CHANNEL_DETECT */ + +VOID p2pStateInit_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo) +{ + P_P2P_SCAN_REQ_INFO_T prScanReqInfo = (P_P2P_SCAN_REQ_INFO_T) NULL; + + do { + + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL)); + + prScanReqInfo = &prP2pFsmInfo->rScanReqInfo; + + prScanReqInfo->fgIsScanRequest = TRUE; + + p2pFuncRequestScan(prAdapter, prScanReqInfo); + + } while (FALSE); + +} /* p2pStateInit_SCAN */ + +VOID p2pStateAbort_SCAN(IN P_ADAPTER_T prAdapter, IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN ENUM_P2P_STATE_T eNextState) +{ + do { + ASSERT_BREAK(prAdapter != NULL); + + /* 1. Scan cancel. (Make sure the scan request is invalid. */ + p2pFuncCancelScan(prAdapter, &(prP2pFsmInfo->rScanReqInfo)); + + /* Scan done indication. */ + kalP2PIndicateScanDone(prAdapter->prGlueInfo, prP2pFsmInfo->rScanReqInfo.fgIsAbort); + } while (FALSE); + +} /* p2pStateAbort_SCAN */ + +VOID +p2pStateInit_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, + IN P_BSS_INFO_T prP2pBssInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN P_BSS_DESC_T prBssDesc) +{ + P_MSG_JOIN_REQ_T prJoinReqMsg = (P_MSG_JOIN_REQ_T) NULL; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && + (prP2pFsmInfo != NULL) && + (prP2pBssInfo != NULL) && (prJoinInfo != NULL) && (prBssDesc != NULL)); + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prP2pConnSettings->aucSSID, + prP2pConnSettings->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + /* Setup a join timer. */ + DBGLOG(P2P, TRACE, "Start a join init timer\n"); + cnmTimerStartTimer(prAdapter, + &(prAdapter->rP2pFsmTimeoutTimer), + (prP2pFsmInfo->u4GrantInterval - AIS_JOIN_CH_GRANT_THRESHOLD)); + + /* 2 <1> We are goin to connect to this BSS */ + prBssDesc->fgIsConnecting = TRUE; + + /* 2 <2> Setup corresponding STA_RECORD_T */ + prStaRec = bssCreateStaRecFromBssDesc(prAdapter, + (prBssDesc->fgIsP2PPresent ? (STA_TYPE_P2P_GO) + : (STA_TYPE_LEGACY_AP)), NETWORK_TYPE_P2P_INDEX, prBssDesc); + + if (prStaRec == NULL) { + DBGLOG(P2P, TRACE, "Create station record fail\n"); + break; + } + + prJoinInfo->prTargetStaRec = prStaRec; + prJoinInfo->fgIsJoinComplete = FALSE; + prJoinInfo->u4BufLength = 0; + + /* 2 <2.1> Sync. to FW domain */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + if (prP2pBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + prStaRec->fgIsReAssoc = FALSE; + + prP2pConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + switch (prP2pConnSettings->eAuthMode) { + case AUTH_MODE_OPEN: /* Note: Omit break here. */ + case AUTH_MODE_WPA: + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA2: + case AUTH_MODE_WPA2_PSK: + prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_OPEN_SYSTEM; + break; + case AUTH_MODE_SHARED: + prJoinInfo->ucAvailableAuthTypes = (UINT_8) AUTH_TYPE_SHARED_KEY; + break; + case AUTH_MODE_AUTO_SWITCH: + DBGLOG(P2P, LOUD, "JOIN INIT: eAuthMode == AUTH_MODE_AUTO_SWITCH\n"); + prJoinInfo->ucAvailableAuthTypes = (UINT_8) (AUTH_TYPE_OPEN_SYSTEM | + AUTH_TYPE_SHARED_KEY); + break; + default: + ASSERT(!(prP2pConnSettings->eAuthMode == AUTH_MODE_WPA_NONE)); + DBGLOG(P2P, ERROR, "JOIN INIT: Auth Algorithm : %d was not supported by JOIN\n", + prP2pConnSettings->eAuthMode); + /* TODO(Kevin): error handling ? */ + return; + } + prStaRec->ucTxAuthAssocRetryLimit = TX_AUTH_ASSOCI_RETRY_LIMIT; + } else { + ASSERT(FALSE); + /* TODO: Shall we considering ROAMIN case for P2P Device?. */ + } + + /* 2 <4> Use an appropriate Authentication Algorithm Number among the ucAvailableAuthTypes. */ + if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_OPEN_SYSTEM) { + + DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == OPEN_SYSTEM.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_OPEN_SYSTEM; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_OPEN_SYSTEM; + } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_SHARED_KEY) { + + DBGLOG(P2P, TRACE, "JOIN INIT: Try to do Authentication with AuthType == SHARED_KEY.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_SHARED_KEY; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY; + } else if (prJoinInfo->ucAvailableAuthTypes & (UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION) { + + DBGLOG(P2P, TRACE, + "JOIN INIT: Try to do Authentication with AuthType == FAST_BSS_TRANSITION.\n"); + + prJoinInfo->ucAvailableAuthTypes &= ~(UINT_8) AUTH_TYPE_FAST_BSS_TRANSITION; + + prStaRec->ucAuthAlgNum = (UINT_8) AUTH_ALGORITHM_NUM_FAST_BSS_TRANSITION; + } else { + ASSERT(0); + } + + /* 4 <5> Overwrite Connection Setting for eConnectionPolicy == ANY (Used by Assoc Req) */ + if (prBssDesc->ucSSIDLen) { + COPY_SSID(prJoinInfo->rSsidStruct.aucSsid, + prJoinInfo->rSsidStruct.ucSsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + } + /* 2 <5> Backup desired channel. */ + + /* 2 <6> Send a Msg to trigger SAA to start JOIN process. */ + prJoinReqMsg = (P_MSG_JOIN_REQ_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_REQ_T)); + + if (!prJoinReqMsg) { + DBGLOG(P2P, TRACE, "Allocation Join Message Fail\n"); + ASSERT(FALSE); + return; + } + + prJoinReqMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_START; + prJoinReqMsg->ucSeqNum = ++prJoinInfo->ucSeqNumOfReqMsg; + prJoinReqMsg->prStaRec = prStaRec; + + /* TODO: Consider fragmentation info in station record. */ + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinReqMsg, MSG_SEND_METHOD_BUF); + + } while (FALSE); + +} /* p2pStateInit_GC_JOIN */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process of JOIN Abort. Leave JOIN State & Abort JOIN. +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +p2pStateAbort_GC_JOIN(IN P_ADAPTER_T prAdapter, + IN P_P2P_FSM_INFO_T prP2pFsmInfo, IN P_P2P_JOIN_INFO_T prJoinInfo, IN ENUM_P2P_STATE_T eNextState) +{ + P_MSG_JOIN_ABORT_T prJoinAbortMsg = (P_MSG_JOIN_ABORT_T) NULL; + + do { + ASSERT_BREAK((prAdapter != NULL) && (prP2pFsmInfo != NULL) && (prJoinInfo != NULL)); + + if (prJoinInfo->fgIsJoinComplete == FALSE) { + + prJoinAbortMsg = + (P_MSG_JOIN_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_JOIN_ABORT_T)); + if (!prJoinAbortMsg) { + DBGLOG(P2P, TRACE, "Fail to allocate join abort message buffer\n"); + ASSERT(FALSE); + return; + } + + prJoinAbortMsg->rMsgHdr.eMsgId = MID_P2P_SAA_FSM_ABORT; + prJoinAbortMsg->ucSeqNum = prJoinInfo->ucSeqNumOfReqMsg; + prJoinAbortMsg->prStaRec = prJoinInfo->prTargetStaRec; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prJoinAbortMsg, MSG_SEND_METHOD_BUF); + + } + + /* Stop Join Timer. */ + cnmTimerStopTimer(prAdapter, &(prAdapter->rP2pFsmTimeoutTimer)); + + /* Release channel requested. */ + p2pFuncReleaseCh(prAdapter, &(prP2pFsmInfo->rChnlReqInfo)); + + } while (FALSE); + + return; + +} /* p2pStateAbort_GC_JOIN */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c new file mode 100644 index 0000000000000..72fa52e761da5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/privacy.c @@ -0,0 +1,915 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/privacy.c#1 +*/ + +/*! \file "privacy.c" + \brief This file including the protocol layer privacy function. + + This file provided the macros and functions library support for the + protocol layer security setting from rsn.c and nic_privacy.c + +*/ + +/* +** Log: privacy.c + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 20 2011 terry.wu + * NULL + * Fix Hotspot deauth send failed. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 06 28 2011 tsaiyuan.hsu + * [WCXRP00000819] [MT6620 Wi-Fi][Driver] check if staRec is NULL or not in secCheckClassError + * check if staRec is NULL or not in secCheckClassError. + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T + * and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 20 2010 wh.su + * + * adding the wapi code. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * adding the compiling flag for migration. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 04 22 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the wpi same key id rx issue and fixed the remove wep key issue. + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Send Deauth for Class 3 Error and Leave Network Support + * + * 04 15 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * remove the assert code for allow ad-hoc pkt. + * + * 04 13 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the Klocwork error and refine the class error message. + * + * 03 04 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Code refine, and remove non-used code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, + * and modify the security related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 26 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * change the waning message shown level, and clear the global transmit flag for CMD INFRASTRUCTURE. + * + * 02 25 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * For support the WHQL test, do the remove key code refine. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 12 25 2009 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Integrated modifications for 1st connection (mainly on FW modules MQM, TXM, and RXM) + * * * * * * * * * MQM: BA handling + * * * * * * * * * TXM: Macros updates + * * * * * * * * * RXM: Macros/Duplicate Removal updates + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 11 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * modify the cmd with result return + * + * Dec 11 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * fixed the value not initialize issue + * + * Dec 10 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the cmd return type + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function to update the auth mode and encryption status for cmd build connection + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some code for wapi mode + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the call to check the 4th and eapol error report frame + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the function name + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code for parsing the EAPoL frame, and do some code refine + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the class error check + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the cmd_802_11_pmkid code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * doing some function rename, and adding the code for cmd CMD_ADD_REMOVE_KEY + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the clear pmkid function + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix eStaType check for AIS + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the ap selection related code + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_PRIVACY_MIGRATION + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to initialize the privacy-related +* parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] ucNetTypeIdx Pointer to netowrk type index +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID secInit(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetTypeIdx) +{ + UINT_8 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("secInit"); + + ASSERT(prAdapter); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prBssInfo->u4RsnSelectedGroupCipher = 0; + prBssInfo->u4RsnSelectedPairwiseCipher = 0; + prBssInfo->u4RsnSelectedAKMSuite = 0; + +#if CFG_ENABLE_WIFI_DIRECT + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX]; + + prBssInfo->u4RsnSelectedGroupCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prBssInfo->u4RsnSelectedAKMSuite = RSN_AKM_SUITE_PSK; +#endif + + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[0].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_WEP40; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[1].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_TKIP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[2].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_CCMP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[3].dot11RSNAConfigPairwiseCipher = WPA_CIPHER_SUITE_WEP104; + + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[4].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_WEP40; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[5].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_TKIP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[6].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_CCMP; + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[7].dot11RSNAConfigPairwiseCipher = RSN_CIPHER_SUITE_WEP104; + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; + + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[0].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_NONE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[1].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[2].dot11RSNAConfigAuthenticationSuite = + WPA_AKM_SUITE_PSK; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[3].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_NONE; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[4].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[5].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_PSK; + +#if CFG_SUPPORT_802_11W + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[6].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_802_1X_SHA256; + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[7].dot11RSNAConfigAuthenticationSuite = + RSN_AKM_SUITE_PSK_SHA256; +#endif + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i].dot11RSNAConfigAuthenticationSuiteEnabled = + FALSE; + } + + secClearPmkid(prAdapter); + + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rPreauthenticationTimer, + (PFN_MGMT_TIMEOUT_FUNC) rsnIndicatePmkidCand, (ULONG) NULL); + +#if CFG_SUPPORT_802_11W + cnmTimerInitTimer(prAdapter, + &prAisSpecBssInfo->rSaQueryTimer, (PFN_MGMT_TIMEOUT_FUNC) rsnStartSaQueryTimer, (ULONG) NULL); +#endif + + prAisSpecBssInfo->fgCounterMeasure = FALSE; + prAisSpecBssInfo->ucWEPDefaultKeyID = 0; + +#if 0 + for (i = 0; i < WTBL_SIZE; i++) { + g_prWifiVar->arWtbl[i].fgUsed = FALSE; + g_prWifiVar->arWtbl[i].prSta = NULL; + g_prWifiVar->arWtbl[i].ucNetTypeIdx = NETWORK_TYPE_INDEX_NUM; + + } + nicPrivacyInitialize((UINT_8) NETWORK_TYPE_INDEX_NUM); +#endif +} /* secInit */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Rx Class Error" to SEC_FSM for +* JOIN Module. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSwRfb Pointer to the SW RFB. +* +* \return FALSE Class Error +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secCheckClassError(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN P_STA_RECORD_T prStaRec) +{ + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prStaRec) + return FALSE; + + eNetTypeIndex = prStaRec->ucNetTypeIndex; + if (!IS_NET_ACTIVE(prAdapter, eNetTypeIndex)) + return FALSE; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]; + if ((STA_STATE_3 != prStaRec->ucStaState) && prBssInfo->fgIsNetAbsent == FALSE) { + /*(IS_AP_STA(prStaRec) || IS_CLIENT_STA(prStaRec))) { */ + +#if 0 /* by scott's suggestions, do not put work-around in JB2,we need to find the root cause */ + /* work-around for CR ALPS00816361 */ + if (eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + DBGLOG(RSN, INFO, + "p2p> skip to send Deauth to MAC:[%pM] for Rx Class 3.\n", + prStaRec->aucMacAddr); + return TRUE; + } +#endif + + if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, + prStaRec, + NULL, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL)) + + DBGLOG(RSN, INFO, "Send Deauth to [ %pM ] for Rx Class 3 Error.\n", + prStaRec->aucMacAddr); + else + DBGLOG(RSN, INFO, "Host sends Deauth to [ %pM ] for Rx Class 3 fail.\n", + prStaRec->aucMacAddr); + return FALSE; + } + + return secRxPortControlCheck(prAdapter, prSwRfb); +} /* end of secCheckClassError() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to setting the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[in] fgPortBlock The port status +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID secSetPortBlocked(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgPortBlock) +{ + if (prSta == NULL) + return; + + prSta->fgPortBlock = fgPortBlock; + + DBGLOG(RSN, TRACE, + "The STA %pM port %s\n", prSta->aucMacAddr, fgPortBlock == TRUE ? "BLOCK" : " OPEN"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to report the sta port status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer to the sta +* \param[out] fgPortBlock The port status +* +* \return TRUE sta exist, FALSE sta not exist +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secGetPortStatus(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, OUT PBOOLEAN pfgPortStatus) +{ + if (prSta == NULL) + return FALSE; + + *pfgPortStatus = prSta->fgPortBlock; + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle Peer device Tx Security process MSDU. +* +* \param[in] prMsduInfo pointer to the packet info pointer +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port blocked +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN /* ENUM_PORT_CONTROL_RESULT */ +secTxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + if (prStaRec) { + + /* Todo:: */ + if (prMsduInfo->fgIs802_1x) + return TRUE; + + if (prStaRec->fgPortBlock == TRUE) { + DBGLOG(SEC, TRACE, "Drop Tx packet due Port Control!\n"); + return FALSE; + } +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) + return TRUE; +#endif + if (IS_STA_IN_AIS(prStaRec)) { + if (!prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist && + (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED)) { + DBGLOG(SEC, TRACE, "Drop Tx packet due the key is removed!!!\n"); + return FALSE; + } + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The Rx Security process MSDU. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSWRfb SW rfb pinter +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secRxPortControlCheck(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSWRfb) +{ + ASSERT(prSWRfb); + +#if 0 + /* whsu:Todo: Process MGMT and DATA */ + if (prSWRfb->prStaRec) { + if (prSWRfb->prStaRec->fgPortBlock == TRUE) { + if (1 /* prSWRfb->fgIsDataFrame and not 1x */ && + (g_prWifiVar->rConnSettings.eAuthMode >= AUTH_MODE_WPA)) { + /* DBGLOG(SEC, WARN, ("Drop Rx data due port control !\r\n")); */ + return TRUE; /* Todo: whsu FALSE; */ + } + /* if (!RX_STATUS_IS_PROTECT(prSWRfb->prRxStatus)) { */ + /* DBGLOG(RSN, WARN, ("Drop rcv non-encrypted data frame!\n")); */ + /* return FALSE; */ + /* } */ + } + } else { + } +#endif + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine will enable/disable the cipher suite +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4CipherSuitesFlags flag for cipher suite +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID secSetCipherSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4CipherSuitesFlags) +{ + UINT_32 i; + P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; + P_IEEE_802_11_MIB_T prMib; + + ASSERT(prAdapter); + + prMib = &prAdapter->rMib; + + ASSERT(prMib); + + if (u4CipherSuitesFlags == CIPHER_FLAG_NONE) { + /* Disable all the pairwise cipher suites. */ + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) + prMib->dot11RSNAConfigPairwiseCiphersTable[i].dot11RSNAConfigPairwiseCipherEnabled = FALSE; + + /* Update the group cipher suite. */ + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + + return; + } + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = &prMib->dot11RSNAConfigPairwiseCiphersTable[i]; + + switch (prEntry->dot11RSNAConfigPairwiseCipher) { + case WPA_CIPHER_SUITE_WEP40: + case RSN_CIPHER_SUITE_WEP40: + if (u4CipherSuitesFlags & CIPHER_FLAG_WEP40) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (u4CipherSuitesFlags & CIPHER_FLAG_TKIP) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (u4CipherSuitesFlags & CIPHER_FLAG_CCMP) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + + case WPA_CIPHER_SUITE_WEP104: + case RSN_CIPHER_SUITE_WEP104: + if (u4CipherSuitesFlags & CIPHER_FLAG_WEP104) + prEntry->dot11RSNAConfigPairwiseCipherEnabled = TRUE; + else + prEntry->dot11RSNAConfigPairwiseCipherEnabled = FALSE; + break; + default: + break; + } + } + + /* Update the group cipher suite. */ + if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_CCMP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_TKIP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP104; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_WEP40; + else + prMib->dot11RSNAConfigGroupCipher = WPA_CIPHER_SUITE_NONE; + +} /* secSetCipherSuite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle The 2nd Tx EAPoL Frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsduInfo pointer to the packet info pointer +* \param[in] pucPayload pointer to the 1x hdr +* \param[in] u2PayloadLen the 1x payload length +* +* \retval TRUE Accept the packet +* \retval FALSE Refuse the MSDU packet due port control +* +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +secProcessEAPOL(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN PUINT_8 pucPayload, IN UINT_16 u2PayloadLen) +{ + P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; + P_IEEE_802_1X_HDR pr1xHdr; + UINT_16 u2KeyInfo; + + ASSERT(prMsduInfo); + ASSERT(prStaRec); + + /* prStaRec = &(g_arStaRec[prMsduInfo->ucStaRecIndex]); */ + ASSERT(prStaRec); + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR) pucPayload; + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY) ((PUINT_32) (pucPayload + 4)); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (u2KeyInfo & WPA_KEY_INFO_SECURE) { + /* 4th EAPoL check at secHandleTxDoneCallback() */ + /* DBGLOG(RSN, TRACE, ("Tx 4th EAPoL frame\r\n")); */ + } else if (u2PayloadLen == 123 /* Not include LLC */) { + DBGLOG(RSN, INFO, "Tx 2nd EAPoL frame\r\n"); + secFsmEvent2ndEapolTx(prAdapter, prStaRec); + } + } + } + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will handle the 4th EAPoL Tx done and mic Error Report frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secHandleTxDoneCallback(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_STA_RECORD_T prStaRec, IN WLAN_STATUS rStatus) +{ + PUINT_8 pucPayload; + P_IEEE_802_1X_HDR pr1xHdr = (P_IEEE_802_1X_HDR) NULL; + P_EAPOL_KEY prEapol = (P_EAPOL_KEY) NULL; + UINT_16 u2KeyInfo; + UINT_16 u2PayloadLen; + + DEBUGFUNC("secHandleTxDoneCallback"); + + ASSERT(prMsduInfo); + /* Todo:: Notice if using the TX free immediate after send to firmware, the payload may not correcttly!!!! */ + + ASSERT(prStaRec); + + /* Todo:: This call back may not need because the order of set key and send 4th 1x can be make sure */ + /* Todo:: Notice the LLC offset */ +#if 1 + pucPayload = (PUINT_8) prMsduInfo->prPacket; + ASSERT(pucPayload); + + u2PayloadLen = prMsduInfo->u2FrameLength; + + if (0 /* prMsduInfo->fgIs1xFrame */) { + + if (prStaRec && IS_AP_STA(prStaRec)) { + pr1xHdr = (P_IEEE_802_1X_HDR) (PUINT_32) (pucPayload + 8); + if ((pr1xHdr->ucType == 3) /* EAPoL key */ && ((u2PayloadLen - 4) > sizeof(EAPOL_KEY))) { + prEapol = (P_EAPOL_KEY) (PUINT_32) (pucPayload + 12); + WLAN_GET_FIELD_BE16(prEapol->aucKeyInfo, &u2KeyInfo); + if ((prEapol->ucType == 254) && (u2KeyInfo & MASK_2ND_EAPOL)) { + if (prStaRec->rSecInfo.fg2nd1xSend == TRUE + && u2PayloadLen == + 107 /* include LLC *//* u2KeyInfo & WPA_KEY_INFO_SECURE */) { + DBGLOG(RSN, INFO, "Tx 4th EAPoL frame\r\n"); + secFsmEvent4ndEapolTxDone(prAdapter, prStaRec); + } else if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone) { + DBGLOG(RSN, INFO, "Tx EAPoL Error report frame\r\n"); + /* secFsmEventEapolTxDone(prAdapter, (UINT_32)prMsduInfo->prStaRec); */ + } + } + } + } + + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to initialize the pmkid parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID secClearPmkid(IN P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("secClearPmkid"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + DBGLOG(RSN, TRACE, "secClearPmkid\n"); + prAisSpecBssInfo->u4PmkidCandicateCount = 0; + prAisSpecBssInfo->u4PmkidCacheCount = 0; + kalMemZero((PVOID) prAisSpecBssInfo->arPmkidCandicate, sizeof(PMKID_CANDICATE_T) * CFG_MAX_PMKID_CACHE); + kalMemZero((PVOID) prAisSpecBssInfo->arPmkidCache, sizeof(PMKID_ENTRY_T) * CFG_MAX_PMKID_CACHE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether WPA, or WPA2 but not WPA-None is enabled. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secRsnKeyHandshakeEnabled(IN P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + + ASSERT(prConnSettings); + + ASSERT(prConnSettings->eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); + + if (prConnSettings->eEncStatus == ENUM_ENCRYPTION_DISABLED) + return FALSE; + + ASSERT(prConnSettings->eAuthMode < AUTH_MODE_NUM); + if ((prConnSettings->eAuthMode >= AUTH_MODE_WPA) && (prConnSettings->eAuthMode != AUTH_MODE_WPA_NONE)) + return TRUE; + + return FALSE; +} /* secRsnKeyHandshakeEnabled */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return whether the transmit key alread installed. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prSta Pointer the sta record +* +* \retval TRUE Default key or Transmit key installed +* FALSE Default key or Transmit key not installed +* +* \note: +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secTransmitKeyExist(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + ASSERT(prSta); + + if (prSta->fgTransmitKeyExist) + return TRUE; + else + return FALSE; +} /* secTransmitKeyExist */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether 802.11 privacy is enabled. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secEnabledInAis(IN P_ADAPTER_T prAdapter) +{ + DEBUGFUNC("secEnabled"); + + ASSERT(prAdapter->rWifiVar.rConnSettings.eEncStatus < ENUM_ENCRYPTION3_KEY_ABSENT); + + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION_DISABLED: + return FALSE; + case ENUM_ENCRYPTION1_ENABLED: + case ENUM_ENCRYPTION2_ENABLED: + case ENUM_ENCRYPTION3_ENABLED: + return TRUE; + default: + DBGLOG(RSN, TRACE, "Unknown encryption setting %d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus); + break; + } + return FALSE; +} /* secEnabled */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the privacy bit at mac header for TxM +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] prMsdu the msdu for known the sta record +* +* \return TRUE the privacy need to set +* FALSE the privacy no need to set +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secIsProtectedFrame(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsdu, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prAdapter); + + ASSERT(prMsdu); + + ASSERT(prStaRec); + /* prStaRec = &(g_arStaRec[prMsdu->ucStaRecIndex]); */ + + if (prStaRec == NULL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) + return TRUE; + return FALSE; /* No privacy bit */ + } + + /* Todo:: */ + if (0 /* prMsdu->fgIs1xFrame */) { + if (IS_STA_IN_AIS(prStaRec) && prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) { + DBGLOG(RSN, LOUD, "For AIS Legacy 1x, always not encryped\n"); + return FALSE; + } else if (!prStaRec->fgTransmitKeyExist) { + DBGLOG(RSN, LOUD, "1x Not Protected.\n"); + return FALSE; + } else if (prStaRec->rSecInfo.fgKeyStored) { + DBGLOG(RSN, LOUD, "1x not Protected due key stored!\n"); + return FALSE; + } + DBGLOG(RSN, LOUD, "1x Protected.\n"); + return TRUE; + } + if (!prStaRec->fgTransmitKeyExist) { + /* whsu , check for AIS only */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist) { + DBGLOG(RSN, LOUD, "Protected\n"); + return TRUE; + } + } else { + DBGLOG(RSN, LOUD, "Protected.\n"); + return TRUE; + } + + /* No sec or key is removed!!! */ + return FALSE; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c new file mode 100644 index 0000000000000..fd0a8772a6665 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rate.c @@ -0,0 +1,497 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rate.c#1 +*/ + +/*! \file "rate.c" + \brief This file contains the transmission rate handling routines. + + This file contains the transmission rate handling routines for setting up + ACK/CTS Rate, Highest Tx Rate, Lowest Tx Rate, Initial Tx Rate and do + conversion between Rate Set and Data Rates. +*/ + +/* +** Log: rate.c + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add rate.c. + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comments + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix DBGLOG + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +** \main\maintrunk.MT5921\12 2008-12-19 17:19:32 GMT mtk01461 +** Fix the problem that do not ASSERT the length of Supported Rate IE == 8 +** \main\maintrunk.MT5921\11 2008-12-01 18:17:42 GMT mtk01088 +** fixed the lint "possible using null pointer" warning +** \main\maintrunk.MT5921\10 2008-08-20 00:16:36 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\9 2008-04-13 21:17:13 GMT mtk01461 +** Revise GEN Link Speed OID +** \main\maintrunk.MT5921\8 2008-03-28 10:40:13 GMT mtk01461 +** Add rateGetRateSetFromDataRates() for set desired rate OID +** \main\maintrunk.MT5921\7 2008-03-26 09:16:20 GMT mtk01461 +** Add adopt operational rate as ACK rate if BasicRateSet was not found +** Add comments +** \main\maintrunk.MT5921\6 2008-02-21 15:01:39 GMT mtk01461 +** Add initial rate according rx signal quality support +** \main\maintrunk.MT5921\5 2008-01-07 15:06:44 GMT mtk01461 +** Fix typo of rate adaptation of CtrlResp Frame +** \main\maintrunk.MT5921\4 2007-10-25 18:05:12 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* The list of valid data rates. */ +const UINT_8 aucDataRate[] = { + RATE_1M, /* RATE_1M_INDEX = 0 */ + RATE_2M, /* RATE_2M_INDEX */ + RATE_5_5M, /* RATE_5_5M_INDEX */ + RATE_11M, /* RATE_11M_INDEX */ + RATE_22M, /* RATE_22M_INDEX */ + RATE_33M, /* RATE_33M_INDEX */ + RATE_6M, /* RATE_6M_INDEX */ + RATE_9M, /* RATE_9M_INDEX */ + RATE_12M, /* RATE_12M_INDEX */ + RATE_18M, /* RATE_18M_INDEX */ + RATE_24M, /* RATE_24M_INDEX */ + RATE_36M, /* RATE_36M_INDEX */ + RATE_48M, /* RATE_48M_INDEX */ + RATE_54M, /* RATE_54M_INDEX */ + RATE_HT_PHY /* RATE_HT_PHY_INDEX */ +}; + +static const UINT_8 aucDefaultAckCtsRateIndex[RATE_NUM] = { + RATE_1M_INDEX, /* RATE_1M_INDEX = 0 */ + RATE_2M_INDEX, /* RATE_2M_INDEX */ + RATE_5_5M_INDEX, /* RATE_5_5M_INDEX */ + RATE_11M_INDEX, /* RATE_11M_INDEX */ + RATE_1M_INDEX, /* RATE_22M_INDEX - Not supported */ + RATE_1M_INDEX, /* RATE_33M_INDEX - Not supported */ + RATE_6M_INDEX, /* RATE_6M_INDEX */ + RATE_6M_INDEX, /* RATE_9M_INDEX */ + RATE_12M_INDEX, /* RATE_12M_INDEX */ + RATE_12M_INDEX, /* RATE_18M_INDEX */ + RATE_24M_INDEX, /* RATE_24M_INDEX */ + RATE_24M_INDEX, /* RATE_36M_INDEX */ + RATE_24M_INDEX, /* RATE_48M_INDEX */ + RATE_24M_INDEX /* RATE_54M_INDEX */ +}; + +const BOOLEAN afgIsOFDMRate[RATE_NUM] = { + FALSE, /* RATE_1M_INDEX = 0 */ + FALSE, /* RATE_2M_INDEX */ + FALSE, /* RATE_5_5M_INDEX */ + FALSE, /* RATE_11M_INDEX */ + FALSE, /* RATE_22M_INDEX - Not supported */ + FALSE, /* RATE_33M_INDEX - Not supported */ + TRUE, /* RATE_6M_INDEX */ + TRUE, /* RATE_9M_INDEX */ + TRUE, /* RATE_12M_INDEX */ + TRUE, /* RATE_18M_INDEX */ + TRUE, /* RATE_24M_INDEX */ + TRUE, /* RATE_36M_INDEX */ + TRUE, /* RATE_48M_INDEX */ + TRUE /* RATE_54M_INDEX */ +}; + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Supported Rate & Extended Supported Rate IE to the +* Operational Rate Set and Basic Rate Set, and also check if any Basic +* Rate Code is unknown by driver. +* +* @param[in] prIeSupportedRate Pointer to the Supported Rate IE +* @param[in] prIeExtSupportedRate Pointer to the Ext Supported Rate IE +* @param[out] pu2OperationalRateSet Pointer to the Operational Rate Set +* @param[out] pu2BSSBasicRateSet Pointer to the Basic Rate Set +* @param[out] pfgIsUnknownBSSBasicRate Pointer to a Flag to indicate that Basic +* Rate Set has unknown Rate Code +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetRateSetFromIEs(IN P_IE_SUPPORTED_RATE_T prIeSupportedRate, + IN P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate, + OUT PUINT_16 pu2OperationalRateSet, + OUT PUINT_16 pu2BSSBasicRateSet, OUT PBOOLEAN pfgIsUnknownBSSBasicRate) +{ + UINT_16 u2OperationalRateSet = 0; + UINT_16 u2BSSBasicRateSet = 0; + BOOLEAN fgIsUnknownBSSBasicRate = FALSE; + UINT_8 ucRate; + UINT_32 i, j; + + ASSERT(pu2OperationalRateSet); + ASSERT(pu2BSSBasicRateSet); + ASSERT(pfgIsUnknownBSSBasicRate); + + if (prIeSupportedRate) { + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* ASSERT(prIeSupportedRate->ucLength <= ELEM_MAX_LEN_SUP_RATES); */ + ASSERT(prIeSupportedRate->ucLength <= RATE_NUM); + + for (i = 0; i < prIeSupportedRate->ucLength; i++) { + ucRate = prIeSupportedRate->aucSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && + (prIeSupportedRate->aucSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + if (prIeExtSupportedRate) { + /* ASSERT(prIeExtSupportedRate->ucLength <= ELEM_MAX_LEN_EXTENDED_SUP_RATES); */ + + for (i = 0; i < prIeExtSupportedRate->ucLength; i++) { + ucRate = prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2OperationalRateSet |= BIT(j); + + if (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT) + u2BSSBasicRateSet |= BIT(j); + + break; + } + } + + if ((j == sizeof(aucDataRate) / sizeof(UINT_8)) && + (prIeExtSupportedRate->aucExtSupportedRates[i] & RATE_BASIC_BIT)) { + fgIsUnknownBSSBasicRate = TRUE; /* A data rate not list in the aucDataRate[] */ + } + } + } + + *pu2OperationalRateSet = u2OperationalRateSet; + *pu2BSSBasicRateSet = u2BSSBasicRateSet; + *pfgIsUnknownBSSBasicRate = fgIsUnknownBSSBasicRate; + + return; + +} /* end of rateGetRateSetFromIEs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the given Operational Rate Set & Basic Rate Set to the Rate Code +* Format for used in (Ext)Supportec Rate IE. +* +* @param[in] u2OperationalRateSet Operational Rate Set +* @param[in] u2BSSBasicRateSet Basic Rate Set +* @param[out] pucDataRates Pointer to the Data Rate Buffer +* @param[out] pucDataRatesLen Pointer to the Data Rate Buffer Length +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateGetDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, OUT PUINT_8 pucDataRates, OUT PUINT_8 pucDataRatesLen) +{ + UINT_32 i, j; + + ASSERT(pucDataRates); + ASSERT(pucDataRatesLen); + + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + for (i = RATE_1M_INDEX, j = 0; i < RATE_NUM; i++) { + if (u2OperationalRateSet & BIT(i)) { + + *(pucDataRates + j) = aucDataRate[i]; + + if (u2BSSBasicRateSet & BIT(i)) + *(pucDataRates + j) |= RATE_BASIC_BIT; + + j++; + } + } + + *pucDataRatesLen = (UINT_8) j; + + return; + +} /* end of rateGetDataRatesFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the highest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucHighestRateIndex Pointer to buffer of the Highest Rate Index +* +* \retval TRUE Highest Rate Index was found +* \retval FALSE Highest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetHighestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucHighestRateIndex) +{ + INT_32 i; + + ASSERT(pucHighestRateIndex); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucHighestRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetHighestRateIndexFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the lowest rate from given Rate Set. +* +* \param[in] u2RateSet Rate Set +* \param[out] pucLowestRateIndex Pointer to buffer of the Lowest Rate Index +* +* \retval TRUE Lowest Rate Index was found +* \retval FALSE Lowest Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetLowestRateIndexFromRateSet(IN UINT_16 u2RateSet, OUT PUINT_8 pucLowestRateIndex) +{ + UINT_32 i; + + ASSERT(pucLowestRateIndex); + + for (i = RATE_1M_INDEX; i <= RATE_54M_INDEX; i++) { + if (u2RateSet & BIT(i)) { + *pucLowestRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetLowestRateIndexFromRateSet() */ + +#if 0 /* NOTE(Kevin): For reference */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Convert the given Data Rates to the Rate Set. +* +* \param[in] pucDataRates Pointer to the Data Rates +* \param[in] ucDataRatesLen Length of given Data Rates +* \param[out] pu2RateSet Pointer to the Rate Set +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rateGetRateSetFromDataRates(IN PUINT_8 pucDataRates, IN UINT_8 ucDataRatesLen, OUT PUINT_16 pu2RateSet) +{ + UINT_16 u2RateSet = 0; + UINT_8 ucRate; + UINT_32 i, j; + + ASSERT(pucDataRates); + ASSERT(pu2RateSet); + + if (pucDataRates) { + for (i = 0; i < ucDataRatesLen; i++) { + ucRate = pucDataRates[i] & RATE_MASK; + + /* Search all valid data rates */ + for (j = 0; j < sizeof(aucDataRate) / sizeof(UINT_8); j++) { + if (ucRate == aucDataRate[j]) { + u2RateSet |= BIT(j); + break; + } + } + } + } + + *pu2RateSet = u2RateSet; + + return; + +} /* end of rateGetRateSetFromDataRates() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the Operational Rate Set and Basic Rate Set to get the corresponding +* ACK/CTS(Respnose) TX Rates. +* +* \param[in] u2OperationalRateSet Operational Rate Set +* \param[in] u2BSSBasicRateSet Basic Rate Set +* \param[out] aucAckCtsRateIndex Pointer to the Ack/Cts Data Rate Buffer +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +rateSetAckCtsDataRatesFromRateSet(IN UINT_16 u2OperationalRateSet, + IN UINT_16 u2BSSBasicRateSet, IN OUT UINT_8 aucAckCtsRateIndex[]) +{ + INT_32 i, j; + + ASSERT(aucAckCtsRateIndex); + ASSERT(u2BSSBasicRateSet == (u2OperationalRateSet & u2BSSBasicRateSet)); + + /* Setup default ACK/CTS response rate */ + kalMemCopy(aucAckCtsRateIndex, (PVOID) aucDefaultAckCtsRateIndex, sizeof(aucDefaultAckCtsRateIndex)); + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2OperationalRateSet & BIT(i)) { + for (j = i; j >= RATE_1M_INDEX; j--) { + if (u2BSSBasicRateSet & BIT(j)) { + /* Reply ACK Frame at the same Modulation Scheme. */ + if ((afgIsOFDMRate[i] && afgIsOFDMRate[j]) || + (!afgIsOFDMRate[i] && !afgIsOFDMRate[j])) + aucAckCtsRateIndex[i] = (UINT_8) j; + break; + } + } + + /* NOTE(Kevin 2008/03/25): Following code is used for those AP which has + * NULL BasicRateSet. + * e.g. If input Operational Rate Set = [18M 12M 9M], Basic Rate Set = NULL. + * Originally we'll get Ack Rate for [18M 12M 9M] is [12M 12M "6M"]. + * Now we'll get Ack Rate for [18M 12M 9M] is [12M 12M 9M], + * The Ack Rate for Tx Rates which are not list in Operational Rate Set is still + * use highest mandatory rate as default. + */ + if (j < RATE_1M_INDEX) { /* The ACK/CTS rate was not found in BasicRateSet */ + if (!(BIT(aucAckCtsRateIndex[i]) & u2OperationalRateSet)) + aucAckCtsRateIndex[i] = (UINT_8) i; + } + } + } + + return; + +} /* end of rateSetAckCtsDataRatesFromRateSet() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the proper initial rate from Rate Set according to given RCPI value +* +* \param[in] u2RateSet Rate Set +* \param[in] rRcpi RCPI value from AP or Peer STA +* \param[out] pucInitialRateIndex Pointer to buffer of the initial Rate Index +* +* \retval TRUE Initial Rate Index was found +* \retval FALSE Initial Rate Index was not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rateGetBestInitialRateIndex(IN UINT_16 u2RateSet, IN RCPI rRcpi, OUT PUINT_8 pucInitialRateIndex) +{ + UINT_16 u2InitRateSet; + INT_32 i; + + ASSERT(pucInitialRateIndex); + + DBGLOG(MGT, TRACE, "rRcpi = %d\n", rRcpi); + + if (rRcpi >= RCPI_100) { /* Best Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_100); + } else if (rRcpi >= RCPI_80) { /* Better Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_80); + } else if (rRcpi >= RCPI_60) { /* Good Signal */ + u2InitRateSet = INITIAL_RATE_SET(RCPI_60); + } else { /* Worse Signal */ + /* NOTE(Kevin): If return FALSE, we should assign the BSS Basic Rate Index + * (prBssInfo->ucBasicRateIndex) to the initial rate. It was determined in + * function - bssUpdateTxRateForControlFrame(). + */ + return FALSE; + } + + u2RateSet &= u2InitRateSet; + + for (i = RATE_54M_INDEX; i >= RATE_1M_INDEX; i--) { + if (u2RateSet & BIT(i)) { + *pucInitialRateIndex = (UINT_8) i; + return TRUE; + } + } + + return FALSE; + +} /* end of rateGetBestInitialRateIndex() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c new file mode 100644 index 0000000000000..244346983f405 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm.c @@ -0,0 +1,1858 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm.c#2 +*/ + +/*! \file "rlm.c" + \brief + +*/ + +/* +** Log: rlm.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Check length HT cap IE about RX associate request frame + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 03 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Fix preamble type of STA mode + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Not send ERP IE if peer STA is 802.11b-only + * + * 10 11 2011 cm.chang + * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter + * Ignore HT OP IE if its length field is not valid + * + * 09 28 2011 cm.chang + * NULL + * Add length check to reduce possibility to adopt wrong IE + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * Handle client mode about preamble type and slot time + * + * 09 01 2011 cm.chang + * [WCXRP00000971] [MT6620 Wi-Fi][Driver][FW] Not set Beacon timeout interval when CPTT + * Final channel number only adopts the field from assoc response + * + * 06 10 2011 cm.chang + * [WCXRP00000773] [MT6620 Wi-Fi][Driver] Workaround some AP fill primary channel field with its secondary channel + * If DS IE exists, ignore the primary channel field in HT OP IE + * + * 05 03 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Fix compiling error + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Refine range of valid channel number + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Check if channel is valided before record ing BSS channel + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode + * and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 10 15 2010 cm.chang + * [WCXRP00000094] [MT6620 Wi-Fi][Driver] Connect to 2.4GHz AP, Driver crash. + * Add exception handle when no mgmt buffer in free build + * + * 10 08 2010 cm.chang + * NULL + * When 20M only setting, ignore OBSS IE + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 23 2010 chinghwa.yu + * NULL + * Temporary add rlmUpdateParamByStaForBow() and rlmBssInitForBow(). + * + * 08 23 2010 chinghwa.yu + * NULL + * Add CFG_ENABLE_BT_OVER_WIFI. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 02 2010 yuche.tsai + * NULL + * P2P Group Negotiation Code Check in. + * + * 07 26 2010 yuche.tsai + * + * Fix compile error while enabling WiFi Direct function. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 06 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix channel ID definition in RFB status to primary channel instead of center channel + * + * 06 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add TX short GI compiling option + * + * 06 02 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Roll back to remove CFG_SUPPORT_BCM_TEST. + * + * 06 01 2010 chinghwa.yu + * [BORA00000563]Add WiFi CoEx BCM module + * Update BCM Test and RW configuration. + * + * 05 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add some compiling options to control 11n functions + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set RTS threshold of 2K bytes initially + * + * 05 18 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Ad-hoc Beacon should not carry HT OP and OBSS IEs + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 04 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Utilize status of swRfb to know channel number and band + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Different invoking order for WTBL entry of associated AP + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 04 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process Beacon only ready for infra STA now + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 24 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * fixed some WHQL testing error. + * + * 03 15 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide draft measurement and quiet functions + * + * 03 09 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * If bss is not 11n network, zero WTBL HT parameters + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 03 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Generate HT IE only depending on own phyTypeSet + * + * 03 02 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not fill HT related IE if BssInfo does not include 11n phySet + * + * 03 01 2010 tehuang.liu + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * To store field AMPDU Parameters in STA_REC + * + * 02 26 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable RDG RX, but disable RDG TX for IOT and LongNAV + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 07 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Modify the parameter of rlmRecAssocRspHtInfo function + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix prBssInfo->ucPrimaryChannel handle for assoc resp + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add some function to process HT operation + * + * Nov 28 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Call rlmStatisticsInit() to handle MIB counters + * + * Nov 18 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo); + +static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength); + +static BOOLEAN +rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +static BOOLEAN +rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength); + +static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFsmEventInit(P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Note: assume TIMER_T structures are reset to zero or stopped + * before invoking this function. + */ + + /* Initialize OBSS FSM */ + rlmObssInit(prAdapter); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainCheckCountryPowerLimitTable(prAdapter); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFsmEventUninit(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucNetIdx; + + ASSERT(prAdapter); + + RLM_NET_FOR_EACH(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + /* Note: all RLM timers will also be stopped. + * Now only one OBSS scan timer. + */ + rlmBssReset(prAdapter, prBssInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe request, association request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmReqGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#if CFG_SUPPORT_HOTSPOT_2_0 + else if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + hs20FillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateHtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillHtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateExtCapIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillExtCapIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateHtOpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11N(prBssInfo) && (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N))) + rlmFillHtOpIE(prAdapter, prBssInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief For probe response (GO, IBSS) and association response +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmRspGenerateErpIE(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + P_IE_ERP_T prErpIe; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + ASSERT(IS_NET_ACTIVE(prAdapter, prMsduInfo->ucNetworkType)); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]; + ASSERT(prBssInfo); + + if (RLM_NET_IS_11GN(prBssInfo) && prBssInfo->eBand == BAND_2G4 && + (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11GN))) { + prErpIe = (P_IE_ERP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add ERP IE */ + prErpIe->ucId = ELEM_ID_ERP_INFO; + prErpIe->ucLength = 1; + + prErpIe->ucERP = prBssInfo->fgObssErpProtectMode ? ERP_INFO_USE_PROTECTION : 0; + + if (prBssInfo->fgErpProtectMode) + prErpIe->ucERP |= (ERP_INFO_NON_ERP_PRESENT | ERP_INFO_USE_PROTECTION); + + /* Handle barker preamble */ + if (!prBssInfo->fgUseShortPreamble) + prErpIe->ucERP |= ERP_INFO_BARKER_PREAMBLE_MODE; + + ASSERT(IE_SIZE(prErpIe) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_ERP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prErpIe); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT32 +rlmFillHtCapIEByParams(BOOLEAN fg40mAllowed, + BOOLEAN fgShortGIDisabled, + UINT_8 u8SupportRxSgi20, + UINT_8 u8SupportRxSgi40, + UINT_8 u8SupportRxGf, UINT_8 u8SupportRxSTBC, ENUM_OP_MODE_T eCurrentOPMode, UINT_8 *pOutBuf) +{ + P_IE_HT_CAP_T prHtCap; + P_SUP_MCS_SET_FIELD prSupMcsSet; + + ASSERT(pOutBuf); + + prHtCap = (P_IE_HT_CAP_T) pOutBuf; + + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) { + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + } + if (fgShortGIDisabled) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + if (u8SupportRxSTBC == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_RX_STBC_1_SS); + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + return IE_SIZE(prHtCap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillHtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ + P_IE_HT_CAP_T prHtCap; +/* P_SUP_MCS_SET_FIELD prSupMcsSet; */ + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + + prHtCap = (P_IE_HT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + +#if 0 + /* Add HT capabilities IE */ + prHtCap->ucId = ELEM_ID_HT_CAP; + prHtCap->ucLength = sizeof(IE_HT_CAP_T) - ELEM_HDR_LEN; + + prHtCap->u2HtCapInfo = HT_CAP_INFO_DEFAULT_VAL; + if (!fg40mAllowed) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | + HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_DSSS_CCK_IN_40M); + if (prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M); + + if (prAdapter->rWifiVar.u8SupportRxSgi20 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_20M); + if (prAdapter->rWifiVar.u8SupportRxSgi40 == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_SHORT_GI_40M); + if (prAdapter->rWifiVar.u8SupportRxGf == 2) + prHtCap->u2HtCapInfo &= ~(HT_CAP_INFO_HT_GF); + + prHtCap->ucAmpduParam = AMPDU_PARAM_DEFAULT_VAL; + + prSupMcsSet = &prHtCap->rSupMcsSet; + kalMemZero((PVOID)&prSupMcsSet->aucRxMcsBitmask[0], SUP_MCS_RX_BITMASK_OCTET_NUM); + + prSupMcsSet->aucRxMcsBitmask[0] = BITS(0, 7); + + if (fg40mAllowed) + prSupMcsSet->aucRxMcsBitmask[32 / 8] = BIT(0); /* MCS32 */ + prSupMcsSet->u2RxHighestSupportedRate = SUP_MCS_RX_DEFAULT_HIGHEST_RATE; + prSupMcsSet->u4TxRateInfo = SUP_MCS_TX_DEFAULT_VAL; + + prHtCap->u2HtExtendedCap = HT_EXT_CAP_DEFAULT_VAL; + if (!fg40mAllowed || prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHtCap->u2HtExtendedCap &= ~(HT_EXT_CAP_PCO | HT_EXT_CAP_PCO_TRANS_TIME_NONE); + + prHtCap->u4TxBeamformingCap = TX_BEAMFORMING_CAP_DEFAULT_VAL; + + prHtCap->ucAselCap = ASEL_CAP_DEFAULT_VAL; + + ASSERT(IE_SIZE(prHtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtCap); +#else + + prMsduInfo->u2FrameLength += rlmFillHtCapIEByParams(fg40mAllowed, + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, + prAdapter->rWifiVar.u8SupportRxSgi20, + prAdapter->rWifiVar.u8SupportRxSgi40, + prAdapter->rWifiVar.u8SupportRxGf, + prAdapter->rWifiVar.u8SupportRxSTBC, + prBssInfo->eCurrentOPMode, (UINT_8 *) prHtCap); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmFillExtCapIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ +#if CFG_SUPPORT_HOTSPOT_2_0 + P_HS20_EXT_CAP_T prHsExtCap; +#else + P_EXT_CAP_T prExtCap; +#endif + BOOLEAN fg40mAllowed; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + fg40mAllowed = prBssInfo->fgAssoc40mBwAllowed; + +#if CFG_SUPPORT_HOTSPOT_2_0 + prHsExtCap = (P_HS20_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + prHsExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) + prHsExtCap->ucLength = ELEM_MAX_LEN_EXT_CAP; + else + prHsExtCap->ucLength = 3 - ELEM_HDR_LEN; + + kalMemZero(prHsExtCap->aucCapabilities, sizeof(prHsExtCap->aucCapabilities)); + + prHsExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prHsExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + if (prAdapter->prGlueInfo->fgConnectHS20AP == TRUE) { + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_INTERWORKING_BIT); + + /* For R2 WNM-Notification */ + SET_EXT_CAP(prHsExtCap->aucCapabilities, ELEM_MAX_LEN_EXT_CAP, ELEM_EXT_CAP_WNM_NOTIFICATION_BIT); + } + + ASSERT(IE_SIZE(prHsExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHsExtCap); + +#else + /* Add Extended Capabilities IE */ + prExtCap = (P_EXT_CAP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + prExtCap->ucId = ELEM_ID_EXTENDED_CAP; + + prExtCap->ucLength = 3 - ELEM_HDR_LEN; + kalMemZero(prExtCap->aucCapabilities, sizeof(prExtCap->aucCapabilities)); + + prExtCap->aucCapabilities[0] = ELEM_EXT_CAP_DEFAULT_VAL; + + if (!fg40mAllowed) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_20_40_COEXIST_SUPPORT; + + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + prExtCap->aucCapabilities[0] &= ~ELEM_EXT_CAP_PSMP_CAP; + + ASSERT(IE_SIZE(prExtCap) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_EXT_CAP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prExtCap); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT32 rlmFillHtOpIeBody(P_BSS_INFO_T prBssInfo, UINT_8 *pFme) +{ + P_IE_HT_OP_T prHtOp; + UINT_16 i; + + prHtOp = (P_IE_HT_OP_T) pFme; + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; + + /* RIFS and 20/40 bandwidth operations are included */ + prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; + + /* Decide HT protection mode field */ + if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; + } + + if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { + /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED + * Note: it will also be set in ad-hoc network + */ + prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (0 /* Regulatory class 16 */ && + prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection + * although it is possible to have no protection by spec. + */ + prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ + + /* No basic MCSx are needed temporarily */ + for (i = 0; i < 16; i++) + prHtOp->aucBasicMcsSet[i] = 0; + + return sizeof(IE_HT_OP_T); +} + +static VOID rlmFillHtOpIE(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_MSDU_INFO_T prMsduInfo) +{ +/* P_IE_HT_OP_T prHtOp; */ +/* UINT_16 i; */ + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(prMsduInfo); + + prMsduInfo->u2FrameLength += rlmFillHtOpIeBody(prBssInfo, + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength)); +#if 0 + prHtOp = (P_IE_HT_OP_T) + (((PUINT_8) prMsduInfo->prPacket) + prMsduInfo->u2FrameLength); + + /* Add HT operation IE */ + prHtOp->ucId = ELEM_ID_HT_OP; + prHtOp->ucLength = sizeof(IE_HT_OP_T) - ELEM_HDR_LEN; + + /* RIFS and 20/40 bandwidth operations are included */ + prHtOp->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prHtOp->ucInfo1 = prBssInfo->ucHtOpInfo1; + + /* Decide HT protection mode field */ + if (prBssInfo->eHtProtectMode == HT_PROTECT_MODE_NON_HT) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_HT; + else if (prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) + prHtOp->u2Info2 = (UINT_8) HT_PROTECT_MODE_NON_MEMBER; + else { + /* It may be SYS_PROTECT_MODE_NONE or SYS_PROTECT_MODE_20M */ + prHtOp->u2Info2 = (UINT_8) prBssInfo->eHtProtectMode; + } + + if (prBssInfo->eGfOperationMode != GF_MODE_NORMAL) { + /* It may be GF_MODE_PROTECT or GF_MODE_DISALLOWED + * Note: it will also be set in ad-hoc network + */ + prHtOp->u2Info2 |= HT_OP_INFO2_NON_GF_HT_STA_PRESENT; + } + + if (0 /* Regulatory class 16 */ && + prBssInfo->eObssHtProtectMode == HT_PROTECT_MODE_NON_MEMBER) { + /* (TBD) It is HT_PROTECT_MODE_NON_MEMBER, so require protection + * although it is possible to have no protection by spec. + */ + prHtOp->u2Info2 |= HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT; + } + + prHtOp->u2Info3 = prBssInfo->u2HtOpInfo3; /* To do: handle L-SIG TXOP */ + + /* No basic MCSx are needed temporarily */ + for (i = 0; i < 16; i++) + prHtOp->aucBasicMcsSet[i] = 0; + + ASSERT(IE_SIZE(prHtOp) <= (ELEM_HDR_LEN + ELEM_MAX_LEN_HT_OP)); + + prMsduInfo->u2FrameLength += IE_SIZE(prHtOp); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked to update parameters of associated AP. +* (Association response and Beacon) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 rlmRecIeInfoForClient(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, PUINT_8 pucIE, UINT_16 u2IELength) +{ + UINT_16 u2Offset; + P_STA_RECORD_T prStaRec; + P_IE_HT_CAP_T prHtCap; + P_IE_HT_OP_T prHtOp; + P_IE_OBSS_SCAN_PARAM_T prObssScnParam; + UINT_8 ucERP, ucPrimaryChannel; +#if CFG_SUPPORT_QUIET && 0 + BOOLEAN fgHasQuietIE = FALSE; +#endif + + ASSERT(prAdapter); + ASSERT(prBssInfo); + ASSERT(pucIE); + + prStaRec = prBssInfo->prStaRecOfAP; + ASSERT(prStaRec); + if (!prStaRec) + return 0; + + prBssInfo->fgUseShortPreamble = prBssInfo->fgIsShortPreambleAllowed; + ucPrimaryChannel = 0; + prObssScnParam = NULL; + + /* Note: HT-related members in staRec may not be zero before, so + * if following IE does not exist, they are still not zero. + * These HT-related parameters are valid only when the corresponding + * BssInfo supports 802.11n, i.e., RLM_NET_IS_11N() + */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + case ELEM_ID_HT_OP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPrimaryChannel == 0) + ucPrimaryChannel = prHtOp->ucPrimaryChannel; + prBssInfo->ucHtOpInfo1 = prHtOp->ucInfo1; + prBssInfo->u2HtOpInfo2 = prHtOp->u2Info2; + prBssInfo->u2HtOpInfo3 = prHtOp->u2Info3; + + if (!prBssInfo->fg40mBwAllowed) + prBssInfo->ucHtOpInfo1 &= ~(HT_OP_INFO1_SCO | HT_OP_INFO1_STA_CHNL_WIDTH); + + if ((prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) + prBssInfo->eBssSCO = (ENUM_CHNL_EXT_T)(prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_SCO); + + prBssInfo->eHtProtectMode = (ENUM_HT_PROTECT_MODE_T) + (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_HT_PROTECTION); + + /* To do: process regulatory class 16 */ + if ((prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_OBSS_NON_HT_STA_PRESENT) + && 0 /* && regulatory class is 16 */) + prBssInfo->eGfOperationMode = GF_MODE_DISALLOWED; + else if (prBssInfo->u2HtOpInfo2 & HT_OP_INFO2_NON_GF_HT_STA_PRESENT) + prBssInfo->eGfOperationMode = GF_MODE_PROTECT; + else + prBssInfo->eGfOperationMode = GF_MODE_NORMAL; + + prBssInfo->eRifsOperationMode = + (prBssInfo->ucHtOpInfo1 & HT_OP_INFO1_RIFS_MODE) ? RIFS_MODE_NORMAL : RIFS_MODE_DISALLOWED; + + break; + + case ELEM_ID_20_40_BSS_COEXISTENCE: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store if scanning exemption grant to BssInfo */ + break; + + case ELEM_ID_OBSS_SCAN_PARAMS: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_OBSS_SCAN_PARAM_T) - 2)) + break; + /* Store OBSS parameters to BssInfo */ + prObssScnParam = (P_IE_OBSS_SCAN_PARAM_T) pucIE; + break; + + case ELEM_ID_EXTENDED_CAP: + if (!RLM_NET_IS_11N(prBssInfo)) + break; + /* To do: store extended capability (PSMP, coexist) to BssInfo */ + break; + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) != (sizeof(IE_ERP_T) - 2) || prBssInfo->eBand != BAND_2G4) + break; + ucERP = ERP_INFO_IE(pucIE)->ucERP; + prBssInfo->fgErpProtectMode = (ucERP & ERP_INFO_USE_PROTECTION) ? TRUE : FALSE; + + if (ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucPrimaryChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + +#if CFG_SUPPORT_DFS /* Add by Enlai */ + case ELEM_ID_CH_SW_ANNOUNCEMENT: + { + rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) pucIE); + } + break; + +#if CFG_SUPPORT_QUIET && 0 + /* Note: RRM code should be moved to independent RRM function by + * component design rule. But we attach it to RLM temporarily + */ + case ELEM_ID_QUIET: + rrmQuietHandleQuietIE(prBssInfo, (P_IE_QUIET_T) pucIE); + fgHasQuietIE = TRUE; + break; +#endif +#endif + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ + + /* Some AP will have wrong channel number (255) when running time. + * Check if correct channel number information. 20110501 + */ + if ((prBssInfo->eBand == BAND_2G4 && ucPrimaryChannel > 14) || + (prBssInfo->eBand != BAND_2G4 && (ucPrimaryChannel >= 200 || ucPrimaryChannel <= 14))) + ucPrimaryChannel = 0; +#if CFG_SUPPORT_QUIET && 0 + if (!fgHasQuietIE) + rrmQuietIeNotExist(prAdapter, prBssInfo); +#endif + + /* Check if OBSS scan process will launch */ + if (!prAdapter->fgEnOnlineScan || !prObssScnParam || + !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH) || + prBssInfo->eBand != BAND_2G4 || !prBssInfo->fg40mBwAllowed) { + + /* Note: it is ok not to stop rObssScanTimer() here */ + prBssInfo->u2ObssScanInterval = 0; + } else { + if (prObssScnParam->u2TriggerScanInterval < OBSS_SCAN_MIN_INTERVAL) + prObssScnParam->u2TriggerScanInterval = OBSS_SCAN_MIN_INTERVAL; + if (prBssInfo->u2ObssScanInterval != prObssScnParam->u2TriggerScanInterval) { + + prBssInfo->u2ObssScanInterval = prObssScnParam->u2TriggerScanInterval; + + /* Start timer to trigger OBSS scanning */ + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, + prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } + } + + return ucPrimaryChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnFromNeighborForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + UINT_16 u2Offset, i; + UINT_8 ucPriChannel, ucSecChannel; + ENUM_CHNL_EXT_T eSCO; + BOOLEAN fgHtBss, fg20mReq; + + if ((prAdapter == NULL) + || (pucIE == NULL) + || (prBssInfo == NULL) + || (prSwRfb == NULL)) { + ASSERT(FALSE); + return FALSE; + } + + /* Record it to channel list to change 20/40 bandwidth */ + ucPriChannel = 0; + eSCO = CHNL_EXT_SCN; + + fgHtBss = FALSE; + fg20mReq = FALSE; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + { + P_IE_HT_CAP_T prHtCap; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + + prHtCap = (P_IE_HT_CAP_T) pucIE; + if (prHtCap->u2HtCapInfo & HT_CAP_INFO_40M_INTOLERANT) + fg20mReq = TRUE; + fgHtBss = TRUE; + break; + } + case ELEM_ID_HT_OP: + { + P_IE_HT_OP_T prHtOp; + + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + + prHtOp = (P_IE_HT_OP_T) pucIE; + /* Workaround that some APs fill primary channel field by its + * secondary channel, but its DS IE is correct 20110610 + */ + if (ucPriChannel == 0) + ucPriChannel = prHtOp->ucPrimaryChannel; + + if ((prHtOp->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) + eSCO = (ENUM_CHNL_EXT_T) (prHtOp->ucInfo1 & HT_OP_INFO1_SCO); + break; + } + case ELEM_ID_20_40_BSS_COEXISTENCE: + { + P_IE_20_40_COEXIST_T prCoexist; + + if (IE_LEN(pucIE) != (sizeof(IE_20_40_COEXIST_T) - 2)) + break; + + prCoexist = (P_IE_20_40_COEXIST_T) pucIE; + if (prCoexist->ucData & BSS_COEXIST_40M_INTOLERANT) + fg20mReq = TRUE; + break; + } + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) != (sizeof(IE_DS_PARAM_SET_T) - 2)) + break; + ucPriChannel = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + + default: + break; + } + } + + /* To do: Update channel list and 5G band. All channel lists have the same + * update procedure. We should give it the entry pointer of desired + * channel list. + */ + if (HIF_RX_HDR_GET_RF_BAND(prSwRfb->prHifRxHdr) != BAND_2G4) + return FALSE; + + if (ucPriChannel == 0 || ucPriChannel > 14) + ucPriChannel = HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr); + + if (fgHtBss) { + ASSERT(prBssInfo->auc2G_PriChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_PriChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_PriChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_PriChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_PriChnlList[i] = ucPriChannel; + prBssInfo->auc2G_PriChnlList[0]++; + } + + /* Update secondary channel */ + if (eSCO != CHNL_EXT_SCN) { + ucSecChannel = (eSCO == CHNL_EXT_SCA) ? (ucPriChannel + 4) : (ucPriChannel - 4); + + ASSERT(prBssInfo->auc2G_SecChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_SecChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_SecChnlList[i] == ucSecChannel) + break; + } + if ((i > prBssInfo->auc2G_SecChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_SecChnlList[i] = ucSecChannel; + prBssInfo->auc2G_SecChnlList[0]++; + } + } + + /* Update 20M bandwidth request channels */ + if (fg20mReq) { + ASSERT(prBssInfo->auc2G_20mReqChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_20mReqChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_20mReqChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_20mReqChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_20mReqChnlList[i] = ucPriChannel; + prBssInfo->auc2G_20mReqChnlList[0]++; + } + } + } else { + /* Update non-HT channel list */ + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + for (i = 1; i <= prBssInfo->auc2G_NonHtChnlList[0] && i <= CHNL_LIST_SZ_2G; i++) { + if (prBssInfo->auc2G_NonHtChnlList[i] == ucPriChannel) + break; + } + if ((i > prBssInfo->auc2G_NonHtChnlList[0]) && (i <= CHNL_LIST_SZ_2G)) { + prBssInfo->auc2G_NonHtChnlList[i] = ucPriChannel; + prBssInfo->auc2G_NonHtChnlList[0]++; + } + + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief AIS or P2P GC. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN +rlmRecBcnInfoForClient(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + if ((prAdapter == NULL) + || (pucIE == NULL) + || (prBssInfo == NULL) + || (prSwRfb == NULL)) { + ASSERT(FALSE); + return FALSE; + } + +#if 0 /* SW migration 2010/8/20 */ + /* Note: we shall not update parameters when scanning, otherwise + * channel and bandwidth will not be correct or asserted failure + * during scanning. + * Note: remove channel checking. All received Beacons should be processed + * if measurement or other actions are executed in adjacent channels + * and Beacon content checking mechanism is not disabled. + */ + if (IS_SCAN_ACTIVE() + /* || prBssInfo->ucPrimaryChannel != CHNL_NUM_BY_SWRFB(prSwRfb) */ + ) { + return FALSE; + } +#endif + + /* Handle change of slot time */ + prBssInfo->u2CapInfo = ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->u2CapInfo; + prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessBcn(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + BOOLEAN fgNewParameter; + UINT_8 ucNetIdx; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + fgNewParameter = FALSE; + + /* When concurrent networks exist, GO shall have the same handle as + * the other BSS, so the Beacon shall be processed for bandwidth and + * protection mechanism. + * Note1: we do not have 2 AP (GO) cases simultaneously now. + * Note2: If we are GO, concurrent AIS AP should detect it and reflect + * action in its Beacon, so AIS STA just follows Beacon from AP. + */ + RLM_NET_FOR_EACH_NO_BOW(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && + prBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* P2P client or AIS infra STA */ + if (EQUAL_MAC_ADDR(prBssInfo->aucBSSID, ((P_WLAN_MAC_MGMT_HEADER_T) + (prSwRfb->pvHeader))->aucBSSID)) { + + fgNewParameter = rlmRecBcnInfoForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, u2IELength); + } else { + fgNewParameter = rlmRecBcnFromNeighborForClient(prAdapter, + prBssInfo, prSwRfb, pucIE, + u2IELength); + } + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT || + prBssInfo->eCurrentOPMode == OP_MODE_P2P_DEVICE)) { + /* AP scan to check if 20/40M bandwidth is permitted */ + rlmRecBcnFromNeighborForClient(prAdapter, prBssInfo, prSwRfb, pucIE, u2IELength); + } +#endif + else if (prBssInfo->eCurrentOPMode == OP_MODE_IBSS) { + /* Do nothing */ + /* To do: Ad-hoc */ + } + + /* Appy new parameters if necessary */ + if (fgNewParameter) { + DBGLOG(RLM, TRACE, "rlmProcessBcn\n"); + rlmSyncOperationParams(prAdapter, prBssInfo); + fgNewParameter = FALSE; + } + } /* end of IS_BSS_ACTIVE() */ + } /* end of RLM_NET_FOR_EACH_NO_BOW */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessAssocRsp(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_8 ucPriChannel; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) + return; + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prStaRec == prBssInfo->prStaRecOfAP); + + /* To do: the invoked function is used to clear all members. It may be + * done by center mechanism in invoker. + */ + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fgUseShortSlotTime = (prBssInfo->u2CapInfo & CAP_INFO_SHORT_SLOT_TIME) ? TRUE : FALSE; + + ucPriChannel = rlmRecIeInfoForClient(prAdapter, prBssInfo, pucIE, u2IELength); + if (ucPriChannel > 0) + prBssInfo->ucPrimaryChannel = ucPriChannel; + + if (!RLM_NET_IS_11N(prBssInfo) || !(prStaRec->u2HtCapInfo & HT_CAP_INFO_SUP_CHNL_WIDTH)) + prBssInfo->fg40mBwAllowed = FALSE; + + /* Note: Update its capabilities to WTBL by cnmStaRecChangeState(), which + * shall be invoked afterwards. + * Update channel, bandwidth and protection mode by nicUpdateBss() + */ +#if 1 + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + + DBGLOG(P2P, WARN, "Force P2P BW to 20\n"); + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmFillSyncCmdParam(P_CMD_SET_BSS_RLM_PARAM_T prCmdBody, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prCmdBody && prBssInfo); + if (!prCmdBody || !prBssInfo) + return; + + prCmdBody->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prCmdBody->ucRfBand = (UINT_8) prBssInfo->eBand; + prCmdBody->ucPrimaryChannel = prBssInfo->ucPrimaryChannel; + prCmdBody->ucRfSco = (UINT_8) prBssInfo->eBssSCO; + prCmdBody->ucErpProtectMode = (UINT_8) prBssInfo->fgErpProtectMode; + prCmdBody->ucHtProtectMode = (UINT_8) prBssInfo->eHtProtectMode; + prCmdBody->ucGfOperationMode = (UINT_8) prBssInfo->eGfOperationMode; + prCmdBody->ucTxRifsMode = (UINT_8) prBssInfo->eRifsOperationMode; + prCmdBody->u2HtOpInfo3 = prBssInfo->u2HtOpInfo3; + prCmdBody->u2HtOpInfo2 = prBssInfo->u2HtOpInfo2; + prCmdBody->ucHtOpInfo1 = prBssInfo->ucHtOpInfo1; + prCmdBody->ucUseShortPreamble = prBssInfo->fgUseShortPreamble; + prCmdBody->ucUseShortSlotTime = prBssInfo->fgUseShortSlotTime; + prCmdBody->ucCheckId = 0x72; + + if (RLM_NET_PARAM_VALID(prBssInfo)) { + DBGLOG(RLM, INFO, "N=%d b=%d c=%d s=%d e=%d h=%d I=0x%02x l=%d p=%d\n", + prCmdBody->ucNetTypeIndex, prCmdBody->ucRfBand, + prCmdBody->ucPrimaryChannel, prCmdBody->ucRfSco, + prCmdBody->ucErpProtectMode, prCmdBody->ucHtProtectMode, + prCmdBody->ucHtOpInfo1, prCmdBody->ucUseShortSlotTime, + prCmdBody->ucUseShortPreamble); + } else { + DBGLOG(RLM, TRACE, "N=%d closed\n", prCmdBody->ucNetTypeIndex); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will operation parameters based on situations of +* concurrent networks. Channel, bandwidth, protection mode, supported +* rate will be modified. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmSyncOperationParams(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_CMD_SET_BSS_RLM_PARAM_T prCmdBody; + WLAN_STATUS rStatus; + + ASSERT(prAdapter); + ASSERT(prBssInfo); + + prCmdBody = (P_CMD_SET_BSS_RLM_PARAM_T) + cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_BSS_RLM_PARAM_T)); + ASSERT(prCmdBody); + + /* To do: exception handle */ + if (!prCmdBody) { + DBGLOG(RLM, WARN, "No buf for sync RLM params (Net=%d)\n", prBssInfo->ucNetTypeIndex); + return; + } + + rlmFillSyncCmdParam(prCmdBody, prBssInfo); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_BSS_RLM_PARAM, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_BSS_RLM_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdBody, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + + cnmMemFree(prAdapter, prCmdBody); +} + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function should be invoked after judging successful association. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessAssocReq(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb, PUINT_8 pucIE, UINT_16 u2IELength) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + P_IE_HT_CAP_T prHtCap; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (!prStaRec) + return; + ASSERT(prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_HT_CAP: + if (!RLM_NET_IS_11N(prBssInfo) || IE_LEN(pucIE) != (sizeof(IE_HT_CAP_T) - 2)) + break; + prHtCap = (P_IE_HT_CAP_T) pucIE; + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + break; + + default: + break; + } /* end of switch */ + } /* end of IE_FOR_EACH */ +} +#endif /* CFG_SUPPORT_AAA */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssInitForAPandIbss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) + rlmBssInitForAP(prAdapter, prBssInfo); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief It is for both STA and AP modes +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmBssAborted(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + rlmBssReset(prAdapter, prBssInfo); + + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + + /* Assume FW state is updated by CMD_ID_SET_BSS_INFO, so + * the sync CMD is not needed here. + */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief All RLM timers will also be stopped. +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmBssReset(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + ASSERT(prAdapter); + ASSERT(prBssInfo); + + /* HT related parameters */ + prBssInfo->ucHtOpInfo1 = 0; /* RIFS disabled. 20MHz */ + prBssInfo->u2HtOpInfo2 = 0; + prBssInfo->u2HtOpInfo3 = 0; + + prBssInfo->eBssSCO = 0; + prBssInfo->fgErpProtectMode = 0; + prBssInfo->eHtProtectMode = 0; + prBssInfo->eGfOperationMode = 0; + prBssInfo->eRifsOperationMode = 0; + + /* OBSS related parameters */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + prBssInfo->auc2G_PriChnlList[0] = 0; + prBssInfo->auc2G_SecChnlList[0] = 0; + prBssInfo->auc5G_20mReqChnlList[0] = 0; + prBssInfo->auc5G_NonHtChnlList[0] = 0; + prBssInfo->auc5G_PriChnlList[0] = 0; + prBssInfo->auc5G_SecChnlList[0] = 0; + + /* All RLM timers will also be stopped */ + cnmTimerStopTimer(prAdapter, &prBssInfo->rObssScanTimer); + prBssInfo->u2ObssScanInterval = 0; + + prBssInfo->fgObssErpProtectMode = 0; /* GO only */ + prBssInfo->eObssHtProtectMode = 0; /* GO only */ + prBssInfo->eObssGfOperationMode = 0; /* GO only */ + prBssInfo->fgObssRifsOperationMode = 0; /* GO only */ + prBssInfo->fgObssActionForcedTo20M = 0; /* GO only */ + prBssInfo->fgObssBeaconForcedTo20M = 0; /* GO only */ +} + +#if CFG_SUPPORT_DFS /* Add by Enlai */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function handle spectrum management action frame +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessSpecMgtAction(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + P_ACTION_CHANNEL_SWITCH_FRAME prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + DBGLOG(RLM, INFO, "[5G DFS]rlmProcessSpecMgtAction \r\n"); + + prRxFrame = (P_ACTION_CHANNEL_SWITCH_FRAME) prSwRfb->pvHeader; + DBGLOG(RLM, INFO, "[5G DFS]prRxFrame->ucAction[%d] \r\n", prRxFrame->ucAction); + if (prRxFrame->ucAction == ACTION_CHNL_SWITCH) + rlmProcessChannelSwitchIE(prAdapter, (P_IE_CHANNEL_SWITCH_T) prRxFrame->aucInfoElem); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function process Channel Switch IE +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmProcessChannelSwitchIE(P_ADAPTER_T prAdapter, P_IE_CHANNEL_SWITCH_T prChannelSwitchIE) +{ + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + ASSERT(prChannelSwitchIE); + + DBGLOG(RLM, INFO, "[5G DFS] rlmProcessChannelSwitchIE \r\n"); + DBGLOG(RLM, INFO, "[5G DFS] ucChannelSwitchMode[%d], ucChannelSwitchCount[%d], ucNewChannelNum[%d] \r\n", + prChannelSwitchIE->ucChannelSwitchMode, + prChannelSwitchIE->ucChannelSwitchCount, prChannelSwitchIE->ucNewChannelNum); + if (prChannelSwitchIE->ucChannelSwitchMode == 1) { + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + DBGLOG(RLM, INFO, "[5G DFS] switch channel [%d]->[%d] \r\n", prAisBssInfo->ucPrimaryChannel, + prChannelSwitchIE->ucNewChannelNum); + prAisBssInfo->ucPrimaryChannel = prChannelSwitchIE->ucNewChannelNum; + nicUpdateBss(prAdapter, prAisBssInfo->ucNetTypeIndex); + } + +} + +#endif + +#if (CFG_SUPPORT_TXR_ENC == 1) +VOID +rlmTxRateEnhanceConfig( + P_ADAPTER_T prAdapter + ) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_RLM_INFO_T rTxRInfo; + UINT_32 u4SetInfoLen = 0; + + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + + /* suggestion from Tsaiyuan.Hsu */ + kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); + rTxRInfo.fgIsErrRatioEnhanceApplied = TRUE; + rTxRInfo.ucErrRatio2LimitMinRate = 3; + rTxRInfo.ucMinLegacyRateIdx = 2; + rTxRInfo.cMinRssiThreshold = -60; + rTxRInfo.fgIsRtsApplied = TRUE; + rTxRInfo.ucRecoverTime = 60; + + DBGLOG(RLM, INFO, "Enable tx rate enhance function\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxRateInfo, + &rTxRInfo, + sizeof(rTxRInfo), + TRUE, + TRUE, + TRUE, + FALSE, + &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(RLM, WARN, "set tx rate advance info fail 0x%lx\n", rStatus); +} + + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TX Auto Rate module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_32 u4Subcmd; + + + /* parse TAR sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(RLM, INFO, " sub command = %u\n", (UINT32)u4Subcmd); + + /* handle different sub-command */ + switch (u4Subcmd) { + case 0x00: /* configure */ + /* iwpriv wlan0 set_str_cmd 1_0_0_1_3_2_60_1_60 */ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_RLM_INFO_T rTxRInfo; + UINT_32 u4SetInfoLen = 0; + + kalMemZero(&rTxRInfo, sizeof(CMD_RLM_INFO_T)); + rTxRInfo.u4Version = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.fgIsErrRatioEnhanceApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucErrRatio2LimitMinRate = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucMinLegacyRateIdx = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.cMinRssiThreshold = 0 - CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.fgIsRtsApplied = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rTxRInfo.ucRecoverTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(RLM, INFO, " rlmCmd = %u %u %u %u %d %u %u\n", + rTxRInfo.u4Version, + rTxRInfo.fgIsErrRatioEnhanceApplied, + rTxRInfo.ucErrRatio2LimitMinRate, + rTxRInfo.ucMinLegacyRateIdx, + rTxRInfo.cMinRssiThreshold, + rTxRInfo.fgIsRtsApplied, + rTxRInfo.ucRecoverTime)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxRateInfo, + &rTxRInfo, + sizeof(rTxRInfo), + TRUE, + TRUE, + TRUE, + FALSE, + &u4SetInfoLen); + break; + + default: + break; + } +} +#endif /* CFG_SUPPORT_TXR_ENC */ + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c new file mode 100644 index 0000000000000..5e127488ea499 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_domain.c @@ -0,0 +1,1791 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_domain.c#1 +*/ + +/*! \file "rlm_domain.c" + \brief + +*/ + +/* +** Log: rlm_domain.c + * + * 11 10 2011 cm.chang + * NULL + * Modify debug message for XLOG + * + * 09 29 2011 cm.chang + * NULL + * Change the function prototype of rlmDomainGetChnlList() + * + * 09 23 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Let channel number to zero if band is illegal + * + * 09 22 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Exclude channel list with illegal band + * + * 09 15 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use defined country group to have a change to add new group + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 06 01 2011 cm.chang + * [WCXRP00000756] [MT6620 Wi-Fi][Driver] 1. AIS follow channel of BOW 2. Provide legal channel function + * Provide legal channel function based on domain + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 02 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Export rlmDomainGetDomainInfo for p2p driver. + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 03 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Filter out not supported RF freq when reporting available chnl list + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Provide query function about full channel list. + * + * Dec 1 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" +#include "rlm_txpwr_init.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* The following country or domain shall be set from host driver. + * And host driver should pass specified DOMAIN_INFO_ENTRY to MT6620 as + * the channel list of being a STA to do scanning/searching AP or being an + * AP to choose an adequate channel if auto-channel is set. + */ + +/* Define mapping tables between country code and its channel set + */ +static const UINT_16 g_u2CountryGroup0[] = { + COUNTRY_CODE_AO, COUNTRY_CODE_BZ, COUNTRY_CODE_BJ, COUNTRY_CODE_BT, + COUNTRY_CODE_BO, COUNTRY_CODE_BI, COUNTRY_CODE_CM, COUNTRY_CODE_CF, + COUNTRY_CODE_TD, COUNTRY_CODE_KM, COUNTRY_CODE_CD, COUNTRY_CODE_CG, + COUNTRY_CODE_CI, COUNTRY_CODE_DJ, COUNTRY_CODE_GQ, COUNTRY_CODE_ER, + COUNTRY_CODE_FJ, COUNTRY_CODE_GA, COUNTRY_CODE_GM, COUNTRY_CODE_GN, + COUNTRY_CODE_GW, COUNTRY_CODE_RKS, COUNTRY_CODE_KG, COUNTRY_CODE_LY, + COUNTRY_CODE_MG, COUNTRY_CODE_ML, COUNTRY_CODE_NR, COUNTRY_CODE_NC, + COUNTRY_CODE_ST, COUNTRY_CODE_SC, COUNTRY_CODE_SL, COUNTRY_CODE_SB, + COUNTRY_CODE_SO, COUNTRY_CODE_SR, COUNTRY_CODE_SZ, COUNTRY_CODE_TJ, + COUNTRY_CODE_TG, COUNTRY_CODE_TO, COUNTRY_CODE_TM, COUNTRY_CODE_TV, + COUNTRY_CODE_VU, COUNTRY_CODE_YE +}; + +static const UINT_16 g_u2CountryGroup1[] = { + COUNTRY_CODE_AS, COUNTRY_CODE_AI, COUNTRY_CODE_BM, COUNTRY_CODE_CA, + COUNTRY_CODE_KY, COUNTRY_CODE_GU, COUNTRY_CODE_FM, COUNTRY_CODE_PR, + COUNTRY_CODE_US, COUNTRY_CODE_VI +}; + +static const UINT_16 g_u2CountryGroup2[] = { + COUNTRY_CODE_AR, COUNTRY_CODE_AU, COUNTRY_CODE_AZ, COUNTRY_CODE_BW, + COUNTRY_CODE_KH, COUNTRY_CODE_CX, COUNTRY_CODE_CO, COUNTRY_CODE_CR, +#if (CFG_CN_SUPPORT_CLASS121 == 1) + COUNTRY_CODE_CN, +#endif + COUNTRY_CODE_EC, COUNTRY_CODE_GD, COUNTRY_CODE_GT, COUNTRY_CODE_HK, + COUNTRY_CODE_KI, COUNTRY_CODE_LB, COUNTRY_CODE_LR, COUNTRY_CODE_MN, + COUNTRY_CODE_AN, COUNTRY_CODE_NZ, COUNTRY_CODE_NI, COUNTRY_CODE_PW, + COUNTRY_CODE_PY, COUNTRY_CODE_PE, COUNTRY_CODE_PH, COUNTRY_CODE_WS, + COUNTRY_CODE_SG, COUNTRY_CODE_LK, COUNTRY_CODE_TH, COUNTRY_CODE_TT, + COUNTRY_CODE_UY, COUNTRY_CODE_VN +}; + +static const UINT_16 g_u2CountryGroup3[] = { + COUNTRY_CODE_AW, COUNTRY_CODE_LA, COUNTRY_CODE_SA, COUNTRY_CODE_AE, + COUNTRY_CODE_UG +}; + +static const UINT_16 g_u2CountryGroup4[] = { COUNTRY_CODE_MM }; + +static const UINT_16 g_u2CountryGroup5[] = { + COUNTRY_CODE_AL, COUNTRY_CODE_DZ, COUNTRY_CODE_AD, COUNTRY_CODE_AT, + COUNTRY_CODE_BY, COUNTRY_CODE_BE, COUNTRY_CODE_BA, COUNTRY_CODE_VG, + COUNTRY_CODE_BG, COUNTRY_CODE_CV, COUNTRY_CODE_HR, COUNTRY_CODE_CY, + COUNTRY_CODE_CZ, COUNTRY_CODE_DK, COUNTRY_CODE_EE, COUNTRY_CODE_ET, + COUNTRY_CODE_FI, COUNTRY_CODE_FR, COUNTRY_CODE_GF, COUNTRY_CODE_PF, + COUNTRY_CODE_TF, COUNTRY_CODE_GE, COUNTRY_CODE_DE, COUNTRY_CODE_GH, + COUNTRY_CODE_GR, COUNTRY_CODE_GP, COUNTRY_CODE_HU, COUNTRY_CODE_IS, + COUNTRY_CODE_IQ, COUNTRY_CODE_IE, COUNTRY_CODE_IT, COUNTRY_CODE_KE, + COUNTRY_CODE_LV, COUNTRY_CODE_LS, COUNTRY_CODE_LI, COUNTRY_CODE_LT, + COUNTRY_CODE_LU, COUNTRY_CODE_MK, COUNTRY_CODE_MT, COUNTRY_CODE_MQ, + COUNTRY_CODE_MR, COUNTRY_CODE_MU, COUNTRY_CODE_YT, COUNTRY_CODE_MD, + COUNTRY_CODE_MC, COUNTRY_CODE_ME, COUNTRY_CODE_MS, COUNTRY_CODE_NL, + COUNTRY_CODE_NO, COUNTRY_CODE_OM, COUNTRY_CODE_PL, COUNTRY_CODE_PT, + COUNTRY_CODE_RE, COUNTRY_CODE_RO, COUNTRY_CODE_MF, COUNTRY_CODE_SM, + COUNTRY_CODE_SN, COUNTRY_CODE_RS, COUNTRY_CODE_SK, COUNTRY_CODE_SI, + COUNTRY_CODE_ZA, COUNTRY_CODE_ES, COUNTRY_CODE_SE, COUNTRY_CODE_CH, + COUNTRY_CODE_TR, COUNTRY_CODE_TC, COUNTRY_CODE_GB, COUNTRY_CODE_VA, + COUNTRY_CODE_EU +}; + +static const UINT_16 g_u2CountryGroup6[] = { COUNTRY_CODE_JP }; + +static const UINT_16 g_u2CountryGroup7[] = { + COUNTRY_CODE_AM, COUNTRY_CODE_IL, COUNTRY_CODE_KW, COUNTRY_CODE_MA, + COUNTRY_CODE_NE, COUNTRY_CODE_TN, COUNTRY_CODE_MA +}; + +static const UINT_16 g_u2CountryGroup8[] = { COUNTRY_CODE_NP }; + +static const UINT_16 g_u2CountryGroup9[] = { COUNTRY_CODE_AF }; + +static const UINT_16 g_u2CountryGroup10[] = { + COUNTRY_CODE_AG, COUNTRY_CODE_BS, COUNTRY_CODE_BH, COUNTRY_CODE_BB, + COUNTRY_CODE_BN, COUNTRY_CODE_CL, COUNTRY_CODE_EG, +#if (CFG_CN_SUPPORT_CLASS121 == 0) + COUNTRY_CODE_CN, +#endif + COUNTRY_CODE_SV, COUNTRY_CODE_IN, COUNTRY_CODE_MY, COUNTRY_CODE_MV, + COUNTRY_CODE_PA, COUNTRY_CODE_VE, COUNTRY_CODE_ZM +}; + +static const UINT_16 g_u2CountryGroup11[] = { COUNTRY_CODE_JO, COUNTRY_CODE_PG }; + +static const UINT_16 g_u2CountryGroup12[] = { + COUNTRY_CODE_BF, COUNTRY_CODE_GY, COUNTRY_CODE_HT, COUNTRY_CODE_HN, + COUNTRY_CODE_JM, COUNTRY_CODE_MO, COUNTRY_CODE_MW, COUNTRY_CODE_PK, + COUNTRY_CODE_QA, COUNTRY_CODE_RW, COUNTRY_CODE_KN, COUNTRY_CODE_TZ +}; + +static const UINT_16 g_u2CountryGroup13[] = { COUNTRY_CODE_ID }; + +static const UINT_16 g_u2CountryGroup14[] = { COUNTRY_CODE_KR }; + +static const UINT_16 g_u2CountryGroup15[] = { COUNTRY_CODE_NG }; + +static const UINT_16 g_u2CountryGroup16[] = { + COUNTRY_CODE_BD, COUNTRY_CODE_BR, COUNTRY_CODE_DM, COUNTRY_CODE_DO, + COUNTRY_CODE_FK, COUNTRY_CODE_KZ, COUNTRY_CODE_MX, COUNTRY_CODE_MZ, + COUNTRY_CODE_NA, COUNTRY_CODE_RU, COUNTRY_CODE_LC, COUNTRY_CODE_VC, + COUNTRY_CODE_UA, COUNTRY_CODE_UZ, COUNTRY_CODE_ZW +}; + +static const UINT_16 g_u2CountryGroup17[] = { COUNTRY_CODE_MP }; + +static const UINT_16 g_u2CountryGroup18[] = { COUNTRY_CODE_TW }; + +static const UINT_16 g_u2CountryGroup19[] = { + COUNTRY_CODE_CK, COUNTRY_CODE_CU, COUNTRY_CODE_TL, COUNTRY_CODE_FO, + COUNTRY_CODE_GI, COUNTRY_CODE_GG, COUNTRY_CODE_IR, COUNTRY_CODE_IM, + COUNTRY_CODE_JE, COUNTRY_CODE_KP, COUNTRY_CODE_MH, COUNTRY_CODE_NU, + COUNTRY_CODE_NF, COUNTRY_CODE_PS, COUNTRY_CODE_PN, COUNTRY_CODE_PM, + COUNTRY_CODE_SS, COUNTRY_CODE_SD, COUNTRY_CODE_SY +}; + +static const UINT_16 g_u2CountryGroup20[] = { + COUNTRY_CODE_DF, COUNTRY_CODE_FF + /* When country code is not found and no matched NVRAM setting, + * this domain info will be used. + */ +}; + +static const UINT_16 g_u2CountryGroup21[] = { + COUNTRY_CODE_UDF +}; + +DOMAIN_INFO_ENTRY arSupportedRegDomains[] = { + { + (PUINT_16) g_u2CountryGroup0, sizeof(g_u2CountryGroup0) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup1, sizeof(g_u2CountryGroup1) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup2, sizeof(g_u2CountryGroup2) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup3, sizeof(g_u2CountryGroup3) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup4, sizeof(g_u2CountryGroup4) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup5, sizeof(g_u2CountryGroup5) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup6, sizeof(g_u2CountryGroup6) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + {82, BAND_2G4, CHNL_SPAN_5, 14, 1, FALSE} + , /* CH_SET_2G4_14_14 */ + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + } + } + , + { + (PUINT_16) g_u2CountryGroup7, sizeof(g_u2CountryGroup7) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup8, sizeof(g_u2CountryGroup8) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup9, sizeof(g_u2CountryGroup9) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_UPPER_NA */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup10, sizeof(g_u2CountryGroup10) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup11, sizeof(g_u2CountryGroup11) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup12, sizeof(g_u2CountryGroup12) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup13, sizeof(g_u2CountryGroup13) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_NA */ + {118, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_MID_NA */ + {121, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_WW_NA */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup14, sizeof(g_u2CountryGroup14) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 8, FALSE} + , /* CH_SET_UNII_WW_100_128 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 4, FALSE} + , /* CH_SET_UNII_UPPER_149_161 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup15, sizeof(g_u2CountryGroup15) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_NULL, 0, 0, 0, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup16, sizeof(g_u2CountryGroup16) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup17, sizeof(g_u2CountryGroup17) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, TRUE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup18, sizeof(g_u2CountryGroup18) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 11, FALSE} + , /* CH_SET_2G4_1_11 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, FALSE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 11, FALSE} + , /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + (PUINT_16) g_u2CountryGroup19, sizeof(g_u2CountryGroup19) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: Default group if no matched country code */ + (PUINT_16) g_u2CountryGroup20, sizeof(g_u2CountryGroup20) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 13, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 4, FALSE} + , /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 4, TRUE} + , /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 12, TRUE} + , /* CH_SET_UNII_WW_100_144 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 5, FALSE} + , /* CH_SET_UNII_UPPER_149_165 */ + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } + , + { + /* Note: for customer configured their own scanning list and passive scan list */ + (PUINT_16) g_u2CountryGroup21, sizeof(g_u2CountryGroup21) / 2, + { + {81, BAND_2G4, CHNL_SPAN_5, 1, 12, FALSE} + , /* CH_SET_2G4_1_13 */ + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, FALSE} + , + {118, BAND_5G, CHNL_SPAN_20, 52, 0, FALSE} + , + {121, BAND_5G, CHNL_SPAN_20, 100, 0, FALSE} + , + {125, BAND_5G, CHNL_SPAN_20, 149, 0, FALSE} + , + {0, BAND_NULL, 0, 0, 0, FALSE} + } + } +}; + +static UINT_16 g_u2CountryGroup0_Passive[] = { + COUNTRY_CODE_UDF +}; + +DOMAIN_INFO_ENTRY arSupportedRegDomains_Passive[] = { + { + /* Default passive scan channel table is empty */ + COUNTRY_CODE_NULL, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 11, 0, 0}, /* CH_SET_2G4_1_14 */ + {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ + } + }, + { + /* User Defined passive scan channel table */ + g_u2CountryGroup0_Passive, 0, + { + {81, BAND_2G4, CHNL_SPAN_5, 12, 1, 0}, /* CH_SET_2G4_1_14 */ + {82, BAND_2G4, CHNL_SPAN_5, 5, 0, 0}, + + {115, BAND_5G, CHNL_SPAN_20, 36, 0, 0}, /* CH_SET_UNII_LOW_36_48 */ + {118, BAND_5G, CHNL_SPAN_20, 52, 0, 0}, /* CH_SET_UNII_MID_52_64 */ + {121, BAND_5G, CHNL_SPAN_20, 100, 0, 0}, /* CH_SET_UNII_WW_100_140 */ + {125, BAND_5G, CHNL_SPAN_20, 149, 0, 0}, /* CH_SET_UNII_UPPER_149_173 */ + } + } +}; + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY +SUBBAND_CHANNEL_T g_rRlmSubBand[] = { + + {BAND_2G4_LOWER_BOUND, BAND_2G4_UPPER_BOUND, 1, 0} + , /* 2.4G */ + {UNII1_LOWER_BOUND, UNII1_UPPER_BOUND, 2, 0} + , /* ch36,38,40,..,48 */ + {UNII2A_LOWER_BOUND, UNII2A_UPPER_BOUND, 2, 0} + , /* ch52,54,56,..,64 */ + {UNII2C_LOWER_BOUND, UNII2C_UPPER_BOUND, 2, 0} + , /* ch100,102,104,...,144 */ + {UNII3_LOWER_BOUND, UNII3_UPPER_BOUND, 2, 0} + /* ch149,151,153,....,173 */ +}; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +P_DOMAIN_INFO_ENTRY rlmDomainGetDomainInfo(P_ADAPTER_T prAdapter) +{ +#define REG_DOMAIN_DEF_IDX 20 /* Default country domain */ +#define REG_DOMAIN_GROUP_NUM \ + (sizeof(arSupportedRegDomains) / sizeof(DOMAIN_INFO_ENTRY)) + + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_REG_INFO_T prRegInfo; + UINT_16 u2TargetCountryCode; + UINT_16 i, j; + + ASSERT(prAdapter); + + if (prAdapter->prDomainInfo) + return prAdapter->prDomainInfo; + + prRegInfo = &prAdapter->prGlueInfo->rRegInfo; + + DBGLOG(RLM, TRACE, "eRegChannelListMap=%d, u2CountryCode=0x%04x\n", + prRegInfo->eRegChannelListMap, + prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + /* + * Domain info can be specified by given idx of arSupportedRegDomains table, + * customized, or searched by country code, + * only one is set among these three methods in NVRAM. + */ + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_TBL_IDX && + prRegInfo->ucRegChannelListIndex < REG_DOMAIN_GROUP_NUM) { + /* by given table idx */ + DBGLOG(RLM, TRACE, "ucRegChannelListIndex=%d\n", prRegInfo->ucRegChannelListIndex); + prDomainInfo = &arSupportedRegDomains[prRegInfo->ucRegChannelListIndex]; + } else if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + /* by customized */ + prDomainInfo = &prRegInfo->rDomainInfo; + } else { + /* by country code */ + u2TargetCountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + + for (i = 0; i < REG_DOMAIN_GROUP_NUM; i++) { + prDomainInfo = &arSupportedRegDomains[i]; + + if ((prDomainInfo->u4CountryNum && prDomainInfo->pu2CountryGroup) || + prDomainInfo->u4CountryNum == 0) { + for (j = 0; j < prDomainInfo->u4CountryNum; j++) { + if (prDomainInfo->pu2CountryGroup[j] == u2TargetCountryCode) + break; + } + if (j < prDomainInfo->u4CountryNum) + break; /* Found */ + } + } + + /* If no matched country code, use the default country domain */ + if (i >= REG_DOMAIN_GROUP_NUM) { + DBGLOG(RLM, INFO, "No matched country code, use the default country domain\n"); + prDomainInfo = &arSupportedRegDomains[REG_DOMAIN_DEF_IDX]; + } + } + + prAdapter->prDomainInfo = prDomainInfo; + return prDomainInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] The input variable pointed by pucNumOfChannel is the max +* arrary size. The return value indciates meaning list size. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +rlmDomainGetChnlList(P_ADAPTER_T prAdapter, + ENUM_BAND_T eSpecificBand, BOOLEAN fgNoDfs, + UINT_8 ucMaxChannelNum, PUINT_8 pucNumOfChannel, P_RF_CHANNEL_INFO_T paucChannelList) +{ + UINT_8 i, j, ucNum; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + ASSERT(prAdapter); + ASSERT(paucChannelList); + ASSERT(pucNumOfChannel); + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + ucNum = 0; + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_NULL || prSubband->ucBand >= BAND_NUM || + (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand)) + continue; + + if (fgNoDfs == TRUE && prSubband->fgDfs == TRUE) + continue; + + if (eSpecificBand == BAND_NULL || prSubband->ucBand == eSpecificBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if (ucNum >= ucMaxChannelNum) + break; + paucChannelList[ucNum].eBand = prSubband->ucBand; + paucChannelList[ucNum].ucChannelNum = + prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan; + ucNum++; + } + } + } + + *pucNumOfChannel = ucNum; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + rlmDomainSendDomainInfoCmd(prAdapter, fgIsOid); +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + rlmDomainSendPwrLimitCmd(prAdapter); +#endif + rlmDomainSendPassiveScanInfoCmd(prAdapter, fgIsOid); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendDomainInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_8 i; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 0; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set domain info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8)prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPassiveScanInfoCmd(P_ADAPTER_T prAdapter, BOOLEAN fgIsOid) +{ +#define REG_DOMAIN_PASSIVE_DEF_IDX 0 +#define REG_DOMAIN_PASSIVE_UDF_IDX 1 + + P_DOMAIN_INFO_ENTRY prDomainInfo; + P_CMD_SET_DOMAIN_INFO_T prCmd; + P_DOMAIN_SUBBAND_INFO prSubBand; + UINT_8 i; + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_SET_DOMAIN_INFO_T)); + if (!prCmd) { + DBGLOG(RLM, ERROR, "Alloc cmd buffer failed\n"); + return; + } + kalMemZero(prCmd, sizeof(CMD_SET_DOMAIN_INFO_T)); + + prCmd->u2CountryCode = prAdapter->rWifiVar.rConnSettings.u2CountryCode; + prCmd->u2IsSetPassiveScan = 1; + prCmd->uc2G4Bandwidth = prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode; + prCmd->uc5GBandwidth = prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode; + prCmd->aucReserved[0] = 0; + prCmd->aucReserved[1] = 0; + + DBGLOG(RLM, TRACE, "u2CountryCode=0x%04x\n", prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (prAdapter->rWifiVar.rConnSettings.u2CountryCode == COUNTRY_CODE_UDF) + prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_UDF_IDX]; + else + prDomainInfo = &arSupportedRegDomains_Passive[REG_DOMAIN_PASSIVE_DEF_IDX]; + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubBand = &prDomainInfo->rSubBand[i]; + + prCmd->rSubBand[i].ucRegClass = prSubBand->ucRegClass; + prCmd->rSubBand[i].ucBand = prSubBand->ucBand; + + if (prSubBand->ucBand != BAND_NULL && prSubBand->ucBand < BAND_NUM) { + prCmd->rSubBand[i].ucChannelSpan = prSubBand->ucChannelSpan; + prCmd->rSubBand[i].ucFirstChannelNum = prSubBand->ucFirstChannelNum; + prCmd->rSubBand[i].ucNumChannels = prSubBand->ucNumChannels; + } + } + + /* Set passive scan channel info to chip */ + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_DOMAIN_INFO, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + fgIsOid, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(CMD_SET_DOMAIN_INFO_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + cnmMemFree(prAdapter, prCmd); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return TRUE Legal channel +* FALSE Illegal channel for current regulatory domain +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmDomainIsLegalChannel(P_ADAPTER_T prAdapter, ENUM_BAND_T eBand, UINT_8 ucChannel) +{ + UINT_8 i, j; + P_DOMAIN_SUBBAND_INFO prSubband; + P_DOMAIN_INFO_ENTRY prDomainInfo; + + prDomainInfo = rlmDomainGetDomainInfo(prAdapter); + ASSERT(prDomainInfo); + + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + prSubband = &prDomainInfo->rSubBand[i]; + + if (prSubband->ucBand == BAND_5G && !prAdapter->fgEnable5GBand) + continue; + + if (prSubband->ucBand == eBand) { + for (j = 0; j < prSubband->ucNumChannels; j++) { + if ((prSubband->ucFirstChannelNum + j * prSubband->ucChannelSpan) + == ucChannel) { + return TRUE; + } + } + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in/out] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 rlmDomainSupOperatingClassIeFill(PUINT_8 pBuf) +{ + /* + The Country element should only be included for Status Code 0 (Successful). + */ + UINT_32 u4IeLen; + UINT_8 aucClass[12] = { 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21 + }; + + /* + The Supported Operating Classes element is used by a STA to advertise the + operating classes that it is capable of operating with in this country. + + The Country element (see 8.4.2.10) allows a STA to configure its PHY and MAC + for operation when the operating triplet of Operating Extension Identifier, + Operating Class, and Coverage Class fields is present. + */ + SUP_OPERATING_CLASS_IE(pBuf)->ucId = ELEM_ID_SUP_OPERATING_CLASS; + SUP_OPERATING_CLASS_IE(pBuf)->ucLength = 1 + sizeof(aucClass); + SUP_OPERATING_CLASS_IE(pBuf)->ucCur = 0x0c; /* 0x51 */ + kalMemCopy(SUP_OPERATING_CLASS_IE(pBuf)->ucSup, aucClass, sizeof(aucClass)); + u4IeLen = (SUP_OPERATING_CLASS_IE(pBuf)->ucLength + 2); + pBuf += u4IeLen; + + COUNTRY_IE(pBuf)->ucId = ELEM_ID_COUNTRY_INFO; + COUNTRY_IE(pBuf)->ucLength = 6; + COUNTRY_IE(pBuf)->aucCountryStr[0] = 0x55; + COUNTRY_IE(pBuf)->aucCountryStr[1] = 0x53; + COUNTRY_IE(pBuf)->aucCountryStr[2] = 0x20; + COUNTRY_IE(pBuf)->arCountryStr[0].ucFirstChnlNum = 1; + COUNTRY_IE(pBuf)->arCountryStr[0].ucNumOfChnl = 11; + COUNTRY_IE(pBuf)->arCountryStr[0].cMaxTxPwrLv = 0x1e; + u4IeLen += (COUNTRY_IE(pBuf)->ucLength + 2); + + return u4IeLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmDomainCheckChannelEntryValid(P_ADAPTER_T prAdapter, UINT_8 ucCentralCh) +{ + BOOLEAN fgValid = FALSE; + UINT_8 ucTemp = 0; + UINT_8 i; + /*Check Power limit table channel efficient or not */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if ((ucCentralCh >= g_rRlmSubBand[i].ucStartCh) && (ucCentralCh <= g_rRlmSubBand[i].ucEndCh)) + ucTemp = (ucCentralCh - g_rRlmSubBand[i].ucStartCh) % g_rRlmSubBand[i].ucInterval; + } + +#if 0 + /*2.4G, ex 1, 2, 3 */ + if (ucCentralCh >= BAND_2G4_LOWER_BOUND && ucCentralCh <= BAND_2G4_UPPER_BOUND) + ucTemp = 0; + /*FCC- Spec : Band UNII-1, ex 36, 38, 40.... */ + else if (ucCentralCh >= UNII1_LOWER_BOUND && ucCentralCh <= UNII1_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII1_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2A, ex 52, 54, 56.... */ + else if (ucCentralCh >= UNII2A_LOWER_BOUND && ucCentralCh <= UNII2A_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2A_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-2C, ex 100, 102, 104.... */ + else if (ucCentralCh >= UNII2C_LOWER_BOUND && ucCentralCh <= UNII2C_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII2C_LOWER_BOUND) % 2; + /*FCC- Spec : Band UNII-3, ex 149, 151, 153... */ + else if (ucCentralCh >= UNII3_LOWER_BOUND && ucCentralCh <= UNII3_UPPER_BOUND) + ucTemp = (ucCentralCh - UNII3_LOWER_BOUND) % 2; +#endif + if (ucTemp == 0) + fgValid = TRUE; + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rlmDomainGetCenterChannel(ENUM_BAND_T eBand, UINT_8 ucPriChannel, ENUM_CHNL_EXT_T eExtend) +{ + UINT_8 ucCenterChannel; + + if (eExtend == CHNL_EXT_SCA) + ucCenterChannel = ucPriChannel + 2; + else if (eExtend == CHNL_EXT_SCB) + ucCenterChannel = ucPriChannel - 2; + else + ucCenterChannel = ucPriChannel; + + return ucCenterChannel; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainIsValidRfSetting(P_ADAPTER_T prAdapter, + ENUM_BAND_T eBand, + UINT_8 ucPriChannel, + ENUM_CHNL_EXT_T eExtend, + ENUM_CHANNEL_WIDTH_T eChannelWidth, UINT_8 ucChannelS1, UINT_8 ucChannelS2) +{ + UINT_8 ucCenterChannel; + BOOLEAN fgValidChannel = TRUE; + BOOLEAN fgValidBW = TRUE; + BOOLEAN fgValidRfSetting = TRUE; + UINT_32 u4PrimaryOffset; + + /*DBG msg for Channel InValid */ + if (eChannelWidth == CW_20_40MHZ) { + ucCenterChannel = rlmDomainGetCenterChannel(eBand, ucPriChannel, eExtend); + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_80MHZ) { + ucCenterChannel = ucChannelS1; + + /* Check Central Channel Valid or Not */ + fgValidChannel = rlmDomainCheckChannelEntryValid(prAdapter, ucCenterChannel); + if (fgValidChannel == FALSE) + DBGLOG(RLM, WARN, "Rf: CentralCh=%d\n", ucCenterChannel); + } else if (eChannelWidth == CW_160MHZ) { + ucCenterChannel = ucChannelS2; + + /* Check Central Channel Valid or Not */ + /*TODo */ + } + + /* Check BW Setting Correct or Not */ + if (eBand == BAND_2G4) { + if (eChannelWidth != CW_20_40MHZ) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: B=%d, W=%d\n", eBand, eChannelWidth); + } + } else { + if (eChannelWidth == CW_80MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_80M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset > 4) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } else if (eChannelWidth == CW_160MHZ) { + u4PrimaryOffset = CAL_CH_OFFSET_160M(ucPriChannel, ucCenterChannel); + if (u4PrimaryOffset > 8) { + fgValidBW = FALSE; + DBGLOG(RLM, WARN, "Rf: PriOffSet=%d, W=%d\n", u4PrimaryOffset, eChannelWidth); + } + } + } + + if ((fgValidBW == FALSE) || (fgValidChannel == FALSE)) + fgValidRfSetting = FALSE; + + return fgValidRfSetting; + +} + +#if CFG_SUPPORT_PWR_LIMIT_COUNTRY + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (fgValid) : 0 -> inValid, 1 -> Valid +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rlmDomainCheckPowerLimitValid(P_ADAPTER_T prAdapter, + COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION rPowerLimitTableConfiguration, + UINT_8 ucPwrLimitNum) +{ + UINT_8 i; + BOOLEAN fgValid = TRUE; + PINT_8 prPwrLimit; + + prPwrLimit = &rPowerLimitTableConfiguration.aucPwrLimit[0]; + + for (i = 0; i < ucPwrLimitNum; i++, prPwrLimit++) { + if (*prPwrLimit > MAX_TX_POWER || *prPwrLimit < MIN_TX_POWER) { + fgValid = FALSE; + break; /*Find out Wrong Power limit */ + } + } + return fgValid; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainCheckCountryPowerLimitTable(P_ADAPTER_T prAdapter) +{ + UINT_8 i, j; + UINT_16 u2CountryCodeTable, u2CountryCodeCheck; + BOOLEAN fgChannelValid = FALSE; + BOOLEAN fgPowerLimitValid = FALSE; + BOOLEAN fgEntryRepetetion = FALSE; + BOOLEAN fgTableValid = TRUE; + + /*Configuration Table Check */ + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + /*Table Country Code */ + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + /*Repetition Entry Check */ + for (j = i + 1; + j < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); + j++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[j].aucCountryCode[0], &u2CountryCodeCheck); + if (((g_rRlmPowerLimitConfiguration[i].ucCentralCh) == + g_rRlmPowerLimitConfiguration[j].ucCentralCh) + && (u2CountryCodeTable == u2CountryCodeCheck)) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, "Domain: Configuration Repetition CC=%c%c, Ch=%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh); + } + } + + /*Channel Number Check */ + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + /*Power Limit Check */ + fgPowerLimitValid = + rlmDomainCheckPowerLimitValid(prAdapter, g_rRlmPowerLimitConfiguration[i], PWR_LIMIT_NUM); + + if (fgChannelValid == FALSE || fgPowerLimitValid == FALSE) { + fgTableValid = FALSE; + DBGLOG(RLM, LOUD, "Domain: CC=%c%c, Ch=%d, Limit: %d,%d,%d,%d,%d\n", + g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], + g_rRlmPowerLimitConfiguration[i].aucCountryCode[1], + g_rRlmPowerLimitConfiguration[i].ucCentralCh, + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M], + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]); + } + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, LOUD, "Domain: Full search down\n"); + break; /*End of country table entry */ + } + + } + + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Configuration Table no Repetiton.\n"); + + /*Configuration Table no error */ + if (fgTableValid == TRUE) + prAdapter->fgIsPowerLimitTableValid = TRUE; + else + prAdapter->fgIsPowerLimitTableValid = FALSE; + + /*Default Table Check */ + fgEntryRepetetion = FALSE; + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + for (j = i + 1; j < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); j++) { + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[j].aucCountryCode[0], &u2CountryCodeCheck); + if (u2CountryCodeTable == u2CountryCodeCheck) { + fgEntryRepetetion = TRUE; + DBGLOG(RLM, LOUD, + "Domain: Default Repetition CC=%c%c\n", + g_rRlmPowerLimitDefault[j].aucCountryCode[0], + g_rRlmPowerLimitDefault[j].aucCountryCode[1]); + } + } + } + if (fgEntryRepetetion == FALSE) + DBGLOG(RLM, TRACE, "Domain: Default Table no Repetiton.\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (u2TableIndex) : if 0xFFFF -> No Table Match +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 rlmDomainPwrLimitDefaultTableDecision(P_ADAPTER_T prAdapter, UINT_16 u2CountryCode) +{ + + UINT_16 i; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + UINT_16 u2TableIndex = POWER_LIMIT_TABLE_NULL; /* No Table Match */ + + /*Default Table Index */ + for (i = 0; i < sizeof(g_rRlmPowerLimitDefault) / sizeof(COUNTRY_POWER_LIMIT_TABLE_DEFAULT); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[i].aucCountryCode[0], &u2CountryCodeTable); + + if (u2CountryCodeTable == u2CountryCode) { + u2TableIndex = i; + break; /*match country code */ + } else if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + u2TableIndex = i; + break; /*find last one country- Default */ + } + } + + DBGLOG(RLM, TRACE, "Domain: Default Table Index = %d\n", u2TableIndex); + + return u2TableIndex; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByDefaultTable(P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd, UINT_16 u2DefaultTableIndex) +{ + UINT_8 i, k; + P_COUNTRY_POWER_LIMIT_TABLE_DEFAULT prPwrLimitSubBand; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prPwrLimitSubBand = &g_rRlmPowerLimitDefault[u2DefaultTableIndex]; + + /*Build power limit cmd by default table information */ + + for (i = POWER_LIMIT_2G4; i < POWER_LIMIT_SUBAND_NUM; i++) { + if (prPwrLimitSubBand->aucPwrLimitSubBand[i] < MAX_TX_POWER) { + for (k = g_rRlmSubBand[i].ucStartCh; k <= g_rRlmSubBand[i].ucEndCh; + k += g_rRlmSubBand[i].ucInterval) { + if ((prPwrLimitSubBand->ucPwrUnit & BIT(i)) == 0) { + prCmdPwrLimit->ucCentralCh = k; + prCmdPwrLimit->cPwrLimitCCK = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit40 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit80 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit160 = + prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit++; + prCmd->ucNum++; + + } else { + /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; */ + prCmdPwrLimit->ucCentralCh = k; + prCmdPwrLimit->cPwrLimitCCK = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit20 = prPwrLimitSubBand->aucPwrLimitSubBand[i]; + prCmdPwrLimit->cPwrLimit40 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 6; + if (prCmdPwrLimit->cPwrLimit40 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit40 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit80 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 12; + if (prCmdPwrLimit->cPwrLimit80 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit80 = MAX_TX_POWER; + prCmdPwrLimit->cPwrLimit160 = prPwrLimitSubBand->aucPwrLimitSubBand[i] + 18; + if (prCmdPwrLimit->cPwrLimit160 > MAX_TX_POWER) + prCmdPwrLimit->cPwrLimit160 = MAX_TX_POWER; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + } + +#if 0 + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4] < MAX_TX_POWER) { + for (i = BAND_2G4_LOWER_BOUND; i <= BAND_2G4_UPPER_BOUND; i++) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_2G4], + PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1] < MAX_TX_POWER) { + if (prCmd->u2CountryCode != COUNTRY_CODE_KR) { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII1], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } else { + for (i = UNII1_LOWER_BOUND; i <= UNII1_UPPER_BOUND; i += 2) { + /* ex: 40MHz power limit(mW\MHz) = 20MHz power limit(mW\MHz) * 2 + * ---> 40MHz power limit(dBm) = 20MHz power limit(dBm) + 6; */ + prCmdPwrLimit->ucCentralCh = i; + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 6; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 12; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitDefault[u2DefaultTableIndex].cPwrLimitUnii1 + 18; + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A] < MAX_TX_POWER) { + for (i = UNII2A_LOWER_BOUND; i <= UNII2A_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2A], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C] < MAX_TX_POWER) { + for (i = UNII2C_LOWER_BOUND; i <= UNII2C_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII2C], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } + if (prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3] < MAX_TX_POWER) { + for (i = UNII3_LOWER_BOUND; i <= UNII3_UPPER_BOUND; i += 2) { + prCmdPwrLimit->ucCentralCh = i; + kalMemSet(&prCmdPwrLimit->cPwrLimitCCK, + prPwrLimitSubBand->aucPwrLimitSubBand[POWER_LIMIT_UNII3], PWR_LIMIT_NUM); + prCmdPwrLimit++; + prCmd->ucNum++; + } + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainBuildCmdByConfigTable(P_ADAPTER_T prAdapter, P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd) +{ + UINT_8 i, k; + UINT_16 u2CountryCodeTable = COUNTRY_CODE_NULL; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; + BOOLEAN fgChannelValid; + + /*Build power limit cmd by configuration table information */ + + for (i = 0; i < sizeof(g_rRlmPowerLimitConfiguration) / sizeof(COUNTRY_POWER_LIMIT_TABLE_CONFIGURATION); i++) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitConfiguration[i].aucCountryCode[0], &u2CountryCodeTable); + + fgChannelValid = + rlmDomainCheckChannelEntryValid(prAdapter, g_rRlmPowerLimitConfiguration[i].ucCentralCh); + + if (u2CountryCodeTable == COUNTRY_CODE_NULL) { + DBGLOG(RLM, TRACE, "Domain: full search configuration table done.\n"); + break; /*end of configuration table */ + } else if ((u2CountryCodeTable == prCmd->u2CountryCode) && (fgChannelValid == TRUE)) { + + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + if (prCmd->ucNum != 0) { + for (k = 0; k < prCmd->ucNum; k++) { + if (prCmdPwrLimit->ucCentralCh == + g_rRlmPowerLimitConfiguration[i].ucCentralCh) { + + /*Cmd setting (Default table information) and + Configuration table has repetition channel entry, + ex : Default table (ex: 2.4G, limit = 20dBm) --> ch1~14 limit =20dBm, + Configuration table (ex: ch1, limit = 22dBm) --> ch 1 = 22 dBm + Cmd final setting --> ch1 = 22dBm, ch12~14 = 20dBm + */ + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + + DBGLOG(RLM, LOUD, + "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + break; + } + prCmdPwrLimit++; + } + if (k == prCmd->ucNum) { + + /*Full search cmd (Default table setting) no match channey, + ex : Default table (ex: 2.4G, limit = 20dBm) --> ch1~14 limit =20dBm, + Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm + Cmd final setting --> ch1~14 = 20dBm, ch36= 22dBm + */ + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + prCmd->ucNum++; + + DBGLOG(RLM, LOUD, + "Domain: Full CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), (prCmd->u2CountryCode & 0x00ff), + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + + } + } else { + + /*Default table power limit value are 63--> cmd table no channel entry + ex : Default table (ex: 2.4G, limit = 63Bm) --> no channel entry in cmd, + Configuration table (ex: ch36, limit = 22dBm) --> ch 36 = 22 dBm + Cmd final setting --> ch36= 22dBm + */ + prCmdPwrLimit->ucCentralCh = g_rRlmPowerLimitConfiguration[i].ucCentralCh; + prCmdPwrLimit->cPwrLimitCCK = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_CCK]; + prCmdPwrLimit->cPwrLimit20 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_20M]; + prCmdPwrLimit->cPwrLimit40 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_40M]; + prCmdPwrLimit->cPwrLimit80 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_80M]; + prCmdPwrLimit->cPwrLimit160 = + g_rRlmPowerLimitConfiguration[i].aucPwrLimit[PWR_LIMIT_160M]; + prCmd->ucNum++; + + DBGLOG(RLM, LOUD, "Domain: Default table power limit value are 63.\n"); + DBGLOG(RLM, LOUD, "Domain: CC=%c%c,ConfigCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, + prCmdPwrLimit->cPwrLimit40, prCmdPwrLimit->cPwrLimit80, + prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param[in] +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmDomainSendPwrLimitCmd(P_ADAPTER_T prAdapter) +{ + P_CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T prCmd; + UINT_8 i; + UINT_16 u2DefaultTableIndex; + UINT_32 u4SetCmdTableMaxSize; + UINT_32 u4SetQueryInfoLen; + P_CMD_CHANNEL_POWER_LIMIT prCmdPwrLimit; /* for print usage */ + + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); + + u2DefaultTableIndex = + rlmDomainPwrLimitDefaultTableDecision(prAdapter, prAdapter->rWifiVar.rConnSettings.u2CountryCode); + + if (u2DefaultTableIndex != POWER_LIMIT_TABLE_NULL) { + + WLAN_GET_FIELD_BE16(&g_rRlmPowerLimitDefault[u2DefaultTableIndex].aucCountryCode[0], + &prCmd->u2CountryCode); + + prCmd->ucNum = 0; + + if (prCmd->u2CountryCode != COUNTRY_CODE_NULL) { + /*Command - default table information */ + rlmDomainBuildCmdByDefaultTable(prCmd, u2DefaultTableIndex); + + /*Command - configuration table information */ + rlmDomainBuildCmdByConfigTable(prAdapter, prCmd); + } + } +#if 0 + u4SetCmdTableMaxSize = + sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + + MAX_CMD_SUPPORT_CHANNEL_NUM * sizeof(CMD_CHANNEL_POWER_LIMIT); + + prCmd = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4SetCmdTableMaxSize); + ASSERT(prCmd); + + /* To do: exception handle */ + if (!prCmd) { + DBGLOG(RLM, ERROR, "Domain: no buf to send cmd\n"); + return; + } + kalMemZero(prCmd, u4SetCmdTableMaxSize); /* TODO memzero */ + + if (u2TableIndex != POWER_LIMIT_TABLE_NULL && u2TableIndex < MAX_DEFAULT_TABLE_COUNTRY_NUM) { + + prCmd->u2CountryCode = (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[0]) << 8) | + (((UINT_16) g_rRlmCountryPowerLimitTable[u2TableIndex].aucCountryCode[1]) & BITS(0, 7)); + prChPwrLimit = &g_rRlmCountryPowerLimitTable[u2TableIndex].rChannelPowerLimit[0]; + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + prCmd->ucNum = 0; + for (i = 0; i < MAX_CMD_SUPPORT_CHANNEL_NUM; i++) { + + if (prChPwrLimit->ucCentralCh != ENDCH) { + + /*Check Power limit table channel efficient or not */ + fgChannelValid = rlmDomainCheckChannelEntryValid(prAdapter, prChPwrLimit->ucCentralCh); + + /*Cmd set up */ + if (fgChannelValid) { + kalMemCopy(prCmdPwrLimit, prChPwrLimit, sizeof(CMD_CHANNEL_POWER_LIMIT)); + DBGLOG(RLM, INFO, + "Domain: ValidCh=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prCmdPwrLimit->ucCentralCh, prCmdPwrLimit->cPwrLimitCCK, + prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, + prCmdPwrLimit->ucFlag); + prCmd->ucNum++; + prCmdPwrLimit++; + } else { + DBGLOG(RLM, INFO, + "Domain: Non-Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", + prChPwrLimit->ucCentralCh, prChPwrLimit->cPwrLimitCCK, + prChPwrLimit->cPwrLimit20, prChPwrLimit->cPwrLimit40, + prChPwrLimit->cPwrLimit80, prChPwrLimit->cPwrLimit160, + prChPwrLimit->ucFlag); + } + prChPwrLimit++; + } else { + /*End of the chanel entry */ + break; + } + }; + } +#endif + + if (prCmd->u2CountryCode != 0) { + DBGLOG(RLM, INFO, + "Domain: ValidCC =%c%c, ChNum=%d\n", ((prCmd->u2CountryCode & 0xff00) >> 8), + (prCmd->u2CountryCode & 0x00ff), prCmd->ucNum); + } else { + DBGLOG(RLM, INFO, "Domain: ValidCC =0x%04x, ucNum=%d\n", prCmd->u2CountryCode, prCmd->ucNum); + } + prCmdPwrLimit = &prCmd->rChannelPowerLimit[0]; + + for (i = 0; i < prCmd->ucNum; i++) { + DBGLOG(RLM, TRACE, "Domain: Ch=%d,Limit=%d,%d,%d,%d,%d,Fg=%d\n", prCmdPwrLimit->ucCentralCh, + prCmdPwrLimit->cPwrLimitCCK, prCmdPwrLimit->cPwrLimit20, prCmdPwrLimit->cPwrLimit40, + prCmdPwrLimit->cPwrLimit80, prCmdPwrLimit->cPwrLimit160, prCmdPwrLimit->ucFlag); + prCmdPwrLimit++; + } + + u4SetQueryInfoLen = + (sizeof(CMD_SET_COUNTRY_CHANNEL_POWER_LIMIT_T) + (prCmd->ucNum) * sizeof(CMD_CHANNEL_POWER_LIMIT)); + + /* Update domain info to chip */ + if (prCmd->ucNum <= MAX_CMD_SUPPORT_CHANNEL_NUM) { + wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_COUNTRY_POWER_LIMIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + u4SetQueryInfoLen, /* u4SetQueryInfoLen */ + (PUINT_8) prCmd, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + } else + DBGLOG(RLM, ERROR, "Domain: illegal power limit table"); + + cnmMemFree(prAdapter, prCmd); + +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c new file mode 100644 index 0000000000000..8450124a3f38e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_obss.c @@ -0,0 +1,436 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_obss.c#2 +*/ + +/*! \file "rlm_obss.c" + \brief + +*/ + +/* +** Log: rlm_obss.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 11 15 2011 cm.chang + * NULL + * Avoid possible OBSS scan when BSS is switched + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * Regulation class is changed to 81 in 20_40_coexistence action frame + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 29 2011 cm.chang + * [WCXRP00000606] [MT6620 Wi-Fi][Driver][FW] Fix klocwork warning + * As CR title + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame + * in AP mode and stop ampdu timer when sta_rec is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 13 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Refine function when rcv a 20/40M public action frame + * + * 01 13 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * Use SCO of BSS_INFO to replace user-defined setting variables + * + * 01 12 2011 cm.chang + * [WCXRP00000354] [MT6620 Wi-Fi][Driver][FW] Follow NVRAM bandwidth setting + * User-defined bandwidth is for 2.4G and 5G individually + * + * 10 18 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * use definition macro to replace hard-coded constant + * + * 09 16 2010 cm.chang + * NULL + * Change conditional compiling options for BOW + * + * 09 10 2010 cm.chang + * NULL + * Always update Beacon content if FW sync OBSS info + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 26 2010 yuche.tsai + * + * Fix compile error while enabling WiFi Direct function. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 05 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Process 20/40 coexistence public action frame in AP mode + * + * 05 05 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft support for 20/40M bandwidth for AP mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add more ASSERT to check exception + * + * 04 07 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add virtual test for OBSS scan + * + * 03 30 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support 2.4G OBSS scan + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 02 05 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssInit(P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 ucNetIdx; + + RLM_NET_FOR_EACH(ucNetIdx) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[ucNetIdx]; + ASSERT(prBssInfo); + + cnmTimerInitTimer(prAdapter, &prBssInfo->rObssScanTimer, rlmObssScanTimeout, (ULONG) prBssInfo); + } /* end of RLM_NET_FOR_EACH */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rlmObssUpdateChnlLists(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssScanDone(P_ADAPTER_T prAdapter, P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_20_40_COEXIST_FRAME prTxFrame; + UINT_16 i, u2PayloadLen; + + ASSERT(prMsgHdr); + + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) prMsgHdr; + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prScanDoneMsg->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(RLM, INFO, "OBSS Scan Done (NetIdx=%d, Mode=%d)\n", + prScanDoneMsg->ucNetTypeIndex, prBssInfo->eCurrentOPMode); + + cnmMemFree(prAdapter, prMsgHdr); + +#if CFG_ENABLE_WIFI_DIRECT + /* AP mode */ + if ((prAdapter->fgIsP2PRegistered) && + (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex)) && + (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT)) { + return; + } +#endif + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, "OBSS Scan Done (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); + return; + } + + /* To do: check 2.4G channel list to decide if obss mgmt should be + * sent to associated AP. Note: how to handle concurrent network? + * To do: invoke rlmObssChnlLevel() to decide if 20/40 BSS coexistence + * management frame is needed. + */ + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + if ((prBssInfo->auc2G_20mReqChnlList[0] > 0 || prBssInfo->auc2G_NonHtChnlList[0] > 0) && prMsduInfo != NULL) { + DBGLOG(RLM, INFO, "Send 20/40 coexistence mgmt(20mReq=%d, NonHt=%d)\n", + prBssInfo->auc2G_20mReqChnlList[0], prBssInfo->auc2G_NonHtChnlList[0]); + + prTxFrame = (P_ACTION_20_40_COEXIST_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_PUBLIC_ACTION; + prTxFrame->ucAction = ACTION_PUBLIC_20_40_COEXIST; + + /* To do: find correct algorithm */ + prTxFrame->rBssCoexist.ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + prTxFrame->rBssCoexist.ucLength = 1; + prTxFrame->rBssCoexist.ucData = (prBssInfo->auc2G_20mReqChnlList[0] > 0) ? BSS_COEXIST_20M_REQ : 0; + + u2PayloadLen = 2 + 3; + + if (prBssInfo->auc2G_NonHtChnlList[0] > 0) { + ASSERT(prBssInfo->auc2G_NonHtChnlList[0] <= CHNL_LIST_SZ_2G); + + prTxFrame->rChnlReport.ucId = ELEM_ID_20_40_INTOLERANT_CHNL_REPORT; + prTxFrame->rChnlReport.ucLength = prBssInfo->auc2G_NonHtChnlList[0] + 1; + prTxFrame->rChnlReport.ucRegulatoryClass = 81; /* 2.4GHz, ch1~13 */ + for (i = 0; i < prBssInfo->auc2G_NonHtChnlList[0] && i < CHNL_LIST_SZ_2G; i++) + prTxFrame->rChnlReport.aucChannelList[i] = prBssInfo->auc2G_NonHtChnlList[i + 1]; + + u2PayloadLen += IE_SIZE(&prTxFrame->rChnlReport); + } + ASSERT((WLAN_MAC_HEADER_LEN + u2PayloadLen) <= PUBLIC_ACTION_MAX_LEN); + + /* Clear up channel lists in 2.4G band */ + prBssInfo->auc2G_20mReqChnlList[0] = 0; + prBssInfo->auc2G_NonHtChnlList[0] = 0; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + } + /* end of prMsduInfo != NULL */ + if (prBssInfo->u2ObssScanInterval > 0) { + DBGLOG(RLM, INFO, "Set OBSS timer (NetIdx=%d, %d sec)\n", + prBssInfo->ucNetTypeIndex, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +static VOID rlmObssScanTimeout(P_ADAPTER_T prAdapter, ULONG ulData) +{ + P_BSS_INFO_T prBssInfo; + + prBssInfo = (P_BSS_INFO_T) ulData; + ASSERT(prBssInfo); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && (IS_NET_ACTIVE(prAdapter, prBssInfo->ucNetTypeIndex))) { + + /* AP mode */ + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + + prBssInfo->fgObssActionForcedTo20M = FALSE; + + /* Check if Beacon content need to be updated */ + rlmUpdateParamsForAP(prAdapter, prBssInfo, FALSE); + + return; + } +#if CFG_SUPPORT_WFD + /* WFD streaming */ + else { + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = + &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + P_BSS_INFO_T prP2pBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]; + + /* If WFD is enabled & connected */ + if (prWfdCfgSettings->ucWfdEnable && + (prWfdCfgSettings->u4WfdFlag & BIT(0)) && RLM_NET_PARAM_VALID(prP2pBssInfo)) { + + /* Skip OBSS scan */ + prBssInfo->u2ObssScanInterval = 0; + + DBGLOG(RLM, INFO, "WFD is running. Stop net[%u] OBSS scan.\n", + (UINT_32) prBssInfo->ucNetTypeIndex); + + return; + } + } +#endif + } +#endif /* end of CFG_ENABLE_WIFI_DIRECT */ + + /* STA mode */ + if (prBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE || + !RLM_NET_PARAM_VALID(prBssInfo) || prBssInfo->u2ObssScanInterval == 0) { + DBGLOG(RLM, WARN, "OBSS Scan timeout (NetIdx=%d) -- Aborted!!\n", prBssInfo->ucNetTypeIndex); + return; + } + + rlmObssTriggerScan(prAdapter, prBssInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rlmObssTriggerScan(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + P_MSG_SCN_SCAN_REQ prScanReqMsg; + + ASSERT(prBssInfo); + + prScanReqMsg = (P_MSG_SCN_SCAN_REQ) + cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_REQ)); + ASSERT(prScanReqMsg); + + if (!prScanReqMsg) { + DBGLOG(RLM, WARN, "No buf for OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); + + cnmTimerStartTimer(prAdapter, &prBssInfo->rObssScanTimer, prBssInfo->u2ObssScanInterval * MSEC_PER_SEC); + return; + } + + /* It is ok that ucSeqNum is set to fixed value because the same network + * OBSS scan interval is limited to OBSS_SCAN_MIN_INTERVAL (min 10 sec) + * and scan module don't care seqNum of OBSS scanning + */ + prScanReqMsg->rMsgHdr.eMsgId = MID_RLM_SCN_SCAN_REQ; + prScanReqMsg->ucSeqNum = 0x33; + prScanReqMsg->ucNetTypeIndex = prBssInfo->ucNetTypeIndex; + prScanReqMsg->eScanType = SCAN_TYPE_ACTIVE_SCAN; + prScanReqMsg->ucSSIDType = SCAN_REQ_SSID_WILDCARD; + prScanReqMsg->ucSSIDLength = 0; + prScanReqMsg->eScanChannel = SCAN_CHANNEL_2G4; + prScanReqMsg->u2IELen = 0; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanReqMsg, MSG_SEND_METHOD_BUF); + + DBGLOG(RLM, INFO, "Timeout to trigger OBSS scan (NetIdx=%d)!!\n", prBssInfo->ucNetTypeIndex); +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c new file mode 100644 index 0000000000000..d3c5133970956 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rlm_protection.c @@ -0,0 +1,105 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rlm_protection.c#1 +*/ + +/*! \file "rlm_protection.c" + \brief + +*/ + +/* +** Log: rlm_protection.c + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Check draft RLM code for HT cap + * + * 05 28 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Set RTS threshold of 2K bytes initially + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * First draft code to support protection in AP mode + * + * 03 31 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Enable RTS threshold temporarily for AMPDU + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 03 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * To support CFG_SUPPORT_BCM_STP + * + * 02 13 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support PCO in STA mode + * + * 02 12 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Use bss info array for concurrent handle + * + * 01 25 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c new file mode 100644 index 0000000000000..3f088c2839936 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/roaming_fsm.c @@ -0,0 +1,539 @@ +/* +** Id: +*/ + +/*! \file "roaming_fsm.c" + \brief This file defines the FSM for Roaming MODULE. + + This file defines the FSM for Roaming MODULE. +*/ + +/* +** Log: roaming_fsm.c + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 03 16 2011 tsaiyuan.hsu + * [WCXRP00000517] [MT6620 Wi-Fi][Driver][FW] Fine Tune Performance of Roaming + * remove obsolete definition and unused variables. + * + * 02 26 2011 tsaiyuan.hsu + * [WCXRP00000391] [MT6620 Wi-Fi][FW] Add Roaming Support + * not send disassoc or deauth to leaving AP so as to improve performace of roaming. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_ROAMING +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugRoamingState[ROAMING_STATE_NUM] = { + (PUINT_8) DISP_STRING("ROAMING_STATE_IDLE"), + (PUINT_8) DISP_STRING("ROAMING_STATE_DECISION"), + (PUINT_8) DISP_STRING("ROAMING_STATE_DISCOVERY"), + (PUINT_8) DISP_STRING("ROAMING_STATE_ROAM") +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* +#define ROAMING_ENABLE_CHECK(_roam) \ +{ \ + if (!(_roam->fgIsEnableRoaming)) \ + return; \ +} +*/ +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the value in ROAMING_FSM_INFO_T for ROAMING FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmInit(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DBGLOG(ROAMING, LOUD, "->roamingFsmInit(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + /* 4 <1> Initiate FSM */ + prRoamingFsmInfo->fgIsEnableRoaming = prConnSettings->fgIsEnableRoaming; + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + prRoamingFsmInfo->rRoamingDiscoveryUpdateTime = 0; + +} /* end of roamingFsmInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the value in AIS_FSM_INFO_T for AIS FSM operation +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmUninit(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + DBGLOG(ROAMING, LOUD, "->roamingFsmUninit(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + prRoamingFsmInfo->eCurrentState = ROAMING_STATE_IDLE; + +} /* end of roamingFsmUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Send commands to firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmSendCmd(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + WLAN_STATUS rStatus; + + DBGLOG(ROAMING, LOUD, "->roamingFsmSendCmd(): Current Time = %u\n", kalGetTimeTick()); + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_ROAMING_TRANSIT, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(ROAMING_PARAM_T), /* u4SetQueryInfoLen */ + (PUINT_8) prParam, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + +} /* end of roamingFsmSendCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Update the recent time when ScanDone occurred +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmScanResultsUpdate(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, LOUD, "->roamingFsmScanResultsUpdate(): Current Time = %u", kalGetTimeTick()); + + GET_CURRENT_SYSTIME(&prRoamingFsmInfo->rRoamingDiscoveryUpdateTime); + +} /* end of roamingFsmScanResultsUpdate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of ROAMING for AIS Infra. +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN ENUM_ROAMING_STATE_T] eNextState Enum value of next AIS STATE +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_ROAMING_STATE_T eNextState) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T ePreviousState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + do { + + /* Do entering Next State */ +#if DBG + DBGLOG(ROAMING, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugRoamingState[prRoamingFsmInfo->eCurrentState], + apucDebugRoamingState[eNextState]); +#else + DBGLOG(ROAMING, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_ROAMING_IDX, prRoamingFsmInfo->eCurrentState, eNextState); +#endif + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + ePreviousState = prRoamingFsmInfo->eCurrentState; + prRoamingFsmInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + + /* Do tasks of the State that we just entered */ + switch (prRoamingFsmInfo->eCurrentState) { + /* NOTE(Kevin): we don't have to rearrange the sequence of following + * switch case. Instead I would like to use a common lookup table of array + * of function pointer to speed up state search. + */ + case ROAMING_STATE_IDLE: + case ROAMING_STATE_DECISION: + break; + + case ROAMING_STATE_DISCOVERY: + { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prRoamingFsmInfo->rRoamingDiscoveryUpdateTime, + SEC_TO_SYSTIME(ROAMING_DISCOVERY_TIMEOUT_SEC))) { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Timeout"); + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + } else { + DBGLOG(ROAMING, LOUD, "roamingFsmSteps: DiscoveryUpdateTime Updated"); +#if CFG_SUPPORT_ROAMING_ENC + if (prAdapter->fgIsRoamingEncEnabled == TRUE) + aisFsmRunEventRoamingDiscovery(prAdapter, TRUE); + else +#endif /* CFG_SUPPORT_ROAMING_ENC */ + aisFsmRunEventRoamingDiscovery(prAdapter, FALSE); + } + } + break; + + case ROAMING_STATE_ROAM: + break; + + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + } + } while (fgIsTransition); + + return; + +} /* end of roamingFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state after join completion +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventStart(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + P_BSS_INFO_T prAisBssInfo; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->eCurrentOPMode != OP_MODE_INFRASTRUCTURE) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING START: Current Time = %u\n", kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as DECISION, DISCOVERY -> DECISION */ + if (!(prRoamingFsmInfo->eCurrentState == ROAMING_STATE_IDLE || + prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) + return; + + eNextState = ROAMING_STATE_DECISION; + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_START; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Discovery state when deciding to find a candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventDiscovery(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING DISCOVERY: Current Time = %u Reason = %u\n", + kalGetTimeTick(), prParam->u2Reason); + + /* DECISION -> DISCOVERY */ + /* Errors as IDLE, DISCOVERY, ROAM -> DISCOVERY */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DECISION) + return; +#if CFG_SUPPORT_ROAMING_ENC + prRoamingFsmInfo->RoamingEntryTimeoutSkipCount = 0; +#endif + + eNextState = ROAMING_STATE_DISCOVERY; + /* DECISION -> DISCOVERY */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + P_BSS_INFO_T prAisBssInfo; + P_BSS_DESC_T prBssDesc; + + /* sync. rcpi with firmware */ + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prBssDesc = scanSearchBssDescByBssid(prAdapter, prAisBssInfo->aucBSSID); + if (prBssDesc) + prBssDesc->ucRCPI = (UINT_8) (prParam->u2Data & 0xff); + + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventDiscovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Roam state after Scan Done +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventRoam(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ROAM: Current Time = %u\n", kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, ROAM -> ROAM */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_DISCOVERY) + return; + + eNextState = ROAMING_STATE_ROAM; + /* DISCOVERY -> ROAM */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ROAM; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventRoam() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Decision state as being failed to find out any candidate +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventFail(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Param) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + /* Check Roaming Conditions */ + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING FAIL: reason %x Current Time = %u\n", u4Param, kalGetTimeTick()); + + /* IDLE, ROAM -> DECISION */ + /* Errors as IDLE, DECISION, DISCOVERY -> DECISION */ + if (prRoamingFsmInfo->eCurrentState != ROAMING_STATE_ROAM) + return; + + eNextState = ROAMING_STATE_DECISION; + /* ROAM -> DECISION */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_FAIL; + rParam.u2Data = (UINT_16) (u4Param & 0xffff); + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventFail() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Transit to Idle state as beging aborted by other moduels, AIS +* +* @param [IN P_ADAPTER_T] prAdapter +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID roamingFsmRunEventAbort(IN P_ADAPTER_T prAdapter) +{ + P_ROAMING_INFO_T prRoamingFsmInfo; + ENUM_ROAMING_STATE_T eNextState; + ROAMING_PARAM_T rParam; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + + if (!(prRoamingFsmInfo->fgIsEnableRoaming)) + return; + + DBGLOG(ROAMING, EVENT, "EVENT-ROAMING ABORT: Current Time = %u\n", kalGetTimeTick()); + + eNextState = ROAMING_STATE_IDLE; + /* IDLE, DECISION, DISCOVERY, ROAM -> IDLE */ + if (eNextState != prRoamingFsmInfo->eCurrentState) { + rParam.u2Event = ROAMING_EVENT_ABORT; + roamingFsmSendCmd(prAdapter, (P_ROAMING_PARAM_T) & rParam); + + /* Step to next state */ + roamingFsmSteps(prAdapter, eNextState); + } + +} /* end of roamingFsmRunEventAbort() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process events from firmware +* +* @param [IN P_ADAPTER_T] prAdapter +* [IN P_ROAMING_PARAM_T] prParam +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS roamingFsmProcessEvent(IN P_ADAPTER_T prAdapter, IN P_ROAMING_PARAM_T prParam) +{ + DBGLOG(ROAMING, LOUD, "ROAMING Process Events: Current Time = %u\n", kalGetTimeTick()); + + if (ROAMING_EVENT_DISCOVERY == prParam->u2Event) + roamingFsmRunEventDiscovery(prAdapter, prParam); + + return WLAN_STATUS_SUCCESS; +} + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c new file mode 100644 index 0000000000000..eedd8d12f2fd3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/rsn.c @@ -0,0 +1,2533 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/rsn.c#2 +*/ + +/*! \file "rsn.c" + \brief This file including the 802.11i, wpa and wpa2(rsn) related function. + + This file provided the macros and functions library support the wpa/rsn ie parsing, + cipher and AKM check to help the AP seleced deciding, tkip mic error handler and rsn PMKID support. +*/ + +/* +** Log: rsn.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 09 2012 chinglan.wang + * NULL + * Fix the condition error. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 02 09 2011 wh.su + * [WCXRP00000432] [MT6620 Wi-Fi][Driver] Add STA privacy check at hotspot mode + * adding the code for check STA privacy bit at AP mode, . + * + * 12 24 2010 chinglan.wang + * NULL + * [MT6620][Wi-Fi] Modify the key management in the driver for WPS function. + * + * 12 13 2010 cp.wu + * [WCXRP00000260] [MT6620 Wi-Fi][Driver][Firmware] Create V1.1 branch for both firmware and driver + * create branch for Wi-Fi driver v1.1 + * + * 11 05 2010 wh.su + * [WCXRP00000165] [MT6620 Wi-Fi] [Pre-authentication] Assoc req rsn ie use wrong pmkid value + * fixed the.pmkid value mismatch issue + * + * 11 03 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Refine the HT rate disallow TKIP pairwise cipher . + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T + * and replaced by ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 29 2010 yuche.tsai + * NULL + * Fix compile error, remove unused pointer in rsnGenerateRSNIE(). + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 08 30 2010 wh.su + * NULL + * remove non-used code. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * [WPD00003833][MT6620 and MT5931] Driver migration + * enable RX management frame handling. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * [WPD00003840] [MT6620 5931] Security migration + * migration from firmware. + * + * 05 27 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * not indicate pmkid candidate while no new one scanned. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, + * and modify the security related callback function prototype. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * change the name + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * using the Rx0 port to indicate event + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine the code for generate the WPA/RSN IE for assoc req + * + * Dec 3 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust code for pmkid event + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the code for event (mic error and pmkid indicate) and do some function rename + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security function + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding some security feature, including pmkid + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_RSN_MIGRATION + +/* extern PHY_ATTRIBUTE_T rPhyAttributes[]; */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse RSN IE. +* +* \param[in] prInfoElem Pointer to the RSN IE +* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the +** RSN information from the given RSN IE +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnParseRsnIE(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prRsnInfo) +{ + UINT_32 i; + INT_32 u4RemainRsnIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = RSN_CIPHER_SUITE_CCMP; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUINT_8 pucPairSuite = NULL; + PUINT_8 pucAuthSuite = NULL; + PUINT_8 cp; + + DEBUGFUNC("rsnParseRsnIE"); + + ASSERT(prInfoElem); + ASSERT(prRsnInfo); + + /* Verify the length of the RSN IE. */ + if (prInfoElem->ucLength < 2) { + DBGLOG(RSN, TRACE, "RSN IE length too short (length=%d)\n", prInfoElem->ucLength); + return FALSE; + } + + /* Check RSN version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(RSN, TRACE, "Unsupported RSN IE version: %d\n", u2Version); + return FALSE; + } + + cp = (PUCHAR) & prInfoElem->u4GroupKeyCipherSuite; + u4RemainRsnIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainRsnIeLen < 4) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainRsnIeLen -= 4; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainRsnIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (INT_32) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the Authentication and Key Management Cipher Suite Count field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainRsnIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainRsnIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainRsnIeLen -= (INT_32) i; + + if (u4RemainRsnIeLen == 0) + break; + + /* Parse the RSN u2Capabilities field. */ + if (u4RemainRsnIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse RSN IE in RSN capabilities (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + } while (FALSE); + + /* Save the RSN information for the BSS. */ + prRsnInfo->ucElemId = ELEM_ID_RSN; + + prRsnInfo->u2Version = u2Version; + + prRsnInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, LOUD, "RSN: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) + u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; + + prRsnInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prRsnInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, "RSN: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for RSN: CCMP. */ + prRsnInfo->u4PairwiseKeyCipherSuiteCount = 1; + prRsnInfo->au4PairwiseKeyCipherSuite[0] = RSN_CIPHER_SUITE_CCMP; + + DBGLOG(RSN, LOUD, "RSN: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prRsnInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) + u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; + + prRsnInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prRsnInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, "RSN: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for RSN. */ + prRsnInfo->u4AuthKeyMgtSuiteCount = 1; + prRsnInfo->au4AuthKeyMgtSuite[0] = RSN_AKM_SUITE_802_1X; + + DBGLOG(RSN, LOUD, "RSN: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prRsnInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prRsnInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); + } + + prRsnInfo->u2RsnCap = u2Cap; +#if CFG_SUPPORT_802_11W + prRsnInfo->fgRsnCapPresent = TRUE; +#endif + DBGLOG(RSN, LOUD, "RSN cap: 0x%04x\n", prRsnInfo->u2RsnCap); + + return TRUE; +} /* rsnParseRsnIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse WPA IE. +* +* \param[in] prInfoElem Pointer to the WPA IE. +* \param[out] prWpaInfo Pointer to the BSSDescription structure to store the +* WPA information from the given WPA IE. +* +* \retval TRUE Succeeded. +* \retval FALSE Failed. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnParseWpaIE(IN P_ADAPTER_T prAdapter, IN P_WPA_INFO_ELEM_T prInfoElem, OUT P_RSN_INFO_T prWpaInfo) +{ + UINT_32 i; + INT_32 u4RemainWpaIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = WPA_CIPHER_SUITE_TKIP; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUCHAR pucPairSuite = NULL; + PUCHAR pucAuthSuite = NULL; + PUCHAR cp; + BOOLEAN fgCapPresent = FALSE; + + DEBUGFUNC("rsnParseWpaIE"); + + ASSERT(prInfoElem); + ASSERT(prWpaInfo); + + /* Verify the length of the WPA IE. */ + if (prInfoElem->ucLength < 6) { + DBGLOG(RSN, TRACE, "WPA IE length too short (length=%d)\n", prInfoElem->ucLength); + return FALSE; + } + + /* Check WPA version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(RSN, TRACE, "Unsupported WPA IE version: %d\n", u2Version); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u4GroupKeyCipherSuite; + u4RemainWpaIeLen = (INT_32) prInfoElem->ucLength - 6; + + do { + if (u4RemainWpaIeLen == 0) + break; + + /* WPA_OUI : 4 + Version : 2 + GroupSuite : 4 + PairwiseCount: 2 + PairwiseSuite: 4 * pairSuiteCount + AuthCount : 2 + AuthSuite : 4 * authSuiteCount + Cap : 2 */ + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWpaIeLen < 4) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWpaIeLen -= 4; + + if (u4RemainWpaIeLen == 0) + break; + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWpaIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWpaIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWpaIeLen -= (INT_32) i; + + if (u4RemainWpaIeLen == 0) + break; + + /* Parse the Authentication and Key Management Cipher Suite Count + field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWpaIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWpaIeLen < (INT_32) i) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWpaIeLen -= (INT_32) i; + + if (u4RemainWpaIeLen == 0) + break; + + /* Parse the WPA u2Capabilities field. */ + if (u4RemainWpaIeLen < 2) { + DBGLOG(RSN, TRACE, "Fail to parse WPA IE in WPA capabilities (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + fgCapPresent = TRUE; + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWpaIeLen -= 2; + } while (FALSE); + + /* Save the WPA information for the BSS. */ + + prWpaInfo->ucElemId = ELEM_ID_WPA; + + prWpaInfo->u2Version = u2Version; + + prWpaInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(RSN, LOUD, "WPA: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_CIPHER_SUITES) + u2PairSuiteCount = MAX_NUM_SUPPORTED_CIPHER_SUITES; + + prWpaInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prWpaInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(RSN, LOUD, "WPA: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for WPA: TKIP. */ + prWpaInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWpaInfo->au4PairwiseKeyCipherSuite[0] = WPA_CIPHER_SUITE_TKIP; + + DBGLOG(RSN, LOUD, "WPA: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWpaInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_AKM_SUITES) + u2AuthSuiteCount = MAX_NUM_SUPPORTED_AKM_SUITES; + + prWpaInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWpaInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(RSN, LOUD, "WPA: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for WPA. */ + prWpaInfo->u4AuthKeyMgtSuiteCount = 1; + prWpaInfo->au4AuthKeyMgtSuite[0] = WPA_AKM_SUITE_802_1X; + + DBGLOG(RSN, LOUD, "WPA: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWpaInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWpaInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); + } + + if (fgCapPresent) { + prWpaInfo->fgRsnCapPresent = TRUE; + prWpaInfo->u2RsnCap = u2Cap; + DBGLOG(RSN, LOUD, "WPA: RSN cap: 0x%04x\n", prWpaInfo->u2RsnCap); + } else { + prWpaInfo->fgRsnCapPresent = FALSE; + prWpaInfo->u2RsnCap = 0; + } + + return TRUE; +} /* rsnParseWpaIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the desired pairwise +* cipher suite from the MIB Pairwise Cipher Suite +* configuration table. +* +* \param[in] u4Cipher The desired pairwise cipher suite to be searched +* \param[out] pu4Index Pointer to the index of the desired pairwise cipher in +* the table +* +* \retval TRUE - The desired pairwise cipher suite is found in the table. +* \retval FALSE - The desired pairwise cipher suite is not found in the +* table. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnSearchSupportedCipher(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Cipher, OUT PUINT_32 pu4Index) +{ + UINT_8 i; + P_DOT11_RSNA_CONFIG_PAIRWISE_CIPHERS_ENTRY prEntry; + + DEBUGFUNC("rsnSearchSupportedCipher"); + + ASSERT(pu4Index); + + for (i = 0; i < MAX_NUM_SUPPORTED_CIPHER_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigPairwiseCiphersTable[i]; + if (prEntry->dot11RSNAConfigPairwiseCipher == u4Cipher && + prEntry->dot11RSNAConfigPairwiseCipherEnabled) { + *pu4Index = i; + return TRUE; + } + } + return FALSE; +} /* rsnSearchSupportedCipher */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Whether BSS RSN is matched from upper layer set. +* +* \param[in] prAdapter Pointer to the Adapter structure, BSS RSN Information +* +* \retval BOOLEAN +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnIsSuitableBSS(IN P_ADAPTER_T prAdapter, IN P_RSN_INFO_T prBssRsnInfo) +{ + UINT_8 i = 0; + + DEBUGFUNC("rsnIsSuitableBSS"); + + do { + + if ((prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite & 0x000000FF) != + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite)) { + DBGLOG(RSN, TRACE, "Break by GroupKeyCipherSuite\n"); + break; + } + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] & 0x000000FF) != + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i])) + && (i == prBssRsnInfo->u4PairwiseKeyCipherSuiteCount - 1)) { + DBGLOG(RSN, TRACE, "Break by PairwiseKeyCipherSuite\n"); + break; + } + } + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { + if (((prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] & 0x000000FF) != + GET_SELECTOR_TYPE(prBssRsnInfo->au4AuthKeyMgtSuite[0])) + && (i == prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1)) { + DBGLOG(RSN, TRACE, "Break by AuthKeyMgtSuite\n"); + break; + } + } + return TRUE; + } while (FALSE); + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to search the desired +* authentication and key management (AKM) suite from the +* MIB Authentication and Key Management Suites table. +* +* \param[in] u4AkmSuite The desired AKM suite to be searched +* \param[out] pu4Index Pointer to the index of the desired AKM suite in the +* table +* +* \retval TRUE The desired AKM suite is found in the table. +* \retval FALSE The desired AKM suite is not found in the table. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnSearchAKMSuite(IN P_ADAPTER_T prAdapter, IN UINT_32 u4AkmSuite, OUT PUINT_32 pu4Index) +{ + UINT_8 i; + P_DOT11_RSNA_CONFIG_AUTHENTICATION_SUITES_ENTRY prEntry; + + DEBUGFUNC("rsnSearchAKMSuite"); + + ASSERT(pu4Index); + + for (i = 0; i < MAX_NUM_SUPPORTED_AKM_SUITES; i++) { + prEntry = &prAdapter->rMib.dot11RSNAConfigAuthenticationSuitesTable[i]; + if (prEntry->dot11RSNAConfigAuthenticationSuite == u4AkmSuite && + prEntry->dot11RSNAConfigAuthenticationSuiteEnabled) { + *pu4Index = i; + return TRUE; + } + } + return FALSE; +} /* rsnSearchAKMSuite */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform RSNA or TSN policy +* selection for a given BSS. +* +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The RSNA/TSN policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The RSNA/TSN policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ +#if CFG_SUPPORT_802_11W + INT_32 i; + UINT_32 j; +#else + UINT_32 i, j; +#endif + BOOLEAN fgSuiteSupported; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_RSN_INFO_T prBssRsnInfo; + ENUM_NETWORK_TYPE_INDEX_T eNetwotkType; + BOOLEAN fgIsWpsActive = (BOOLEAN) FALSE; + + DEBUGFUNC("rsnPerformPolicySelection"); + + ASSERT(prBss); + + DBGLOG(RSN, TRACE, "rsnPerformPolicySelection\n"); + /* Todo:: */ + eNetwotkType = NETWORK_TYPE_AIS_INDEX; + + prBss->u4RsnSelectedPairwiseCipher = 0; + prBss->u4RsnSelectedGroupCipher = 0; + prBss->u4RsnSelectedAKMSuite = 0; + prBss->ucEncLevel = 0; + +#if CFG_SUPPORT_WPS + fgIsWpsActive = kalWSCGetActiveState(prAdapter->prGlueInfo); + + /* CR1640, disable the AP select privacy check */ + if (fgIsWpsActive && + (prAdapter->rWifiVar.rConnSettings.eAuthMode < AUTH_MODE_WPA) && + (prAdapter->rWifiVar.rConnSettings.eOPMode == NET_TYPE_INFRA)) { + DBGLOG(RSN, TRACE, "-- Skip the Protected BSS check\n"); + return TRUE; + } +#endif + + /* Protection is not required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(RSN, TRACE, "-- Protected BSS\n"); + return FALSE; + + } + + /* Protection is required in this BSS. */ + if ((prBss->u2CapInfo & CAP_INFO_PRIVACY) != 0) { + if (secEnabledInAis(prAdapter) == FALSE) { + DBGLOG(RSN, TRACE, "-- Protected BSS\n"); + return FALSE; + } + } + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_NONE) { + + if (prBss->fgIEWPA) { + prBssRsnInfo = &prBss->rWPAInfo; + } else { + DBGLOG(RSN, TRACE, "WPA Information Element does not exist.\n"); + return FALSE; + } + } else if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2 || + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK) { + + if (prBss->fgIERSN) { + prBssRsnInfo = &prBss->rRSNInfo; + } else { + DBGLOG(RSN, TRACE, "RSN Information Element does not exist.\n"); + return FALSE; + } + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus != ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, ignore this BSS. */ + DBGLOG(RSN, TRACE, "-- Not WEP-only legacy BSS %d\n", prAdapter->rWifiVar.rConnSettings.eEncStatus); + return FALSE; + } else if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) { + /* If the driver is configured to use WEP only, use this BSS. */ + DBGLOG(RSN, TRACE, "-- WEP-only legacy BSS, fgIERSN %d, fgIEWPA %d\n", + prBss->fgIERSN, prBss->fgIEWPA); + /* if this BSS was configured to WPA/WPA2, don't select this AP */ + return (prBss->fgIERSN || prBss->fgIEWPA) ? FALSE : TRUE; + } + + if (!rsnIsSuitableBSS(prAdapter, prBssRsnInfo)) { + DBGLOG(RSN, TRACE, "RSN info check no matched\n"); + return FALSE; + } + + if (prBssRsnInfo->u4PairwiseKeyCipherSuiteCount == 1 && + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[0]) == CIPHER_SUITE_NONE) { + /* Since the pairwise cipher use the same cipher suite as the group + cipher in the BSS, we check the group cipher suite against the + current encryption status. */ + fgSuiteSupported = FALSE; + + switch (prBssRsnInfo->u4GroupKeyCipherSuite) { + case WPA_CIPHER_SUITE_CCMP: + case RSN_CIPHER_SUITE_CCMP: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION3_ENABLED) + fgSuiteSupported = TRUE; + break; + + case WPA_CIPHER_SUITE_TKIP: + case RSN_CIPHER_SUITE_TKIP: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION2_ENABLED) + fgSuiteSupported = TRUE; + break; + + case WPA_CIPHER_SUITE_WEP40: + case WPA_CIPHER_SUITE_WEP104: + if (prAdapter->rWifiVar.rConnSettings.eEncStatus == ENUM_ENCRYPTION1_ENABLED) + fgSuiteSupported = TRUE; + break; + } + + if (fgSuiteSupported) { + u4PairwiseCipher = WPA_CIPHER_SUITE_NONE; + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } +#if DBG + else { + DBGLOG(RSN, TRACE, "Inproper encryption status %d for group-key-only BSS\n", + prAdapter->rWifiVar.rConnSettings.eEncStatus); + } +#endif + } else { + fgSuiteSupported = FALSE; + + DBGLOG(RSN, TRACE, "eEncStatus %d %d 0x%x\n", prAdapter->rWifiVar.rConnSettings.eEncStatus, + (UINT_32) prBssRsnInfo->u4PairwiseKeyCipherSuiteCount, + (UINT_32) prBssRsnInfo->au4PairwiseKeyCipherSuite[0]); + /* Select pairwise/group ciphers */ + switch (prAdapter->rWifiVar.rConnSettings.eEncStatus) { + case ENUM_ENCRYPTION3_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_CCMP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION2_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_TKIP) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == CIPHER_SUITE_CCMP) + DBGLOG(RSN, TRACE, "Cannot join CCMP BSS\n"); + else + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + break; + + case ENUM_ENCRYPTION1_ENABLED: + for (i = 0; i < prBssRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(prBssRsnInfo->au4PairwiseKeyCipherSuite[i]) + == CIPHER_SUITE_WEP104) { + u4PairwiseCipher = prBssRsnInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == + CIPHER_SUITE_CCMP || + GET_SELECTOR_TYPE(prBssRsnInfo->u4GroupKeyCipherSuite) == CIPHER_SUITE_TKIP) { + DBGLOG(RSN, TRACE, "Cannot join CCMP/TKIP BSS\n"); + } else { + u4GroupCipher = prBssRsnInfo->u4GroupKeyCipherSuite; + } + break; + + default: + break; + } + } + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + BSS, do not check the supported AKM suites. */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT + if ((prAdapter->fgIsP2PRegistered) && (eNetwotkType == NETWORK_TYPE_P2P_INDEX)) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { + DBGLOG(RSN, TRACE, "Failed to select pairwise/group cipher for P2P network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (eNetwotkType == NETWORK_TYPE_BOW_INDEX) { + if (u4PairwiseCipher != RSN_CIPHER_SUITE_CCMP || + u4GroupCipher != RSN_CIPHER_SUITE_CCMP || u4AkmSuite != RSN_AKM_SUITE_PSK) { + /* Do nothing */ + } + DBGLOG(RSN, TRACE, + "Failed to select pairwise/group cipher for BT over Wi-Fi network (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } +#endif + + /* Verify if selected pairwisse cipher is supported */ + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4PairwiseCipher, &i); + + /* Verify if selected group cipher is supported */ + if (fgSuiteSupported) + fgSuiteSupported = rsnSearchSupportedCipher(prAdapter, u4GroupCipher, &i); + + if (!fgSuiteSupported) { + DBGLOG(RSN, TRACE, "Failed to support selected pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + the given BSS, we fail to perform RSNA policy selection. */ + /* Attempt to find any overlapping supported AKM suite. */ +#if CFG_SUPPORT_802_11W + if (i != 0) + for (i = (prBssRsnInfo->u4AuthKeyMgtSuiteCount - 1); i >= 0; i--) { +#else + for (i = 0; i < prBssRsnInfo->u4AuthKeyMgtSuiteCount; i++) { +#endif + if (rsnSearchAKMSuite(prAdapter, prBssRsnInfo->au4AuthKeyMgtSuite[i], &j)) { + u4AkmSuite = prBssRsnInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(RSN, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(RSN, TRACE, "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(RSN, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); + +#if CFG_SUPPORT_802_11W + DBGLOG(RSN, TRACE, "MFP setting = %d\n ", kalGetMfpSetting(prAdapter->prGlueInfo)); + + if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) { + if (!prBssRsnInfo->fgRsnCapPresent) { + DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required Capability.\n"); + return FALSE; + } else if (!(prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC)) { + DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required\n"); + return FALSE; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + } else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) { + if (prBssRsnInfo->u2RsnCap && ((prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR) || + (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPC))) { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = TRUE; + } else { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + } + } else { + if (prBssRsnInfo->fgRsnCapPresent && (prBssRsnInfo->u2RsnCap & ELEM_WPA_CAP_MFPR)) { + DBGLOG(RSN, TRACE, "Skip RSN IE, No MFP Required Capability\n"); + return FALSE; + } + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection = FALSE; + } + DBGLOG(RSN, TRACE, "fgMgmtProtection = %d\n ", prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection); +#endif + + if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_CCMP) { + prBss->ucEncLevel = 3; + } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_TKIP) { + prBss->ucEncLevel = 2; + } else if (GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP40 || + GET_SELECTOR_TYPE(u4GroupCipher) == CIPHER_SUITE_WEP104) { + prBss->ucEncLevel = 1; + } else { + ASSERT(FALSE); + } + prBss->u4RsnSelectedPairwiseCipher = u4PairwiseCipher; + prBss->u4RsnSelectedGroupCipher = u4GroupCipher; + prBss->u4RsnSelectedAKMSuite = u4AkmSuite; + + return TRUE; + +} /* rsnPerformPolicySelection */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate WPA IE for beacon frame. +* +* \param[in] pucIeStartAddr Pointer to put the generated WPA IE. +* +* \return The append WPA-None IE length +* \note +* Called by: JOIN module, compose beacon IE +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWpaNoneIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + P_WPA_INFO_ELEM_T prWpaIE; + UINT_32 u4Suite; + UINT_16 u2SuiteCount; + PUINT_8 cp, cp2; + UINT_8 ucExpendedLen = 0; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + + DEBUGFUNC("rsnGenerateWpaNoneIE"); + + ASSERT(prMsduInfo); + + if (prAdapter->rWifiVar.rConnSettings.eAuthMode != AUTH_MODE_WPA_NONE) + return; + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + + if (eNetworkId != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + prWpaIE = (P_WPA_INFO_ELEM_T) (pucBuffer); + + /* Start to construct a WPA IE. */ + /* Fill the Element ID field. */ + prWpaIE->ucElemId = ELEM_ID_WPA; + + /* Fill the OUI and OUI Type fields. */ + prWpaIE->aucOui[0] = 0x00; + prWpaIE->aucOui[1] = 0x50; + prWpaIE->aucOui[2] = 0xF2; + prWpaIE->ucOuiType = VENDOR_OUI_TYPE_WPA; + + /* Fill the Version field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2Version, 1); /* version 1 */ + ucExpendedLen = 6; + + /* Fill the Pairwise Key Cipher Suite List field. */ + u2SuiteCount = 0; + cp = (PUINT_8) &prWpaIE->aucPairwiseKeyCipherSuite1[0]; + + if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_CCMP, &i)) + u4Suite = WPA_CIPHER_SUITE_CCMP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_TKIP, &i)) + u4Suite = WPA_CIPHER_SUITE_TKIP; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP104, &i)) + u4Suite = WPA_CIPHER_SUITE_WEP104; + else if (rsnSearchSupportedCipher(prAdapter, WPA_CIPHER_SUITE_WEP40, &i)) + u4Suite = WPA_CIPHER_SUITE_WEP40; + else + u4Suite = WPA_CIPHER_SUITE_TKIP; + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Group Key Cipher Suite field as the same in pair-wise key. */ + WLAN_SET_FIELD_32(&prWpaIE->u4GroupKeyCipherSuite, u4Suite); + ucExpendedLen += 4; + + /* Fill the Pairwise Key Cipher Suite Count field. */ + WLAN_SET_FIELD_16(&prWpaIE->u2PairwiseKeyCipherSuiteCount, u2SuiteCount); + ucExpendedLen += 2; + + cp2 = cp; + + /* Fill the Authentication and Key Management Suite List field. */ + u2SuiteCount = 0; + cp += 2; + + if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_802_1X, &i)) + u4Suite = WPA_AKM_SUITE_802_1X; + else if (rsnSearchAKMSuite(prAdapter, WPA_AKM_SUITE_PSK, &i)) + u4Suite = WPA_AKM_SUITE_PSK; + else + u4Suite = WPA_AKM_SUITE_NONE; + + /* This shall be the only available value for current implementation */ + ASSERT(u4Suite == WPA_AKM_SUITE_NONE); + + WLAN_SET_FIELD_32(cp, u4Suite); + u2SuiteCount++; + ucExpendedLen += 4; + cp += 4; + + /* Fill the Authentication and Key Management Suite Count field. */ + WLAN_SET_FIELD_16(cp2, u2SuiteCount); + ucExpendedLen += 2; + + /* Fill the Length field. */ + prWpaIE->ucLength = (UINT_8) ucExpendedLen; + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + +} /* rsnGenerateWpaNoneIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWPAIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUCHAR cp; + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo; + + DEBUGFUNC("rsnGenerateWPAIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + /* if (eNetworkId != NETWORK_TYPE_AIS_INDEX) */ + /* return; */ + +#if CFG_ENABLE_WIFI_DIRECT + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->fgIsP2PRegistered) && + (eNetworkId == NETWORK_TYPE_P2P_INDEX) && + (kalP2PGetTkipCipher(prAdapter->prGlueInfo)))) || + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK))) { +#else + if ((1 /* prCurrentBss->fgIEWPA */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA_PSK)))) { +#endif + if (prP2pSpecificBssInfo->u2WpaIeLen != 0) { + kalMemCopy(pucBuffer, prP2pSpecificBssInfo->aucWpaIeBuffer, prP2pSpecificBssInfo->u2WpaIeLen); + prMsduInfo->u2FrameLength += prP2pSpecificBssInfo->u2WpaIeLen; + return; + } + + /* Construct a WPA IE for association request frame. */ + WPA_IE(pucBuffer)->ucElemId = ELEM_ID_WPA; + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + WPA_IE(pucBuffer)->aucOui[0] = 0x00; + WPA_IE(pucBuffer)->aucOui[1] = 0x50; + WPA_IE(pucBuffer)->aucOui[2] = 0xF2; + WPA_IE(pucBuffer)->ucOuiType = VENDOR_OUI_TYPE_WPA; + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2Version, 1); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(&WPA_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedGroupCipher); + + cp = (PUCHAR) &WPA_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + + WLAN_SET_FIELD_16(&WPA_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(cp, WPA_CIPHER_SUITE_TKIP); + } else +#endif + WLAN_SET_FIELD_32(cp, + prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedPairwiseCipher); + cp += 4; + + WLAN_SET_FIELD_16(cp, 1); + cp += 2; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered && eNetworkId == NETWORK_TYPE_P2P_INDEX) { + WLAN_SET_FIELD_32(cp, WPA_AKM_SUITE_PSK); + } else +#endif + WLAN_SET_FIELD_32(cp, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].u4RsnSelectedAKMSuite); + cp += 4; + + WPA_IE(pucBuffer)->ucLength = ELEM_ID_WPA_LEN_FIXED; + + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* rsnGenerateWPAIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate RSN IE for +* associate request frame. +* +* \param[in] prMsduInfo The Selected BSS description +* +* \retval The append RSN IE length +* +* \note +* Called by: AIS module, P2P module, BOW module Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateRSNIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 u4Entry; + PUCHAR cp; + /* UINT_8 ucExpendedLen = 0; */ + PUINT_8 pucBuffer; + ENUM_NETWORK_TYPE_INDEX_T eNetworkId; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("rsnGenerateRSNIE"); + + ASSERT(prMsduInfo); + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + ASSERT(pucBuffer); + + /* Todo:: network id */ + eNetworkId = (ENUM_NETWORK_TYPE_INDEX_T) prMsduInfo->ucNetworkType; + + if ( +#if CFG_ENABLE_WIFI_DIRECT + ((prAdapter->fgIsP2PRegistered) && + (eNetworkId == NETWORK_TYPE_P2P_INDEX) && (kalP2PGetCcmpCipher(prAdapter->prGlueInfo))) || +#endif +#if CFG_ENABLE_BT_OVER_WIFI + (eNetworkId == NETWORK_TYPE_BOW_INDEX) || +#endif + (eNetworkId == NETWORK_TYPE_AIS_INDEX /* prCurrentBss->fgIERSN */ && + ((prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) || + (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2_PSK)))) { + /* Construct a RSN IE for association request frame. */ + RSN_IE(pucBuffer)->ucElemId = ELEM_ID_RSN; + RSN_IE(pucBuffer)->ucLength = ELEM_ID_RSN_LEN_FIXED; + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2Version, 1); /* Version */ + WLAN_SET_FIELD_32(&RSN_IE(pucBuffer)->u4GroupKeyCipherSuite, + prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedGroupCipher); /* Group key suite */ + cp = (PUCHAR) &RSN_IE(pucBuffer)->aucPairwiseKeyCipherSuite1[0]; + WLAN_SET_FIELD_16(&RSN_IE(pucBuffer)->u2PairwiseKeyCipherSuiteCount, 1); + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedPairwiseCipher); + cp += 4; + WLAN_SET_FIELD_16(cp, 1); /* AKM suite count */ + cp += 2; + WLAN_SET_FIELD_32(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u4RsnSelectedAKMSuite); /* AKM suite */ + cp += 4; + WLAN_SET_FIELD_16(cp, prAdapter->rWifiVar.arBssInfo[eNetworkId].u2RsnSelectedCapInfo);/* Capabilities */ +#if CFG_SUPPORT_802_11W + if (eNetworkId == NETWORK_TYPE_AIS_INDEX && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection) { + if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_REQUIRED) + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC | ELEM_WPA_CAP_MFPR); /* Capabilities */ + else if (kalGetMfpSetting(prAdapter->prGlueInfo) == RSN_AUTH_MFP_OPTIONAL) + WLAN_SET_FIELD_16(cp, ELEM_WPA_CAP_MFPC); /* Capabilities */ + } +#endif + cp += 2; + + if (eNetworkId == NETWORK_TYPE_AIS_INDEX) { + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + if (!prStaRec) { + DBGLOG(RSN, TRACE, "rsnGenerateRSNIE: prStaRec is NULL\n"); + return; + } + } + + if (eNetworkId == NETWORK_TYPE_AIS_INDEX && + rsnSearchPmkidEntry(prAdapter, prStaRec->aucMacAddr, &u4Entry)) { + /* DBGLOG(RSN, TRACE, ("Add Pmk at assoc req\n")); */ + /* DBGLOG(RSN, TRACE, ("addr %pM PMKID %pM\n", */ + /* (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arBSSID),*/ + /* (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].rBssidInfo.arPMKID))); */ + if (prAdapter->rWifiVar.rAisSpecificBssInfo.arPmkidCache[u4Entry].fgPmkidExist) { + RSN_IE(pucBuffer)->ucLength = 38; + WLAN_SET_FIELD_16(cp, 1); /* PMKID count */ + cp += 2; + DBGLOG(RSN, TRACE, + "BSSID %pM ind=%d\n", prStaRec->aucMacAddr, (UINT_32) u4Entry); + DBGLOG(RSN, TRACE, "use PMKID %pM\n", + (prAdapter->rWifiVar.rAisSpecificBssInfo. + arPmkidCache[u4Entry].rBssidInfo.arPMKID)); + kalMemCopy(cp, + (PVOID) prAdapter->rWifiVar.rAisSpecificBssInfo. + arPmkidCache[u4Entry].rBssidInfo.arPMKID, sizeof(PARAM_PMKID_VALUE)); + /* ucExpendedLen = 40; */ + } else { + WLAN_SET_FIELD_16(cp, 0); /* PMKID count */ + /* ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; */ +#if CFG_SUPPORT_802_11W + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; +#endif + } + } else { + WLAN_SET_FIELD_16(cp, 0); /* PMKID count */ + /* ucExpendedLen = ELEM_ID_RSN_LEN_FIXED + 2; */ +#if CFG_SUPPORT_802_11W + cp += 2; + RSN_IE(pucBuffer)->ucLength += 2; +#endif + } + +#if CFG_SUPPORT_802_11W + if ((eNetworkId == NETWORK_TYPE_AIS_INDEX) + && (kalGetMfpSetting(prAdapter->prGlueInfo) != + RSN_AUTH_MFP_DISABLED) /* (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) */) { + WLAN_SET_FIELD_32(cp, RSN_CIPHER_SUITE_AES_128_CMAC); + cp += 4; + RSN_IE(pucBuffer)->ucLength += 4; + } +#endif + prMsduInfo->u2FrameLength += IE_SIZE(pucBuffer); + } + +} /* rsnGenerateRSNIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the given IE buffer and check if it is WFA IE and return Type and +* SubType for further process. +* +* \param[in] pucBuf Pointer to the buffer of WFA Information Element. +* \param[out] pucOuiType Pointer to the storage of OUI Type. +* \param[out] pu2SubTypeVersion Pointer to the storage of OUI SubType and Version. + +* \retval TRUE Parse IE ok +* \retval FALSE Parse IE fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +rsnParseCheckForWFAInfoElem(IN P_ADAPTER_T prAdapter, + IN PUINT_8 pucBuf, OUT PUINT_8 pucOuiType, OUT PUINT_16 pu2SubTypeVersion) +{ + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_IE_WFA_T prWfaIE; + + ASSERT(pucBuf); + ASSERT(pucOuiType); + ASSERT(pu2SubTypeVersion); + prWfaIE = (P_IE_WFA_T) pucBuf; + + do { + if (IE_LEN(pucBuf) <= ELEM_MIN_LEN_WFA_OUI_TYPE_SUBTYPE) { + break; + } else if (prWfaIE->aucOui[0] != aucWfaOui[0] || + prWfaIE->aucOui[1] != aucWfaOui[1] || prWfaIE->aucOui[2] != aucWfaOui[2]) { + break; + } + + *pucOuiType = prWfaIE->ucOuiType; + WLAN_GET_FIELD_16(&prWfaIE->aucOuiSubTypeVersion[0], pu2SubTypeVersion); + + return TRUE; + } while (FALSE); + + return FALSE; + +} /* end of rsnParseCheckForWFAInfoElem() */ + +#if CFG_SUPPORT_AAA +/*----------------------------------------------------------------------------*/ +/*! +* \brief Parse the given IE buffer and check if it is RSN IE with CCMP PSK +* +* \param[in] prAdapter Pointer to Adapter +* \param[in] prSwRfb Pointer to the rx buffer +* \param[in] pIE Pointer rthe buffer of Information Element. +* \param[out] prStatusCode Pointer to the return status code. + +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void rsnParserCheckForRSNCCMPPSK(P_ADAPTER_T prAdapter, P_RSN_INFO_ELEM_T prIe, PUINT_16 pu2StatusCode) +{ + + RSN_INFO_T rRsnIe; + + ASSERT(prAdapter); + ASSERT(prIe); + ASSERT(pu2StatusCode); + + *pu2StatusCode = STATUS_CODE_INVALID_INFO_ELEMENT; + + if (rsnParseRsnIE(prAdapter, prIe, &rRsnIe)) { + if ((rRsnIe.u4PairwiseKeyCipherSuiteCount != 1) + || (rRsnIe.au4PairwiseKeyCipherSuite[0] != RSN_CIPHER_SUITE_CCMP)) { + *pu2StatusCode = STATUS_CODE_INVALID_PAIRWISE_CIPHER; + return; + } + if (rRsnIe.u4GroupKeyCipherSuite != RSN_CIPHER_SUITE_CCMP) { + *pu2StatusCode = STATUS_CODE_INVALID_GROUP_CIPHER; + return; + } + if ((rRsnIe.u4AuthKeyMgtSuiteCount != 1) || (rRsnIe.au4AuthKeyMgtSuite[0] != RSN_AKM_SUITE_PSK)) { + *pu2StatusCode = STATUS_CODE_INVALID_AKMP; + return; + } + + DBGLOG(RSN, TRACE, "RSN with CCMP-PSK\n"); + *pu2StatusCode = WLAN_STATUS_SUCCESS; + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate an authentication event to NDIS. +* +* \param[in] u4Flags Authentication event: \n +* PARAM_AUTH_REQUEST_REAUTH 0x01 \n +* PARAM_AUTH_REQUEST_KEYUPDATE 0x02 \n +* PARAM_AUTH_REQUEST_PAIRWISE_ERROR 0x06 \n +* PARAM_AUTH_REQUEST_GROUP_ERROR 0x0E \n +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenMicErrorEvent(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgFlags) +{ + P_PARAM_AUTH_EVENT_T prAuthEvent; + + DEBUGFUNC("rsnGenMicErrorEvent"); + + prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, + (PVOID) prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucBSSID, MAC_ADDR_LEN); + + if (fgFlags == TRUE) + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); + +} /* rsnGenMicErrorEvent */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to handle TKIP MIC failures. +* +* \param[in] adapter_p Pointer to the adapter object data area. +* \param[in] prSta Pointer to the STA which occur MIC Error +* \param[in] fgErrorKeyType type of error key +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnTkipHandleMICFailure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN BOOLEAN fgErrorKeyType) +{ + /* UINT_32 u4RsnaCurrentMICFailTime; */ + /* P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; */ + + DEBUGFUNC("rsnTkipHandleMICFailure"); + + ASSERT(prAdapter); +#if 1 + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + + nicConfigPowerSaveProfile(prAdapter, NETWORK_TYPE_AIS_INDEX, Param_PowerModeCAM, FALSE); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); +#else + ASSERT(prSta); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Record the MIC error occur time. */ + GET_CURRENT_SYSTIME(&u4RsnaCurrentMICFailTime); + + /* Generate authentication request event. */ + DBGLOG(RSN, INFO, "Generate TKIP MIC error event (type: 0%d)\n", fgErrorKeyType); + + /* If less than 60 seconds have passed since a previous TKIP MIC failure, + disassociate from the AP and wait for 60 seconds before (re)associating + with the same AP. */ + if (prAisSpecBssInfo->u4RsnaLastMICFailTime != 0 && + !CHECK_FOR_TIMEOUT(u4RsnaCurrentMICFailTime, + prAisSpecBssInfo->u4RsnaLastMICFailTime, SEC_TO_SYSTIME(TKIP_COUNTERMEASURE_SEC))) { + /* If less than 60 seconds expired since last MIC error, we have to + block traffic. */ + + DBGLOG(RSN, INFO, "Start blocking traffic!\n"); + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + + secFsmEventStartCounterMeasure(prAdapter, prSta); + } else { + rsnGenMicErrorEvent(prAdapter, /* prSta, */ fgErrorKeyType); + DBGLOG(RSN, INFO, "First TKIP MIC error!\n"); + } + + COPY_SYSTIME(prAisSpecBssInfo->u4RsnaLastMICFailTime, u4RsnaCurrentMICFailTime); +#endif +} /* rsnTkipHandleMICFailure */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS Desc at scan result list +* \param[out] pu4CandidateCount Pointer to the number of selected candidates. +* It is set to zero if no BSSID matches our requirement. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnSelectPmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("rsnSelectPmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + + /* Search a BSS with the same SSID from the given BSS description set. */ + /* DBGLOG(RSN, TRACE, ("Check scan result [%pM]\n", */ + /* prBssDesc->aucBSSID)); */ + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, "-- SSID not matched\n"); + return; + } +#if 0 + if ((prBssDesc->u2BSSBasicRateSet & + ~(rPhyAttributes[prAisBssInfo->ePhyType].u2SupportedRateSet)) || prBssDesc->fgIsUnknownBssBasicRate) { + DBGLOG(RSN, TRACE, "-- Rate set not matched\n"); + return; + } + + if (/* prBssDesc->u4RsnSelectedPairwiseCipher != prAisBssInfo->u4RsnSelectedPairwiseCipher || */ + prBssDesc->u4RsnSelectedGroupCipher != prAisBssInfo->u4RsnSelectedGroupCipher /*|| + prBssDesc->u4RsnSelectedAKMSuite != prAisBssInfo->u4RsnSelectedAKMSuite */) { + DBGLOG(RSN, TRACE, "-- Encrypt status not matched for PMKID\n"); + return; + } +#endif + + rsnUpdatePmkidCandidateList(prAdapter, prBssDesc); + +} /* rsnSelectPmkidCandidateList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to select a list of BSSID from +* the scan results for PMKID candidate list. +* +* \param[in] prBssDesc the BSS DESC at scan result list +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnUpdatePmkidCandidateList(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc) +{ + UINT_32 i; + P_CONNECTION_SETTINGS_T prConnSettings; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnUpdatePmkidCandidateList"); + + ASSERT(prBssDesc); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (UNEQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + DBGLOG(RSN, TRACE, "-- SSID not matched\n"); + return; + } + + for (i = 0; i < CFG_MAX_PMKID_CACHE; i++) { + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)) + return; + } + + /* If the number of selected BSSID exceed MAX_NUM_PMKID_CACHE(16), + then we only store MAX_NUM_PMKID_CACHE(16) in PMKID cache */ + if ((prAisSpecBssInfo->u4PmkidCandicateCount + 1) > CFG_MAX_PMKID_CACHE) + prAisSpecBssInfo->u4PmkidCandicateCount--; + + i = prAisSpecBssInfo->u4PmkidCandicateCount; + + COPY_MAC_ADDR((PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, (PVOID) prBssDesc->aucBSSID); + + if (prBssDesc->u2RsnCap & MASK_RSNIE_CAP_PREAUTH) { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 1; + DBGLOG(RSN, TRACE, "Add %pM with pre-auth to candidate list\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + } else { + prAisSpecBssInfo->arPmkidCandicate[i].u4PreAuthFlags = 0; + DBGLOG(RSN, TRACE, "Add %pM without pre-auth to candidate list\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + } + + prAisSpecBssInfo->u4PmkidCandicateCount++; + +} /* rsnUpdatePmkidCandidateList */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search the desired entry in +* PMKID cache according to the BSSID +* +* \param[in] pucBssid Pointer to the BSSID +* \param[out] pu4EntryIndex Pointer to place the found entry index +* +* \retval TRUE, if found one entry for specified BSSID +* \retval FALSE, if not found +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnSearchPmkidEntry(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBssid, OUT PUINT_32 pu4EntryIndex) +{ + UINT_32 i; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + DEBUGFUNC("rsnSearchPmkidEntry"); + + ASSERT(pucBssid); + ASSERT(pu4EntryIndex); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if (prAisSpecBssInfo->u4PmkidCacheCount > CFG_MAX_PMKID_CACHE) + return FALSE; + + ASSERT(prAisSpecBssInfo->u4PmkidCacheCount <= CFG_MAX_PMKID_CACHE); + + /* Search for desired BSSID */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCacheCount; i++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[i].rBssidInfo.arBSSID, pucBssid, MAC_ADDR_LEN)) + break; + } + + /* If desired BSSID is found, then set the PMKID */ + if (i < prAisSpecBssInfo->u4PmkidCacheCount) { + *pu4EntryIndex = i; + + return TRUE; + } + + return FALSE; +} /* rsnSearchPmkidEntry */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check if there is difference +* between PMKID candicate list and PMKID cache. If there +* is new candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \retval TRUE, if new member in the PMKID candicate list +* \retval FALSe, if no new member in the PMKID candicate list +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnCheckPmkidCandicate(IN P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + UINT_32 i; /* Index for PMKID candicate */ + UINT_32 j; /* Indix for PMKID cache */ + BOOLEAN status = FALSE; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + /* Check for each candicate */ + for (i = 0; i < prAisSpecBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecBssInfo->u4PmkidCacheCount; j++) { + if (!kalMemCmp(prAisSpecBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN)) { + /* DBGLOG(RSN, TRACE, ("%pM at PMKID cache!!\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid))); */ + break; + } + } + + /* No entry found in PMKID cache for the candicate, add new one */ + if (j == prAisSpecBssInfo->u4PmkidCacheCount + && prAisSpecBssInfo->u4PmkidCacheCount < CFG_MAX_PMKID_CACHE) { + DBGLOG(RSN, TRACE, + "Add %pM to PMKID cache!!\n", + (prAisSpecBssInfo->arPmkidCandicate[i].aucBssid)); + kalMemCopy((PVOID) prAisSpecBssInfo-> + arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].rBssidInfo.arBSSID, + (PVOID) prAisSpecBssInfo->arPmkidCandicate[i].aucBssid, MAC_ADDR_LEN); + prAisSpecBssInfo->arPmkidCache[prAisSpecBssInfo->u4PmkidCacheCount].fgPmkidExist = FALSE; + prAisSpecBssInfo->u4PmkidCacheCount++; + + status = TRUE; + } + } + + return status; +} /* rsnCheckPmkidCandicate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to wait a duration to indicate the pre-auth AP candicate +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnIndicatePmkidCand(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) +{ + DBGLOG(RSN, EVENT, "Security - Time to indicate the PMKID cand.\n"); + + /* If the authentication mode is WPA2 and indication PMKID flag + is available, then we indicate the PMKID candidate list to NDIS and + clear the flag, indicatePMKID */ + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnGeneratePmkidIndication(prAdapter); + } + +} /* end of rsnIndicatePmkidCand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check the BSS Desc at scan result +* with pre-auth cap at wpa2 mode. If there +* is candicate that no cache entry is available, then +* add a new entry for the new candicate in the PMKID cache +* and set the PMKID indication flag to TRUE. +* +* \param[in] prBss The BSS Desc at scan result +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnCheckPmkidCache(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + P_AIS_BSS_INFO_T prAisBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + + DEBUGFUNC("rsnCheckPmkidCandicate"); + + ASSERT(prBss); + + prConnSettings = &prAdapter->rWifiVar.rConnSettings; + prAisBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + if ((prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) && + (prConnSettings->eAuthMode == AUTH_MODE_WPA2)) { + rsnSelectPmkidCandidateList(prAdapter, prBss); + + /* Set indication flag of PMKID to TRUE, and then connHandleNetworkConnection() + will indicate this later */ + if (rsnCheckPmkidCandicate(prAdapter)) { + DBGLOG(RSN, TRACE, "Prepare a timer to indicate candidate PMKID Candidate\n"); + cnmTimerStopTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(prAdapter, &prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC(WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to generate an PMKID candidate list +* indication to NDIS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] u4Flags PMKID candidate list event: +* PARAM_PMKID_CANDIDATE_PREAUTH_ENABLED 0x01 +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGeneratePmkidIndication(IN P_ADAPTER_T prAdapter) +{ + P_PARAM_STATUS_INDICATION_T prStatusEvent; + P_PARAM_PMKID_CANDIDATE_LIST_T prPmkidEvent; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecificBssInfo; + UINT_8 i, j = 0, count = 0; + UINT_32 u4LenOfUsedBuffer; + + DEBUGFUNC("rsnGeneratePmkidIndication"); + + ASSERT(prAdapter); + + prStatusEvent = (P_PARAM_STATUS_INDICATION_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: PMKID Candidatelist Event */ + prStatusEvent->eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + ASSERT(prStatusEvent); + + prPmkidEvent = (P_PARAM_PMKID_CANDIDATE_LIST_T) (&prStatusEvent->eStatusType + 1); + ASSERT(prPmkidEvent); + + prAisSpecificBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prAisSpecificBssInfo); + + for (i = 0; i < prAisSpecificBssInfo->u4PmkidCandicateCount; i++) { + for (j = 0; j < prAisSpecificBssInfo->u4PmkidCacheCount; j++) { + if (EQUAL_MAC_ADDR(prAisSpecificBssInfo->arPmkidCache[j].rBssidInfo.arBSSID, + prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid) && + (prAisSpecificBssInfo->arPmkidCache[j].fgPmkidExist == TRUE)) { + break; + } + } + if (count >= CFG_MAX_PMKID_CACHE) + break; + + if (j == prAisSpecificBssInfo->u4PmkidCacheCount) { + kalMemCopy((PVOID) prPmkidEvent->arCandidateList[count].arBSSID, + (PVOID) prAisSpecificBssInfo->arPmkidCandicate[i].aucBssid, PARAM_MAC_ADDR_LEN); + prPmkidEvent->arCandidateList[count].u4Flags = + prAisSpecificBssInfo->arPmkidCandicate[i].u4PreAuthFlags; + DBGLOG(RSN, TRACE, "%pM %d\n", (prPmkidEvent->arCandidateList[count].arBSSID), + (UINT_32) prPmkidEvent->arCandidateList[count].u4Flags); + count++; + } + } + + /* PMKID Candidate List */ + prPmkidEvent->u4Version = 1; + prPmkidEvent->u4NumCandidates = count; + DBGLOG(RSN, TRACE, "rsnGeneratePmkidIndication #%d\n", (UINT_32) prPmkidEvent->u4NumCandidates); + u4LenOfUsedBuffer = sizeof(ENUM_STATUS_TYPE_T) + (2 * sizeof(UINT_32)) + + (count * sizeof(PARAM_PMKID_CANDIDATE_T)); + /* dumpMemory8((PUINT_8)prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); */ + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAdapter->aucIndicationEventBuffer, u4LenOfUsedBuffer); + +} /* rsnGeneratePmkidIndication */ +#endif + +#if CFG_SUPPORT_WPS2 +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WSC IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WSC IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID rsnGenerateWSCIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + (UINT_32) prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 221 :0xDD */ + if (prAdapter->prGlueInfo->u2WSCAssocInfoIELen) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWSCAssocInfoIE, + prAdapter->prGlueInfo->u2WSCAssocInfoIELen); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WSCAssocInfoIELen; + } + +} +#endif + +#if CFG_SUPPORT_802_11W + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the Bip Key installed or not +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 rsnCheckBipKeyInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + if (prStaRec && prStaRec->ucNetTypeIndex == (UINT_8) NETWORK_TYPE_AIS_INDEX) + return prAdapter->rWifiVar.rAisSpecificBssInfo.fgBipKeyInstalled; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to check the Sa query timeout. +* +* +* \note +* Called by: AIS module, Handle by Sa Quert timeout +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 rsnCheckSaQueryTimeout(IN P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + UINT_32 now; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + GET_CURRENT_SYSTIME(&now); + + if (CHECK_FOR_TIMEOUT(now, prBssSpecInfo->u4SaQueryStart, TU_TO_MSEC(1000))) { + LOG_FUNC("association SA Query timed out\n"); + + prBssSpecInfo->ucSaQueryTimedOut = 1; + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + prBssSpecInfo->pucSaQueryTransId = NULL; + prBssSpecInfo->u4SaQueryCount = 0; + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + /* Re-connect */ + DBGLOG(RSN, TRACE, "DisBy11w\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query timer. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStartSaQueryTimer(IN P_ADAPTER_T prAdapter) +{ + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prTxFrame; + UINT_16 u2PayloadLen; + PUINT_8 pucTmp = NULL; + UINT_8 ucTransId[ACTION_SA_QUERY_TR_ID_LEN]; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + ASSERT(prBssInfo); + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + LOG_FUNC("MFP: Start Sa Query\n"); + + if (prBssSpecInfo->u4SaQueryCount > 0 && rsnCheckSaQueryTimeout(prAdapter)) { + LOG_FUNC("MFP: u4SaQueryCount count =%d\n", prBssSpecInfo->u4SaQueryCount); + return; + } + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_REQUEST; + + if (prBssSpecInfo->u4SaQueryCount == 0) + GET_CURRENT_SYSTIME(&prBssSpecInfo->u4SaQueryStart); + + if (prBssSpecInfo->u4SaQueryCount) { + pucTmp = kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!pucTmp) { + DBGLOG(RSN, ERROR, "MFP: Fail to alloc tmp buffer for backup sa query id\n"); + return; + } + kalMemCopy(pucTmp, prBssSpecInfo->pucSaQueryTransId, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + } + + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + + ucTransId[0] = (UINT_8) (kalRandomNumber() & 0xFF); + ucTransId[1] = (UINT_8) (kalRandomNumber() & 0xFF); + + kalMemCopy(prTxFrame->ucTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + prBssSpecInfo->u4SaQueryCount++; + + prBssSpecInfo->pucSaQueryTransId = + kalMemAlloc(prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN, VIR_MEM_TYPE); + if (!prBssSpecInfo->pucSaQueryTransId) { + DBGLOG(RSN, ERROR, "MFP: Fail to alloc buffer for sa query id list\n"); + return; + } + + if (pucTmp) { + kalMemCopy(prBssSpecInfo->pucSaQueryTransId, pucTmp, + (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + kalMemCopy(&prBssSpecInfo->pucSaQueryTransId + [(prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN], ucTransId, + ACTION_SA_QUERY_TR_ID_LEN); + kalMemFree(pucTmp, VIR_MEM_TYPE, (prBssSpecInfo->u4SaQueryCount - 1) * ACTION_SA_QUERY_TR_ID_LEN); + } else { + kalMemCopy(prBssSpecInfo->pucSaQueryTransId, ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + } + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + DBGLOG(RSN, TRACE, + "Set SA Query timer %d (%d sec)\n", prBssSpecInfo->u4SaQueryCount, prBssInfo->u2ObssScanInterval); + + cnmTimerStartTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer, TU_TO_MSEC(201)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to start the 802.11w sa query. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStartSaQuery(IN P_ADAPTER_T prAdapter) +{ + rsnStartSaQueryTimer(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to stop the 802.11w sa query. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnStopSaQuery(IN P_ADAPTER_T prAdapter) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + cnmTimerStopTimer(prAdapter, &prBssSpecInfo->rSaQueryTimer); + kalMemFree(prBssSpecInfo->pucSaQueryTransId, VIR_MEM_TYPE, + prBssSpecInfo->u4SaQueryCount * ACTION_SA_QUERY_TR_ID_LEN); + prBssSpecInfo->pucSaQueryTransId = NULL; + prBssSpecInfo->u4SaQueryCount = 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnSaQueryRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + P_MSDU_INFO_T prMsduInfo; + P_ACTION_SA_QUERY_FRAME prRxFrame = NULL; + UINT_16 u2PayloadLen; + P_STA_RECORD_T prStaRec; + P_ACTION_SA_QUERY_FRAME prTxFrame; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]; + ASSERT(prBssInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + DBGLOG(RSN, TRACE, "IEEE 802.11: Received SA Query Request from %pM\n", prStaRec->aucMacAddr); + + DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) == PARAM_MEDIA_STATE_DISCONNECTED) { + DBGLOG(RSN, TRACE, "IEEE 802.11: Ignore SA Query Request from unassociated STA %pM\n", + prStaRec->aucMacAddr); + return; + } + DBGLOG(RSN, TRACE, "IEEE 802.11: Sending SA Query Response to %pM\n", prStaRec->aucMacAddr); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_SA_QUERY_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + /* SA Query always with protected */ + prTxFrame->u2FrameCtrl |= MASK_FC_PROTECTED_FRAME; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prBssInfo->aucBSSID); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_SA_QUERT_ACTION; + prTxFrame->ucAction = ACTION_SA_QUERY_RESPONSE; + + kalMemCopy(prTxFrame->ucTransId, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + u2PayloadLen = 2 + ACTION_SA_QUERY_TR_ID_LEN; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfo->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = FALSE; + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w sa query action frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +void rsnSaQueryAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_AIS_SPECIFIC_BSS_INFO_T prBssSpecInfo; + P_ACTION_SA_QUERY_FRAME prRxFrame; + P_STA_RECORD_T prStaRec; + UINT_32 i; + + prBssSpecInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + ASSERT(prBssSpecInfo); + + prRxFrame = (P_ACTION_SA_QUERY_FRAME) prSwRfb->pvHeader; + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prSwRfb->u2PacketLen < ACTION_SA_QUERY_TR_ID_LEN) { + DBGLOG(RSN, TRACE, "IEEE 802.11: Too short SA Query Action frame (len=%u)\n", + prSwRfb->u2PacketLen); + return; + } + + if (prRxFrame->ucAction == ACTION_SA_QUERY_REQUEST) { + rsnSaQueryRequest(prAdapter, prSwRfb); + return; + } + + if (prRxFrame->ucAction != ACTION_SA_QUERY_RESPONSE) { + DBGLOG(RSN, TRACE, "IEEE 802.11: Unexpected SA Query " "Action %d\n", prRxFrame->ucAction); + return; + } + + DBGLOG(RSN, TRACE, "IEEE 802.11: Received SA Query Response from %pM\n", prStaRec->aucMacAddr); + + DBGLOG_MEM8(RSN, TRACE, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + + for (i = 0; i < prBssSpecInfo->u4SaQueryCount; i++) { + if (kalMemCmp(prBssSpecInfo->pucSaQueryTransId + + i * ACTION_SA_QUERY_TR_ID_LEN, prRxFrame->ucTransId, ACTION_SA_QUERY_TR_ID_LEN) == 0) + break; + } + + if (i >= prBssSpecInfo->u4SaQueryCount) { + DBGLOG(RSN, TRACE, "IEEE 802.11: No matching SA Query " "transaction identifier found\n"); + return; + } + + DBGLOG(RSN, TRACE, "Reply to pending SA Query received\n"); + + rsnStopSaQuery(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11w mgmt frame. +* +* +* \note +* Called by: AIS module, Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN rsnCheckRxMgmt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN UINT_8 ucSubtype) +{ + P_HIF_RX_HEADER_T prHifRxHdr; + BOOLEAN fgUnicast = TRUE; + BOOLEAN fgRobustAction = FALSE; + + prHifRxHdr = prSwRfb->prHifRxHdr; + + if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) && + prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + + P_WLAN_ASSOC_REQ_FRAME_T prAssocReqFrame; + + prAssocReqFrame = (P_WLAN_ASSOC_REQ_FRAME_T) prSwRfb->pvHeader; + + if (prAssocReqFrame->aucDestAddr[0] & BIT(0)) + fgUnicast = FALSE; + + LOG_FUNC("QM RX MGT: rsnCheckRxMgmt = %d 0x%x %d ucSubtype=%x\n", fgUnicast, prHifRxHdr->ucReserved, + (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC), ucSubtype); + + if (prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC) { + /* "Dropped unprotected Robust Action frame from an MFP STA" */ + /* exclude Public Action */ + if (ucSubtype == 13 /* 0x1011: MAC_FRAME_ACTION */) { + UINT_8 ucAction = *prSwRfb->pucRecvBuff; + + if (ucAction != CATEGORY_PUBLIC_ACTION && ucAction != CATEGORY_HT_ACTION) { +#if DBG && CFG_RX_PKTS_DUMP + LOG_FUNC("QM RX MGT: UnProtected Robust Action frame = %d\n", ucAction); +#endif + fgRobustAction = TRUE; + return TRUE; + } + } + if (fgUnicast && ((ucSubtype == 10 /* 0x1010: MAC_FRAME_DISASSOC */) + || (ucSubtype == 12 /* 0x1100: MAC_FRAME_DEAUTH */))) { + LOG_FUNC("QM RX MGT: rsnStartSaQuery\n"); + /* MFP test plan 5.3.3.5 */ + rsnStartSaQuery(prAdapter); + return TRUE; + } + } +#if 0 + else { + if (fgUnicast && ((ucSubtype == MAC_FRAME_DISASSOC) || (ucSubtype == MAC_FRAME_DEAUTH))) { + /* This done by function handler */ + /* kalIndicateStatusAndComplete(prAdapter->prGlueInfo, */ + /* WLAN_STATUS_MEDIA_DISCONNECT, */ + /* NULL, */ + /* 0); */ + } + } +#endif + } + return FALSE; +} +#endif + +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE +static BOOLEAN rsnCheckWpaRsnInfo(P_BSS_INFO_T prBss, P_RSN_INFO_T prWpaRsnInfo) +{ + UINT_32 i = 0; + + if (prWpaRsnInfo->u4GroupKeyCipherSuite != prBss->u4RsnSelectedGroupCipher) { + DBGLOG(RSN, INFO, "GroupCipherSuite change, old=0x%04x, new=0x%04x\n", + prBss->u4RsnSelectedGroupCipher, prWpaRsnInfo->u4GroupKeyCipherSuite); + return TRUE; + } + for (; i < prWpaRsnInfo->u4AuthKeyMgtSuiteCount; i++) + if (prBss->u4RsnSelectedAKMSuite == prWpaRsnInfo->au4AuthKeyMgtSuite[i]) + break; + if (i == prWpaRsnInfo->u4AuthKeyMgtSuiteCount) { + DBGLOG(RSN, INFO, "KeyMgmt change, not find 0x%04x in new beacon\n", prBss->u4RsnSelectedAKMSuite); + return TRUE; + } + + for (i = 0; i < prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount; i++) + if (prBss->u4RsnSelectedPairwiseCipher == prWpaRsnInfo->au4PairwiseKeyCipherSuite[i]) + break; + if (i == prWpaRsnInfo->u4PairwiseKeyCipherSuiteCount) { + DBGLOG(RSN, INFO, "Pairwise Cipher change, not find 0x%04x in new beacon\n", + prBss->u4RsnSelectedPairwiseCipher); + return TRUE; + } + + return FALSE; +} + +BOOLEAN rsnCheckSecurityModeChanged(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo, P_BSS_DESC_T prBssDesc) +{ + ENUM_PARAM_AUTH_MODE_T eAuthMode = prAdapter->rWifiVar.rConnSettings.eAuthMode; + + switch (eAuthMode) { + case AUTH_MODE_OPEN: /* original is open system */ + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) && !prAdapter->prGlueInfo->rWpaInfo.fgPrivacyInvoke) { + DBGLOG(RSN, INFO, "security change, open->privacy\n"); + return TRUE; + } + break; + case AUTH_MODE_SHARED: /* original is WEP */ + case AUTH_MODE_AUTO_SWITCH: + if ((prBssDesc->u2CapInfo & CAP_INFO_PRIVACY) == 0) { + DBGLOG(RSN, INFO, "security change, WEP->open\n"); + return TRUE; + } else if (prBssDesc->fgIERSN || prBssDesc->fgIEWPA) { + DBGLOG(RSN, INFO, "security change, WEP->WPA/WPA2\n"); + return TRUE; + } + break; + case AUTH_MODE_WPA: /*original is WPA */ + case AUTH_MODE_WPA_PSK: + case AUTH_MODE_WPA_NONE: + if (prBssDesc->fgIEWPA) + return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rWPAInfo); + DBGLOG(RSN, INFO, "security change, WPA->%s\n", + prBssDesc->fgIERSN ? "WPA2" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); + return TRUE; + case AUTH_MODE_WPA2: /*original is WPA2 */ + case AUTH_MODE_WPA2_PSK: + if (prBssDesc->fgIERSN) + return rsnCheckWpaRsnInfo(prBssInfo, &prBssDesc->rRSNInfo); + DBGLOG(RSN, INFO, "security change, WPA2->%s\n", + prBssDesc->fgIEWPA ? "WPA" : + (prBssDesc->u2CapInfo & CAP_INFO_PRIVACY ? "WEP" : "OPEN")); + return TRUE; + default: + DBGLOG(RSN, WARN, "unknowned eAuthMode=%d\n", eAuthMode); + break; + } + /*DBGLOG(RSN, INFO, ("rsnCheckSecurityModeChanged, eAuthMode=%d, u2CapInfo=0x%02x, fgIEWPA=%d, fgIERSN=%d\n", + eAuthMode, prBssDesc->u2CapInfo, prBssDesc->fgIEWPA, prBssDesc->fgIERSN)); */ + return FALSE; +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c new file mode 100644 index 0000000000000..596ede60d7887 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/saa_fsm.c @@ -0,0 +1,1788 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/saa_fsm.c#2 +*/ + +/*! \file "saa_fsm.c" + \brief This file defines the FSM for SAA MODULE. + + This file defines the FSM for SAA MODULE. +*/ + +/* +** Log: saa_fsm.c +** +** 09 04 2013 cp.wu +** fix typo +** +** 09 03 2013 cp.wu +** add path for reassociation + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 04 20 2012 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * correct macro + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 04 2011 cp.wu + * [WCXRP00001086] [MT6620 Wi-Fi][Driver] On Android, indicate an extra DISCONNECT + * for REASSOCIATED cases as an explicit trigger for Android framework + * 1. for DEAUTH/DISASSOC cases, indicate for DISCONNECTION immediately. + * 2. (Android only) when reassociation-and-non-roaming cases happened, + * indicate an extra DISCONNECT indication to Android Wi-Fi framework + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 09 30 2011 cm.chang + * [WCXRP00001020] [MT6620 Wi-Fi][Driver] Handle secondary channel offset of AP in 5GHz band + * Add debug message about 40MHz bandwidth allowed + * + * 05 12 2011 cp.wu + * [WCXRP00000720] [MT6620 Wi-Fi][Driver] Do not do any further operation in case STA-REC + * has been invalidated before SAA-FSM starts to roll + * check for valid STA-REC before SAA-FSM starts to roll. + * + * 04 21 2011 terry.wu + * [WCXRP00000674] [MT6620 Wi-Fi][Driver] Refine AAA authSendAuthFrame + * Add network type parameter to authSendAuthFrame. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 03 31 2011 puff.wen + * NULL + * . + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix compile error of after Station Type Macro modification. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC + * for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete + * and might leads to BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 24 2010 chinghwa.yu + * NULL + * Update for MID_SCN_BOW_SCAN_DONE mboxDummy. + * Update saa_fsm for BOW. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 02 2010 yuche.tsai + * NULL + * Add support for P2P join event start. + * + * 07 12 2010 cp.wu + * + * SAA will take a record for tracking request sequence number. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * AIS-FSM integration with CNM channel request messages + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with main branch for resetting to state 1 when associating with another AP + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration the security related function from firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error when enable WiFi Direct function. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * + * * * Add Connection Policy - Any and Rx Burst Deauth Support for WHQL + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support of Driver STA_RECORD_T activation + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 12 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Fix compile warning due to declared but not used + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Refine Debug Label + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update comment + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * rename the function + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugAAState[AA_STATE_NUM] = { + (PUINT_8) DISP_STRING("AA_STATE_IDLE"), + (PUINT_8) DISP_STRING("SAA_STATE_SEND_AUTH1"), + (PUINT_8) DISP_STRING("SAA_STATE_WAIT_AUTH2"), + (PUINT_8) DISP_STRING("SAA_STATE_SEND_AUTH3"), + (PUINT_8) DISP_STRING("SAA_STATE_WAIT_AUTH4"), + (PUINT_8) DISP_STRING("SAA_STATE_SEND_ASSOC1"), + (PUINT_8) DISP_STRING("SAA_STATE_WAIT_ASSOC2"), + (PUINT_8) DISP_STRING("AAA_STATE_SEND_AUTH2"), + (PUINT_8) DISP_STRING("AAA_STATE_SEND_AUTH4"), + (PUINT_8) DISP_STRING("AAA_STATE_SEND_ASSOC2"), + (PUINT_8) DISP_STRING("AA_STATE_RESOURCE") +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief The Core FSM engine of SAA Module. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] eNextState The value of Next State +* @param[in] prRetainedSwRfb Pointer to the retained SW_RFB_T for JOIN Success +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +saaFsmSteps(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN ENUM_AA_STATE_T eNextState, IN P_SW_RFB_T prRetainedSwRfb) +{ + ENUM_AA_STATE_T ePreviousState; + BOOLEAN fgIsTransition; + + ASSERT(prStaRec); + if (!prStaRec) { + return; + } + + do { + +#if DBG + DBGLOG(SAA, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugAAState[prStaRec->eAuthAssocState], apucDebugAAState[eNextState]); +#else + DBGLOG(SAA, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_SAA_IDX, prStaRec->eAuthAssocState, eNextState); +#endif + ePreviousState = prStaRec->eAuthAssocState; + + /* NOTE(Kevin): This is the only place to change the eAuthAssocState(except initial) */ + prStaRec->eAuthAssocState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + switch (prStaRec->eAuthAssocState) { + case AA_STATE_IDLE: + if (ePreviousState != prStaRec->eAuthAssocState) { /* Only trigger this event once */ + + if (prRetainedSwRfb) { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_SUCCESS, + prStaRec, + prRetainedSwRfb) == WLAN_STATUS_SUCCESS) { + /* Do nothing */ + } else { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } else { + if (saaFsmSendEventJoinComplete(prAdapter, + WLAN_STATUS_FAILURE, + prStaRec, + NULL) == WLAN_STATUS_RESOURCES) { + eNextState = AA_STATE_RESOURCE; + fgIsTransition = TRUE; + } + } + + } + + /* Free allocated TCM memory */ + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + break; + + case SAA_STATE_SEND_AUTH1: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + /* Update Station Record - Class 1 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) { +#else + if (authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_1, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { +#endif /* CFG_SUPPORT_AAA */ + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH2: + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + +#if !CFG_SUPPORT_AAA + if (authSendAuthFrame(prAdapter, + prStaRec, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) { +#else + if (authSendAuthFrame(prAdapter, + prStaRec, + prStaRec->ucNetTypeIndex, + NULL, + AUTH_TRANSACTION_SEQ_3, + STATUS_CODE_RESERVED) != WLAN_STATUS_SUCCESS) { +#endif /* CFG_SUPPORT_AAA */ + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_AUTHENTICATION_RETRY_TIMEOUT_TU)); + } + } + } + break; + + case SAA_STATE_WAIT_AUTH4: + break; + + case SAA_STATE_SEND_ASSOC1: + /* Do tasks in INIT STATE */ + if (prStaRec->ucTxAuthAssocRetryCount >= prStaRec->ucTxAuthAssocRetryLimit) { + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + eNextState = AA_STATE_IDLE; + fgIsTransition = TRUE; + } else { + prStaRec->ucTxAuthAssocRetryCount++; + + if (assocSendReAssocReqFrame(prAdapter, prStaRec) != WLAN_STATUS_SUCCESS) { + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventTxReqTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(TX_ASSOCIATION_RETRY_TIMEOUT_TU)); + } + } + + break; + + case SAA_STATE_WAIT_ASSOC2: + break; + + case AA_STATE_RESOURCE: + /* TODO(Kevin) Can setup a timer and send message later */ + break; + + default: + DBGLOG(SAA, ERROR, "Unknown AA STATE\n"); + ASSERT(0); + break; + } + + } while (fgIsTransition); + + return; + +} /* end of saaFsmSteps() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Event to AIS/BOW/P2P +* +* @param[in] rJoinStatus To indicate JOIN success or failure. +* @param[in] prStaRec Pointer to the STA_RECORD_T +* @param[in] prSwRfb Pointer to the SW_RFB_T + +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmSendEventJoinComplete(IN P_ADAPTER_T prAdapter, + IN WLAN_STATUS rJoinStatus, IN P_STA_RECORD_T prStaRec, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_INFO_T prBssInfo; + + ASSERT(prStaRec); + if (!prStaRec) + return WLAN_STATUS_INVALID_PACKET; + + /* Store limitation about 40Mhz bandwidth capability during association */ + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if (rJoinStatus == WLAN_STATUS_SUCCESS) + prBssInfo->fg40mBwAllowed = prBssInfo->fgAssoc40mBwAllowed; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_AIS_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && (IS_STA_IN_P2P(prStaRec))) { + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_P2P_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + /* @TODO: BOW handler */ + + P_MSG_SAA_FSM_COMP_T prSaaFsmCompMsg; + + prSaaFsmCompMsg = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SAA_FSM_COMP_T)); + if (!prSaaFsmCompMsg) + return WLAN_STATUS_RESOURCES; + + prSaaFsmCompMsg->rMsgHdr.eMsgId = MID_SAA_BOW_JOIN_COMPLETE; + prSaaFsmCompMsg->ucSeqNum = prStaRec->ucAuthAssocReqSeqNum; + prSaaFsmCompMsg->rJoinStatus = rJoinStatus; + prSaaFsmCompMsg->prStaRec = prStaRec; + prSaaFsmCompMsg->prSwRfb = prSwRfb; + + /* NOTE(Kevin): Set to UNBUF for immediately JOIN complete */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSaaFsmCompMsg, MSG_SEND_METHOD_UNBUF); + + return WLAN_STATUS_SUCCESS; + } +#endif + else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + +} /* end of saaFsmSendEventJoinComplete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Start Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Join Request for a particular STA. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_FSM_START_T prSaaFsmStartMsg; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(prMsgHdr); + + prSaaFsmStartMsg = (P_MSG_SAA_FSM_START_T) prMsgHdr; + prStaRec = prSaaFsmStartMsg->prStaRec; + + if ((!prStaRec) || (prStaRec->fgIsInUse == FALSE)) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + ASSERT(prStaRec); + + DBGLOG(SAA, LOUD, "EVENT-START: Trigger SAA FSM.\n"); + + /* record sequence number of request message */ + prStaRec->ucAuthAssocReqSeqNum = prSaaFsmStartMsg->ucSeqNum; + + cnmMemFree(prAdapter, prMsgHdr); + + /* 4 <1> Validation of SAA Start Event */ + if (!IS_AP_STA(prStaRec)) { + + DBGLOG(SAA, ERROR, "EVENT-START: STA Type - %d was not supported.\n", prStaRec->eStaType); + + /* Ignore the return value because don't care the prSwRfb */ + saaFsmSendEventJoinComplete(prAdapter, WLAN_STATUS_FAILURE, prStaRec, NULL); + + return; + } + /* 4 <2> The previous JOIN process is not completed ? */ + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { + DBGLOG(SAA, ERROR, "EVENT-START: Reentry of SAA Module.\n"); + prStaRec->eAuthAssocState = AA_STATE_IDLE; + } + /* 4 <3> Reset Status Code and Time */ + /* Update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = STATUS_CODE_SUCCESSFUL; + + /* Update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rLastJoinTime); + + prStaRec->ucTxAuthAssocRetryCount = 0; + + if (prStaRec->prChallengeText) { + cnmMemFree(prAdapter, prStaRec->prChallengeText); + prStaRec->prChallengeText = (P_IE_CHALLENGE_TEXT_T) NULL; + } + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + +#if CFG_PRIVACY_MIGRATION + /* 4 <4> Init the sec fsm */ + secFsmInit(prAdapter, prStaRec); +#endif + + /* 4 <5> Reset the STA STATE */ + /* Update Station Record - Class 1 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for Reconnect issue - + * We won't deactivate the same STA_RECORD_T and then activate it again for the + * case of reconnection. + */ + /* cnmStaRecChangeState(prStaRec, STA_STATE_1); */ + + /* 4 <6> Decide if this BSS 20/40M bandwidth is allowed */ + if (prStaRec->ucNetTypeIndex < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + + if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) + && (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + prBssInfo->fgAssoc40mBwAllowed = cnmBss40mBwPermitted(prAdapter, prBssInfo->ucNetTypeIndex); + } else { + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + DBGLOG(RLM, INFO, "STA 40mAllowed=%d\n", prBssInfo->fgAssoc40mBwAllowed); + } + /* 4 <7> Trigger SAA FSM */ + if (prStaRec->ucStaState == STA_STATE_1) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_AUTH1, (P_SW_RFB_T) NULL); + else if (prStaRec->ucStaState == STA_STATE_2 || prStaRec->ucStaState == STA_STATE_3) + saaFsmSteps(prAdapter, prStaRec, SAA_STATE_SEND_ASSOC1, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventStart() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(Auth1/Auth3/AssocReq) Event of SAA FSM. +* +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Auth1/Auth3/AssocReq frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +saaFsmRunEventTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + + P_STA_RECORD_T prStaRec; + ENUM_AA_STATE_T eNextState; + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(SAA, INFO, "EVENT-TX DONE: Status %d, Invalid StaRec\n", rTxDoneStatus); + return WLAN_STATUS_INVALID_PACKET; + } + + ASSERT(prStaRec); + + DBGLOG(SAA, INFO, "EVENT-TX DONE: Status: %d, eAuthAssocState: %d , SeqNO: %d ", + rTxDoneStatus, prStaRec->eAuthAssocState, + prMsduInfo->ucTxSeqNum); + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + { + /* Strictly check the outgoing frame is matched with current AA STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_1) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + { + /* Strictly check the outgoing frame is matched with current JOIN STATE */ + if (authCheckTxAuthFrame(prAdapter, prMsduInfo, AUTH_TRANSACTION_SEQ_3) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_AUTH4; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + TU_TO_MSEC(DOT11_AUTHENTICATION_RESPONSE_TIMEOUT_TU)); + } + + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_ASSOC1: + { + /* Strictly check the outgoing frame is matched with current SAA STATE */ + if (assocCheckTxReAssocReqFrame(prAdapter, prMsduInfo) != WLAN_STATUS_SUCCESS) + break; + + if (rTxDoneStatus == TX_RESULT_SUCCESS) { + eNextState = SAA_STATE_WAIT_ASSOC2; + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + cnmTimerInitTimer(prAdapter, + &prStaRec->rTxReqDoneOrRxRespTimer, + (PFN_MGMT_TIMEOUT_FUNC) saaFsmRunEventRxRespTimeOut, + (ULONG) prStaRec); + + cnmTimerStartTimer(prAdapter, + &(prStaRec->rTxReqDoneOrRxRespTimer), + TU_TO_MSEC(DOT11_ASSOCIATION_RESPONSE_TIMEOUT_TU)); + } + /* if TX was successful, change to next state. + * if TX was failed, do retry if possible. + */ + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } + + return WLAN_STATUS_SUCCESS; + +} /* end of saaFsmRunEventTxDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Tx Request Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventTxReqTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ASSERT(prStaRec); + if (!prStaRec) + return; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: TX REQ TIMEOUT, Current Time = %u\n", kalGetTimeTick()); + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_SEND_ASSOC1: + saaFsmSteps(prAdapter, prStaRec, prStaRec->eAuthAssocState, (P_SW_RFB_T) NULL); + break; + + default: + return; + } + +} /* end of saaFsmRunEventTxReqTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will send Rx Response Timeout Event to SAA FSM. +* +* @param[in] prStaRec Pointer to the STA_RECORD_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventRxRespTimeOut(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + ENUM_AA_STATE_T eNextState; + + DBGLOG(SAA, LOUD, "EVENT-TIMER: RX RESP TIMEOUT, Current Time = %u\n", kalGetTimeTick()); + + ASSERT(prStaRec); + if (!prStaRec) + return; + + eNextState = prStaRec->eAuthAssocState; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_WAIT_AUTH2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH1; + break; + + case SAA_STATE_WAIT_AUTH4: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_AUTH_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_AUTH3; + break; + + case SAA_STATE_WAIT_ASSOC2: + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_ASSOC_TIMEOUT; + + /* Pull back to earlier state to do retry */ + eNextState = SAA_STATE_SEND_ASSOC1; + break; + + default: + break; /* Ignore other cases */ + } + + if (eNextState != prStaRec->eAuthAssocState) + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + +} /* end of saaFsmRunEventRxRespTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx Auth Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventRxAuth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + /* Peter: we can handle the packet without station record */ + /* ASSERT(0); */ + return; + } + + if (!IS_AP_STA(prStaRec)) + return; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_AUTH1: + case SAA_STATE_WAIT_AUTH2: + /* Check if the incoming frame is what we are waiting for */ + if (authCheckRxAuthFrameStatus(prAdapter, + prSwRfb, AUTH_TRANSACTION_SEQ_2, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); + + if (prStaRec->ucAuthAlgNum == (UINT_8) AUTH_ALGORITHM_NUM_SHARED_KEY) { + + eNextState = SAA_STATE_SEND_AUTH3; + } else { + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } + } else { + DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + case SAA_STATE_SEND_AUTH3: + case SAA_STATE_WAIT_AUTH4: + /* Check if the incoming frame is what we are waiting for */ + if (authCheckRxAuthFrameStatus(prAdapter, + prSwRfb, AUTH_TRANSACTION_SEQ_4, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + authProcessRxAuth2_Auth4Frame(prAdapter, prSwRfb); /* Add for 802.11r handling */ + + /* Update Station Record - Class 2 Flag */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + eNextState = SAA_STATE_SEND_ASSOC1; + } else { + DBGLOG(SAA, INFO, "Auth Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + + eNextState = AA_STATE_IDLE; + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + saaFsmSteps(prAdapter, prStaRec, eNextState, (P_SW_RFB_T) NULL); + } + break; + + default: + break; /* Ignore other cases */ + } + +} /* end of saaFsmRunEventRxAuth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will process the Rx (Re)Association Response Frame and then +* trigger SAA FSM. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS if the status code was not success +* @retval WLAN_STATUS_BUFFER_RETAINED if the status code was success +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxAssoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2StatusCode; + ENUM_AA_STATE_T eNextState; + P_SW_RFB_T prRetainedSwRfb = (P_SW_RFB_T) NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + /* We should have the corresponding Sta Record. */ + if (!prStaRec) { + ASSERT(0); + return rStatus; + } + + if (!IS_AP_STA(prStaRec)) + return rStatus; + + switch (prStaRec->eAuthAssocState) { + case SAA_STATE_SEND_ASSOC1: + case SAA_STATE_WAIT_ASSOC2: + /* TRUE if the incoming frame is what we are waiting for */ + if (assocCheckRxReAssocRspFrameStatus(prAdapter, prSwRfb, &u2StatusCode) == WLAN_STATUS_SUCCESS) { + + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = u2StatusCode; + + if (u2StatusCode == STATUS_CODE_SUCCESSFUL) { + + /* Update Station Record - Class 3 Flag */ + /* NOTE(Kevin): Moved to AIS FSM for roaming issue - + * We should deactivate the STA_RECORD_T of previous AP before + * activate new one in Driver. + */ + /* cnmStaRecChangeState(prStaRec, STA_STATE_3); */ + + prStaRec->ucJoinFailureCount = 0; /* Clear history. */ + + prRetainedSwRfb = prSwRfb; + rStatus = WLAN_STATUS_PENDING; + } else { + DBGLOG(SAA, INFO, "Assoc Req was rejected by [ %pM ], Status Code = %d\n", + (prStaRec->aucMacAddr), u2StatusCode); + } + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* update RCPI */ + prStaRec->ucRCPI = prSwRfb->prHifRxHdr->ucRcpi; + + eNextState = AA_STATE_IDLE; + + saaFsmSteps(prAdapter, prStaRec, eNextState, prRetainedSwRfb); + } + break; + + default: + break; /* Ignore other cases */ + } + + return rStatus; + +} /* end of saaFsmRunEventRxAssoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Deauth Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain deauthentication frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDeauth(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DEAUTH_FRAME_T prDeauthFrame; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + prDeauthFrame = (P_WLAN_DEAUTH_FRAME_T) prSwRfb->pvHeader; + DBGLOG(SAA, INFO, "Rx Deauth frame from BSSID=[ %pM ].\n", prDeauthFrame->aucBSSID); + + do { + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState <= STA_STATE_1) + break; + + /* Check if this is the AP we are associated or associating with */ + if (authProcessRxDeauthFrame(prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + DBGLOG(SAA, INFO, "Deauth reason = %d\n", prStaRec->u2ReasonCode); + + if (STA_STATE_2 <= prStaRec->ucStaState) { + P_MSG_AIS_ABORT_T prAisAbortMsg; + + /* NOTE(Kevin): Change state immediately to avoid starvation of + * MSG buffer because of too many deauth frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + prAisAbortMsg = + (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) + break; + + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DEAUTHENTICATED; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + } else { + + /* TODO(Kevin): Joining Abort */ + } + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; + + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDeauthentication(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) + bowRunEventRxDeAuth(prAdapter, prStaRec, prSwRfb); +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* end of saaFsmRunEventRxDeauth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will check the incoming Disassociation Frame. +* +* @param[in] prSwRfb Pointer to the SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS Always not retain disassociation frames +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS saaFsmRunEventRxDisassoc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_STA_RECORD_T prStaRec; + P_WLAN_DISASSOC_FRAME_T prDisassocFrame; + + ASSERT(prSwRfb); + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if (prStaRec == NULL) + return WLAN_STATUS_FAILURE; + + prDisassocFrame = (P_WLAN_DISASSOC_FRAME_T) prSwRfb->pvHeader; + DBGLOG(SAA, INFO, "Rx Disassoc frame from BSSID=[ %pM ].\n", (prDisassocFrame->aucBSSID)); + + do { + if (IS_STA_IN_AIS(prStaRec)) { + P_AIS_BSS_INFO_T prAisBssInfo; + + if (!IS_AP_STA(prStaRec)) + break; + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prStaRec->ucStaState <= STA_STATE_1) + break; + + /* Check if this is the AP we are associated or associating with */ + if (assocProcessRxDisassocFrame(prAdapter, + prSwRfb, + prStaRec->aucMacAddr, + &prStaRec->u2ReasonCode) == WLAN_STATUS_SUCCESS) { + + DBGLOG(SAA, INFO, "Disassoc reason = %d\n", prStaRec->u2ReasonCode); + + if (STA_STATE_3 <= prStaRec->ucStaState) { + P_MSG_AIS_ABORT_T prAisAbortMsg; + /* NOTE(Chaozhong): Change state immediately to avoid starvation of + * MSG buffer because of too many disassoc frames before changing + * the STA state. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_2); + + prAisAbortMsg = + (P_MSG_AIS_ABORT_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_AIS_ABORT_T)); + if (!prAisAbortMsg) + break; + + prAisAbortMsg->rMsgHdr.eMsgId = MID_SAA_AIS_FSM_ABORT; + prAisAbortMsg->ucReasonOfDisconnect = + DISCONNECT_REASON_CODE_DISASSOCIATED; + prAisAbortMsg->fgDelayIndication = FALSE; + + mboxSendMsg(prAdapter, + MBOX_ID_0, + (P_MSG_HDR_T) prAisAbortMsg, MSG_SEND_METHOD_BUF); + } else { + + /* TODO(Kevin): Joining Abort */ + } + prAisBssInfo->u2DeauthReason = prStaRec->u2ReasonCode; + + } + + } +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered && IS_STA_IN_P2P(prStaRec)) { + /* TODO(Kevin) */ + p2pFsmRunEventRxDisassociation(prAdapter, prStaRec, prSwRfb); + } +#endif +#if CFG_ENABLE_BT_OVER_WIFI + else if (IS_STA_IN_BOW(prStaRec)) { + /* Do nothing */ + /* TODO(Kevin) */ + } +#endif + else + ASSERT(0); + + } while (FALSE); + + return WLAN_STATUS_SUCCESS; +} /* end of saaFsmRunEventRxDisassoc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle the Abort Event to SAA FSM. +* +* @param[in] prMsgHdr Message of Abort Request for a particular STA. +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID saaFsmRunEventAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SAA_FSM_ABORT_T prSaaFsmAbortMsg; + P_STA_RECORD_T prStaRec; + + ASSERT(prMsgHdr); + + prSaaFsmAbortMsg = (P_MSG_SAA_FSM_ABORT_T) prMsgHdr; + prStaRec = prSaaFsmAbortMsg->prStaRec; + + ASSERT(prStaRec); + if (!prStaRec) { + cnmMemFree(prAdapter, prMsgHdr); + return; + } + + DBGLOG(SAA, LOUD, "EVENT-ABORT: Stop SAA FSM.\n"); + + cnmMemFree(prAdapter, prMsgHdr); + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prStaRec->ucTxAuthAssocRetryCount = 0; + + /* Cancel JOIN relative Timer */ + cnmTimerStopTimer(prAdapter, &prStaRec->rTxReqDoneOrRxRespTimer); + + if (prStaRec->eAuthAssocState != AA_STATE_IDLE) { +#if DBG + DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %s.\n", + apucDebugAAState[prStaRec->eAuthAssocState]); +#else + DBGLOG(SAA, LOUD, "EVENT-ABORT: Previous Auth/Assoc State == %d.\n", prStaRec->eAuthAssocState); +#endif + } +#if 0 + /* For the Auth/Assoc State to IDLE */ + prStaRec->eAuthAssocState = AA_STATE_IDLE; +#else + /* Free this StaRec */ + cnmStaRecFree(prAdapter, prStaRec, FALSE); +#endif + +} /* end of saaFsmRunEventAbort() */ + +/* TODO(Kevin): following code will be modified and move to AIS FSM */ +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will send Join Timeout Event to JOIN FSM. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \retval WLAN_STATUS_FAILURE Fail because of Join Timeout +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS joinFsmRunEventJoinTimeOut(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("joinFsmRunEventJoinTimeOut"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + + DBGLOG(JOIN, EVENT, "JOIN EVENT: JOIN TIMEOUT\n"); + + /* Get a Station Record if possible, TA == BSSID for AP */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prJoinInfo->prBssDesc->aucBSSID); + + /* We have renew this Sta Record when in JOIN_STATE_INIT */ + ASSERT(prStaRec); + + /* Record the Status Code of Authentication Request */ + prStaRec->u2StatusCode = STATUS_CODE_JOIN_TIMEOUT; + + /* Increase Failure Count */ + prStaRec->ucJoinFailureCount++; + + /* Reset Send Auth/(Re)Assoc Frame Count */ + prJoinInfo->ucTxAuthAssocRetryCount = 0; + + /* Cancel other JOIN relative Timer */ + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rTxRequestTimer); + + ARB_CANCEL_TIMER(prAdapter, prJoinInfo->rRxResponseTimer); + + /* Restore original setting from current BSS_INFO_T */ + if (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED) + joinAdoptParametersFromCurrentBss(prAdapter); + + /* Pull back to IDLE */ + joinFsmSteps(prAdapter, JOIN_STATE_IDLE); + + return WLAN_STATUS_FAILURE; + +} /* end of joinFsmRunEventJoinTimeOut() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from Peer BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromPeerBss(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + + DEBUGFUNC("joinAdoptParametersFromPeerBss"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + + /* 4 <1> Adopt Peer BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssDesc->ePhyType; + + DBGLOG(JOIN, INFO, "Target BSS[%s]'s PhyType = %s\n", + prBssDesc->aucSSID, (prBssDesc->ePhyType == PHY_TYPE_ERP_INDEX) ? "ERP" : "HR_DSSS"); + + /* 4 <2> Adopt Peer BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Target BSS's Channel = %d, Band = %d\n", prBssDesc->ucChannelNum, prBssDesc->eBand); + + nicSwitchChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum, 10); + + prJoinInfo->fgIsParameterAdopted = TRUE; + +} /* end of joinAdoptParametersFromPeerBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will adopt the parameters from current associated BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinAdoptParametersFromCurrentBss(IN P_ADAPTER_T prAdapter) +{ + /* P_JOIN_INFO_T prJoinInfo = &prAdapter->rJoinInfo; */ + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + prBssInfo = &prAdapter->rBssInfo; + + /* 4 <1> Adopt current BSS' PHY TYPE */ + prAdapter->eCurrentPhyType = prBssInfo->ePhyType; + + /* 4 <2> Adopt current BSS' Frequency(Band/Channel) */ + DBGLOG(JOIN, INFO, "Current BSS's Channel = %d, Band = %d\n", prBssInfo->ucChnl, prBssInfo->eBand); + + nicSwitchChannel(prAdapter, prBssInfo->eBand, prBssInfo->ucChnl, 10); +} /* end of joinAdoptParametersFromCurrentBss() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will update all the SW variables and HW MCR registers after +* the association with target BSS. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID joinComplete(IN P_ADAPTER_T prAdapter) +{ + P_JOIN_INFO_T prJoinInfo; + P_BSS_DESC_T prBssDesc; + P_PEER_BSS_INFO_T prPeerBssInfo; + P_BSS_INFO_T prBssInfo; + P_CONNECTION_SETTINGS_T prConnSettings; + P_STA_RECORD_T prStaRec; + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_802_11D + P_IE_COUNTRY_T prIECountry; +#endif + + DEBUGFUNC("joinComplete"); + + ASSERT(prAdapter); + prJoinInfo = &prAdapter->rJoinInfo; + prBssDesc = prJoinInfo->prBssDesc; + prPeerBssInfo = &prAdapter->rPeerBssInfo; + prBssInfo = &prAdapter->rBssInfo; + prConnSettings = &prAdapter->rConnSettings; + prTxCtrl = &prAdapter->rTxCtrl; + +/* 4 <1> Update Connecting & Connected Flag of BSS_DESC_T. */ + /* Remove previous AP's Connection Flags if have */ + scanRemoveConnectionFlagOfBssDescByBssid(prAdapter, prBssInfo->aucBSSID); + + prBssDesc->fgIsConnected = TRUE; /* Mask as Connected */ + + if (prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): This is for the case of Passive Scan and the target BSS didn't + * broadcast SSID on its Beacon Frame. + */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prAdapter->rConnSettings.aucSSID, prAdapter->rConnSettings.ucSSIDLen); + + if (prBssDesc->ucSSIDLen) + prBssDesc->fgIsHiddenSSID = FALSE; +#if DBG + else + ASSERT(0); +#endif /* DBG */ + + DBGLOG(JOIN, INFO, "Hidden SSID! - Update SSID : %s\n", prBssDesc->aucSSID); + } +/* 4 <2> Update BSS_INFO_T from BSS_DESC_T */ + /* 4 <2.A> PHY Type */ + prBssInfo->ePhyType = prBssDesc->ePhyType; + + /* 4 <2.B> BSS Type */ + prBssInfo->eBSSType = BSS_TYPE_INFRASTRUCTURE; + + /* 4 <2.C> BSSID */ + COPY_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID); + + DBGLOG(JOIN, INFO, "JOIN to BSSID: [%pM]\n", prBssDesc->aucBSSID); + + /* 4 <2.D> SSID */ + COPY_SSID(prBssInfo->aucSSID, prBssInfo->ucSSIDLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + /* 4 <2.E> Channel / Band information. */ + prBssInfo->eBand = prBssDesc->eBand; + prBssInfo->ucChnl = prBssDesc->ucChannelNum; + + /* 4 <2.F> RSN/WPA information. */ + secFsmRunEventStart(prAdapter); + prBssInfo->u4RsnSelectedPairwiseCipher = prBssDesc->u4RsnSelectedPairwiseCipher; + prBssInfo->u4RsnSelectedGroupCipher = prBssDesc->u4RsnSelectedGroupCipher; + prBssInfo->u4RsnSelectedAKMSuite = prBssDesc->u4RsnSelectedAKMSuite; + + if (secRsnKeyHandshakeEnabled()) + prBssInfo->fgIsWPAorWPA2Enabled = TRUE; + else + prBssInfo->fgIsWPAorWPA2Enabled = FALSE; + + /* 4 <2.G> Beacon interval. */ + prBssInfo->u2BeaconInterval = prBssDesc->u2BeaconInterval; + + /* 4 <2.H> DTIM period. */ + prBssInfo->ucDtimPeriod = prBssDesc->ucDTIMPeriod; + + /* 4 <2.I> ERP Information */ + if ((prBssInfo->ePhyType == PHY_TYPE_ERP_INDEX) && /* Our BSS's PHY_TYPE is ERP now. */ + (prBssDesc->fgIsERPPresent)) { + + prBssInfo->fgIsERPPresent = TRUE; + prBssInfo->ucERP = prBssDesc->ucERP; /* Save the ERP for later check */ + } else { /* Some AP, may send ProbeResp without ERP IE. Thus prBssDesc->fgIsERPPresent is FALSE. */ + prBssInfo->fgIsERPPresent = FALSE; + prBssInfo->ucERP = 0; + } + +#if CFG_SUPPORT_802_11D + /* 4 <2.J> Country inforamtion of the associated AP */ + if (prConnSettings->fgMultiDomainCapabilityEnabled) { + DOMAIN_INFO_ENTRY rDomainInfo; + + if (domainGetDomainInfoByScanResult(prAdapter, &rDomainInfo)) { + if (prBssDesc->prIECountry) { + prIECountry = prBssDesc->prIECountry; + + domainParseCountryInfoElem(prIECountry, &prBssInfo->rDomainInfo); + + /* use the domain get from the BSS info */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, prBssInfo->rDomainInfo.u2CountryCode, FALSE); + } else { + /* use the domain get from the scan result */ + prBssInfo->fgIsCountryInfoPresent = TRUE; + nicSetupOpChnlList(prAdapter, rDomainInfo.u2CountryCode, FALSE); + } + } + } +#endif + + /* 4 <2.K> Signal Power of the associated AP */ + prBssInfo->rRcpi = prBssDesc->rRcpi; + prBssInfo->rRssi = RCPI_TO_dBm(prBssInfo->rRcpi); + GET_CURRENT_SYSTIME(&prBssInfo->rRssiLastUpdateTime); + + /* 4 <2.L> Capability Field of the associated AP */ + prBssInfo->u2CapInfo = prBssDesc->u2CapInfo; + + DBGLOG(JOIN, INFO, "prBssInfo-> fgIsERPPresent = %d, ucERP = %02x, rRcpi = %d, rRssi = %ld\n", + prBssInfo->fgIsERPPresent, prBssInfo->ucERP, prBssInfo->rRcpi, prBssInfo->rRssi); + +/* 4 <3> Update BSS_INFO_T from PEER_BSS_INFO_T & NIC RATE FUNC */ + /* 4 <3.A> Association ID */ + prBssInfo->u2AssocId = prPeerBssInfo->u2AssocId; + + /* 4 <3.B> WMM Information */ + if (prAdapter->fgIsEnableWMM && (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_SUPPORT_WMM)) { + + prBssInfo->fgIsWmmAssoc = TRUE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC3; + + qosWmmInfoInit(&prBssInfo->rWmmInfo, (prBssInfo->ePhyType == PHY_TYPE_HR_DSSS_INDEX) ? TRUE : FALSE); + + if (prPeerBssInfo->rWmmInfo.ucWmmFlag & WMM_FLAG_AC_PARAM_PRESENT) { + kalMemCopy(&prBssInfo->rWmmInfo, &prPeerBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } else { + kalMemCopy(&prBssInfo->rWmmInfo, + &prPeerBssInfo->rWmmInfo, + sizeof(WMM_INFO_T) - sizeof(prPeerBssInfo->rWmmInfo.arWmmAcParams)); + } + } else { + prBssInfo->fgIsWmmAssoc = FALSE; + prTxCtrl->rTxQForVoipAccess = TXQ_AC1; + + kalMemZero(&prBssInfo->rWmmInfo, sizeof(WMM_INFO_T)); + } + + /* 4 <3.C> Operational Rate Set & BSS Basic Rate Set */ + prBssInfo->u2OperationalRateSet = prPeerBssInfo->u2OperationalRateSet; + prBssInfo->u2BSSBasicRateSet = prPeerBssInfo->u2BSSBasicRateSet; + + /* 4 <3.D> Short Preamble */ + if (prBssInfo->fgIsERPPresent) { + + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * TRUE FALSE TRUE FALSE + * FALSE FALSE FALSE FALSE(shouldn't have such case, use the AssocResp) + * FALSE FALSE TRUE FALSE + * TRUE TRUE FALSE TRUE(follow ERP) + * TRUE TRUE TRUE FALSE(follow ERP) + * FALSE TRUE FALSE FALSE(shouldn't have such case, and we should set to FALSE) + * FALSE TRUE TRUE FALSE(we should set to FALSE) + */ + if ((prPeerBssInfo->fgIsShortPreambleAllowed) && + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_SHORT) || + ((prConnSettings->ePreambleType == PREAMBLE_TYPE_AUTO) && + (prBssDesc->u2CapInfo & CAP_INFO_SHORT_PREAMBLE)))) { + + prBssInfo->fgIsShortPreambleAllowed = TRUE; + + if (prBssInfo->ucERP & ERP_INFO_BARKER_PREAMBLE_MODE) + prBssInfo->fgUseShortPreamble = FALSE; + else + prBssInfo->fgUseShortPreamble = TRUE; + } else { + prBssInfo->fgIsShortPreambleAllowed = FALSE; + prBssInfo->fgUseShortPreamble = FALSE; + } + } else { + /* NOTE(Kevin 2007/12/24): Truth Table. + * Short Preamble Bit in + * Final Driver Setting(Short) + * TRUE FALSE FALSE + * FALSE FALSE FALSE + * TRUE TRUE TRUE + * FALSE TRUE(status success) TRUE + * --> Honor the result of prPeerBssInfo. + */ + + prBssInfo->fgIsShortPreambleAllowed = prBssInfo->fgUseShortPreamble = + prPeerBssInfo->fgIsShortPreambleAllowed; + } + + DBGLOG(JOIN, INFO, "prBssInfo->fgIsShortPreambleAllowed = %d, prBssInfo->fgUseShortPreamble = %d\n", + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortPreamble); + + /* 4 <3.E> Short Slot Time */ + prBssInfo->fgUseShortSlotTime = prPeerBssInfo->fgUseShortSlotTime; /* AP support Short Slot Time */ + + DBGLOG(JOIN, INFO, "prBssInfo->fgUseShortSlotTime = %d\n", prBssInfo->fgUseShortSlotTime); + + nicSetSlotTime(prAdapter, + prBssInfo->ePhyType, + ((prConnSettings->fgIsShortSlotTimeOptionEnable && + prBssInfo->fgUseShortSlotTime) ? TRUE : FALSE)); + + /* 4 <3.F> Update Tx Rate for Control Frame */ + bssUpdateTxRateForControlFrame(prAdapter); + + /* 4 <3.G> Save the available Auth Types during Roaming (Design for Fast BSS Transition). */ + /* if (prAdapter->fgIsEnableRoaming) */ /* NOTE(Kevin): Always prepare info for roaming */ + { + + if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_OPEN_SYSTEM) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_OPEN_SYSTEM; + else if (prJoinInfo->ucCurrAuthAlgNum == AUTH_ALGORITHM_NUM_SHARED_KEY) + prJoinInfo->ucRoamingAuthTypes |= AUTH_TYPE_SHARED_KEY; + + prBssInfo->ucRoamingAuthTypes = prJoinInfo->ucRoamingAuthTypes; + + /* Set the stable time of the associated BSS. We won't do roaming decision + * during the stable time. + */ + SET_EXPIRATION_TIME(prBssInfo->rRoamingStableExpirationTime, + SEC_TO_SYSTIME(ROAMING_STABLE_TIMEOUT_SEC)); + } + + /* 4 <3.H> Update Parameter for TX Fragmentation Threshold */ +#if CFG_TX_FRAGMENT + txFragInfoUpdate(prAdapter); +#endif /* CFG_TX_FRAGMENT */ + +/* 4 <4> Update STA_RECORD_T */ + /* Get a Station Record if possible */ + prStaRec = staRecGetStaRecordByAddr(prAdapter, prBssDesc->aucBSSID); + + if (prStaRec) { + UINT_16 u2OperationalRateSet, u2DesiredRateSet; + + /* 4 <4.A> Desired Rate Set */ + u2OperationalRateSet = (rPhyAttributes[prBssInfo->ePhyType].u2SupportedRateSet & + prBssInfo->u2OperationalRateSet); + + u2DesiredRateSet = (u2OperationalRateSet & prConnSettings->u2DesiredRateSet); + if (u2DesiredRateSet) { + prStaRec->u2DesiredRateSet = u2DesiredRateSet; + } else { + /* For Error Handling - The Desired Rate Set is not covered in Operational Rate Set. */ + prStaRec->u2DesiredRateSet = u2OperationalRateSet; + } + + /* Try to set the best initial rate for this entry */ + if (!rateGetBestInitialRateIndex(prStaRec->u2DesiredRateSet, + prStaRec->rRcpi, &prStaRec->ucCurrRate1Index)) { + + if (!rateGetLowestRateIndexFromRateSet(prStaRec->u2DesiredRateSet, &prStaRec->ucCurrRate1Index)) + ASSERT(0); + } + + DBGLOG(JOIN, INFO, "prStaRec->ucCurrRate1Index = %d\n", prStaRec->ucCurrRate1Index); + + /* 4 <4.B> Preamble Mode */ + prStaRec->fgIsShortPreambleOptionEnable = prBssInfo->fgUseShortPreamble; + + /* 4 <4.C> QoS Flag */ + prStaRec->fgIsQoS = prBssInfo->fgIsWmmAssoc; + } +#if DBG + else + ASSERT(0); +#endif /* DBG */ + +/* 4 <5> Update NIC */ + /* 4 <5.A> Update BSSID & Operation Mode */ + nicSetupBSS(prAdapter, prBssInfo); + + /* 4 <5.B> Update WLAN Table. */ + if (nicSetHwBySta(prAdapter, prStaRec) == FALSE) + ASSERT(FALSE); + /* 4 <5.C> Update Desired Rate Set for BT. */ +#if CFG_TX_FRAGMENT + if (prConnSettings->fgIsEnableTxAutoFragmentForBT) + txRateSetInitForBT(prAdapter, prStaRec); +#endif /* CFG_TX_FRAGMENT */ + + /* 4 <5.D> TX AC Parameter and TX/RX Queue Control */ + if (prBssInfo->fgIsWmmAssoc) { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, FALSE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + qosUpdateWMMParametersAndAssignAllowedACI(prAdapter, &prBssInfo->rWmmInfo); + } else { + +#if CFG_TX_AGGREGATE_HW_FIFO + nicTxAggregateTXQ(prAdapter, TRUE); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxNonQoSAssignDefaultAdmittedTXQ(prAdapter); + + nicTxNonQoSUpdateTXQParameters(prAdapter, prBssInfo->ePhyType); + } + +#if CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN + { + prTxCtrl->fgBlockTxDuringJoin = FALSE; + +#if !CFG_TX_AGGREGATE_HW_FIFO /* TX FIFO AGGREGATE already do flush once */ + nicTxFlushStopQueues(prAdapter, (UINT_8) TXQ_DATA_MASK, (UINT_8) NULL); +#endif /* CFG_TX_AGGREGATE_HW_FIFO */ + + nicTxRetransmitOfSendWaitQue(prAdapter); + + if (prTxCtrl->fgIsPacketInOsSendQueue) + nicTxRetransmitOfOsSendQue(prAdapter); +#if CFG_SDIO_TX_ENHANCE + halTxLeftClusteredMpdu(prAdapter); +#endif /* CFG_SDIO_TX_ENHANCE */ + + } +#endif /* CFG_TX_STOP_WRITE_TX_FIFO_UNTIL_JOIN */ + +/* 4 <6> Setup CONNECTION flag. */ + prAdapter->eConnectionState = MEDIA_STATE_CONNECTED; + prAdapter->eConnectionStateIndicated = MEDIA_STATE_CONNECTED; + + if (prJoinInfo->fgIsReAssoc) + prAdapter->fgBypassPortCtrlForRoaming = TRUE; + else + prAdapter->fgBypassPortCtrlForRoaming = FALSE; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, (PVOID) NULL, 0); + +} /* end of joinComplete() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c new file mode 100644 index 0000000000000..2c9ccbe82dd1b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan.c @@ -0,0 +1,3103 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan.c#3 +*/ + +/*! \file "scan.c" + \brief This file defines the scan profile and the processing function of + scan result for SCAN Module. + + The SCAN Profile selection is part of SCAN MODULE and responsible for defining + SCAN Parameters - e.g. MIN_CHANNEL_TIME, number of scan channels. + In this file we also define the process of SCAN Result including adding, searching + and removing SCAN record from the list. +*/ + +/* +** Log: scan.c +** +** 01 30 2013 yuche.tsai +** [ALPS00451578] [JB2][WFD][Case Fail][JE][MR1]?????????[Java (JE),660,-1361051648,99, +** /data/core/,0,system_server_crash,system_server]JE happens when try to connect WFD.(4/5) +** Fix possible old scan result indicate to supplicant after formation. +** +** 01 16 2013 yuche.tsai +** [ALPS00431980] [WFD]Aupus one ?play game 10 minitues?wfd connection automaticlly disconnect +** Fix possible FW assert issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 25 2012 cp.wu + * [WCXRP00001258] [MT6620][MT5931][MT6628][Driver] Do not use stale scan result for deciding connection target + * drop off scan result which is older than 5 seconds when choosing which BSS to join + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 16 2012 cp.wu + * [WCXRP00001169] [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band + * configuration with corresponding network configuration + * correct typo. + * + * 01 16 2012 cp.wu + * [MT6620 Wi-Fi][Driver] API and behavior modification for preferred band configuration + * with corresponding network configuration + * add wlanSetPreferBandByNetwork() for glue layer to invoke for setting preferred + * band configuration corresponding to network type. + * + * 12 05 2011 cp.wu + * [WCXRP00001131] [MT6620 Wi-Fi][Driver][AIS] Implement connect-by-BSSID path + * add CONNECT_BY_BSSID policy + * + * 11 23 2011 cp.wu + * [WCXRP00001123] [MT6620 Wi-Fi][Driver] Add option to disable beacon content change detection + * add compile option to disable beacon content change detection. + * + * 11 04 2011 cp.wu + * [WCXRP00001085] [MT6628 Wi-Fi][Driver] deprecate old BSS-DESC if timestamp + * is reset with received beacon/probe response frames + * deprecate old BSS-DESC when timestamp in received beacon/probe response frames showed a smaller value than before + * + * 10 11 2011 cm.chang + * [WCXRP00001031] [All Wi-Fi][Driver] Check HT IE length to avoid wrong SCO parameter + * Ignore HT OP IE if its length field is not valid + * + * 09 30 2011 cp.wu + * [WCXRP00001021] [MT5931][Driver] Correct scan result generation for conversion between BSS type and operation mode + * correct type casting issue. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 10 2011 cp.wu + * [WCXRP00000922] [MT6620 Wi-Fi][Driver] traverse whole BSS-DESC list for removing + * traverse whole BSS-DESC list because BSSID is not unique anymore. + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * for multiple BSS descriptior detecting issue: + * 1) check BSSID for infrastructure network + * 2) check SSID for AdHoc network + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * check for BSSID for beacons used to update DTIM + * + * 07 12 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * do not check BSS descriptor for connected flag due to linksys's hidden + * SSID will use another BSS descriptor and never connected + * + * 07 11 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * just pass beacons with the same BSSID. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define + * for make sure the value is initialize, for customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 28 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * Do not check for SSID as beacon content change due to the existence of + * single BSSID with multiple SSID AP configuration + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple + * SSID settings to work around some tricky AP which use space character as hidden SSID + * 1. correct logic + * 2. replace only BSS-DESC which doesn't have a valid SSID. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID + * settings to work around some tricky AP which use space character as hidden SSID + * remove unused temporal variable reference. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID + * settings to work around some tricky AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 06 02 2011 cp.wu + * [WCXRP00000757] [MT6620 Wi-Fi][Driver][SCN] take use of RLM API to filter out BSS in disallowed channels + * filter out BSS in disallowed channel by + * 1. do not add to scan result array if BSS is at disallowed channel + * 2. do not allow to search for BSS-DESC in disallowed channels + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Refine range of valid channel number + * + * 05 02 2011 cp.wu + * [MT6620 Wi-Fi][Driver] Take parsed result for channel information instead of + * hardware channel number passed from firmware domain + * take parsed result for generating scanning result with channel information. + * + * 05 02 2011 cm.chang + * [WCXRP00000691] [MT6620 Wi-Fi][Driver] Workaround about AP's wrong HT capability IE to have wrong channel number + * Check if channel is valided before record ing BSS channel + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 03 25 2011 yuche.tsai + * NULL + * Always update Bss Type, for Bss Type for P2P Network is changing every time. + * + * 03 23 2011 yuche.tsai + * NULL + * Fix concurrent issue when AIS scan result would overwrite p2p scan result. + * + * 03 14 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * filtering out other BSS coming from adjacent channels + * + * 03 11 2011 chinglan.wang + * [WCXRP00000537] [MT6620 Wi-Fi][Driver] Can not connect to 802.11b/g/n mixed AP with WEP security. + * . + * + * 03 11 2011 cp.wu + * [WCXRP00000535] [MT6620 Wi-Fi][Driver] Fixed channel operation when AIS and Tethering are operating concurrently + * When fixed channel operation is necessary, AIS-FSM would scan and only connect for BSS on the specific channel + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() + * won't sleep long enough for specified interval such as 500ms + * implement beacon change detection by checking SSID and supported rate. + * + * 02 22 2011 yuche.tsai + * [WCXRP00000480] [Volunteer Patch][MT6620][Driver] WCS IE format issue + * Fix WSC big endian issue. + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix scan channel extension issue when p2p module is not registered. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 21 2011 cp.wu + * [WCXRP00000380] [MT6620 Wi-Fi][Driver] SSID information should come from buffered + * BSS_DESC_T rather than using beacon-carried information + * SSID should come from buffered prBssDesc rather than beacon-carried information + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Fix compile error. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Memfree for P2P Descriptor & P2P Descriptor List. + * + * 01 14 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * Free P2P Descriptor List & Descriptor under BSS Descriptor. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc + * and vmalloc implementations to ease physically continuous memory demands + * 1) correct typo in scan.c + * 2) TX descriptors, RX descriptos and management buffer should use virtually + * continuous buffer instead of physically continuous one + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc + * and vmalloc implementations to ease physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * while being unloaded, clear all pending interrupt then set LP-own to firmware + * + * 12 21 2010 cp.wu + * [WCXRP00000280] [MT6620 Wi-Fi][Driver] Enable BSS selection with best RCPI policy in SCN module + * SCN: enable BEST RSSI selection policy support + * + * 11 29 2010 cp.wu + * [WCXRP00000210] [MT6620 Wi-Fi][Driver][FW] Set RCPI value in STA_REC + * for initial TX rate selection of auto-rate algorithm + * update ucRcpi of STA_RECORD_T for AIS when + * 1) Beacons for IBSS merge is received + * 2) Associate Response for a connecting peer is received + * + * 11 03 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Refine the HT rate disallow TKIP pairwise cipher . + * + * 10 12 2010 cp.wu + * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out + * beacons which is received on the folding frequency + * trust HT IE if available for 5GHz band + * + * 10 11 2010 cp.wu + * [WCXRP00000091] [MT6620 Wi-Fi][Driver] Add scanning logic to filter out + * beacons which is received on the folding frequency + * add timing and strenght constraint for filtering out beacons with same SSID/TA but received on different channels + * + * 10 08 2010 wh.su + * [WCXRP00000085] [MT6620 Wif-Fi] [Driver] update the modified p2p state machine + * update the frog's new p2p state machine. + * + * 10 01 2010 yuche.tsai + * NULL + * [MT6620 P2P] Fix Big Endian Issue when parse P2P device name TLV. + * + * 09 24 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate unused variables which lead gcc to argue + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * When indicate scan result, append IE buffer information in the scan result. + * + * 09 03 2010 yuche.tsai + * NULL + * 1. Update Beacon RX count when running SLT. + * 2. Ignore Beacon when running SLT, would not update information from Beacon. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 29 2010 yuche.tsai + * NULL + * 1. Fix P2P Descriptor List to be a link list, to avoid link corrupt after Bss Descriptor Free. + * 2.. Fix P2P Device Name Length BE issue. + * + * 08 23 2010 yuche.tsai + * NULL + * Add P2P Device Found Indication to supplicant + * + * 08 20 2010 cp.wu + * NULL + * reset BSS_DESC_T variables before parsing IE due to peer might have been reconfigured. + * + * 08 20 2010 yuche.tsai + * NULL + * Workaround for P2P Descriptor Infinite loop issue. + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 16 2010 yuche.tsai + * NULL + * Modify code of processing Probe Resonse frame for P2P. + * + * 08 12 2010 yuche.tsai + * NULL + * Add function to get P2P descriptor of BSS descriptor directly. + * + * 08 11 2010 yuche.tsai + * NULL + * Modify Scan result processing for P2P module. + * + * 08 05 2010 yuche.tsai + * NULL + * Update P2P Device Discovery result add function. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 26 2010 yuche.tsai + * + * Add support for Probe Request & Response parsing. + * + * 07 21 2010 cp.wu + * + * 1) change BG_SCAN to ONLINE_SCAN for consistent term + * 2) only clear scanning result when scan is permitted to do + * + * 07 21 2010 yuche.tsai + * + * Fix compile error for SCAN module while disabling P2P feature. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 wh.su + * + * update for security supporting. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, + * other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct BSS_DESC_T initialization after allocated. + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan uninitialization procedure + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * if beacon/probe-resp is received in 2.4GHz bands and there is ELEM_ID_DS_PARAM_SET IE available, + * trust IE instead of RMAC information + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 28 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * send MMPDU in basic rate. + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * modify Beacon/ProbeResp to complete parsing, + * because host software has looser memory usage restriction + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * integrate . + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 21 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Update P2P Function call. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * RSN/PRIVACY compilation flag awareness correction + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * specify correct value for management frames. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 18 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * migration from MT6620 firmware. + * + * 06 17 2010 yuche.tsai + * [WPD00003839][MT6620 5931][P2P] Feature migration + * Fix compile error when enable P2P function. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct when ADHOC support is turned on. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan.c. + * + * 06 04 2010 george.huang + * [BORA00000678][MT6620]WiFi LP integration + * [PM] Support U-APSD for STA mode + * + * 05 28 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * adding the TKIP disallow join a HT AP code. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add more chance of JOIN retry for BG_SCAN + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 04 29 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * adjsut the pre-authentication code. + * + * 04 27 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add Set Slot Time and Beacon Timeout Support for AdHoc Mode + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 19 2010 kevin.huang + * [BORA00000714][WIFISYS][New Feature]Beacon Timeout Support + * Add Beacon Timeout Support and will send Null frame to diagnose connection + * + * 04 13 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add new HW CH macro support + * + * 04 06 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the firmware return the broadcast frame at wrong tc. + * + * 03 29 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * let the rsn wapi IE always parsing. + * + * 03 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Not carry HT cap when being associated with b/g only AP + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Solve the compile warning for 'return non-void' function + * + * 03 16 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Add AdHoc Mode + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * + * * * * * * * * * * * * * * * * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Fix No PKT_INFO_T issue + * + * 02 26 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Update outgoing ProbeRequest Frame's TX data rate + * + * 02 23 2010 wh.su + * [BORA00000592][MT6620 Wi-Fi] Adding the security related code for driver + * refine the scan procedure, reduce the WPA and WAPI IE parsing, and move the parsing to the time for join. + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 02 04 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add AAA Module Support, Revise Net Type to Net Type Index for array lookup + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 22 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Support protection and bandwidth switch + * + * 01 20 2010 kevin.huang + * [BORA00000569][WIFISYS] Phase 2 Integration Test + * Add PHASE_2_INTEGRATION_WORK_AROUND and CFG_SUPPORT_BCM flags + * + * 01 11 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add Deauth and Disassoc Handler + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * + * Refine Beacon processing, add read RF channel from RX Status + * + * 01 04 2010 tehuang.liu + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * For working out the first connection Chariot-verified version + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 12 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Modify u2EstimatedExtraIELen for probe request + * + * Dec 9 2009 mtk01104 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add HT cap IE to probe request + * + * Dec 7 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix lint warning + * + * + * Dec 3 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update the process of SCAN Result by adding more Phy Attributes + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function and code for meet the new define + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Rename u4RSSI to i4RSSI + * + * Nov 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Report event of scan result to host + * + * Nov 26 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix SCAN Record update + * + * Nov 24 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Revise MGMT Handler with Retain Status and Integrate with TXM + * + * Nov 23 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add (Ext)Support Rate Set IE to ProbeReq + * + * Nov 20 2009 mtk02468 + * [BORA00000337] To check in codes for FPGA emulation + * Removed the use of SW_RFB->u2FrameLength + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix uninitial aucMacAddress[] for ProbeReq + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add scanSearchBssDescByPolicy() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Add Send Probe Request Frame + * + * Oct 30 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define REPLICATED_BEACON_TIME_THRESHOLD (3000) +#define REPLICATED_BEACON_FRESH_PERIOD (10000) +#define REPLICATED_BEACON_STRENGTH_THRESHOLD (32) + +#define ROAMING_NO_SWING_RCPI_STEP (10) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used by SCN to initialize its variables +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scnInit(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_BSS_DESC_T prBSSDesc; + PUINT_8 pucBSSBuff; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + pucBSSBuff = &prScanInfo->aucScanBuffer[0]; + + DBGLOG(SCN, INFO, "->scnInit()\n"); + + /* 4 <1> Reset STATE and Message List */ + prScanInfo->eCurrentState = SCAN_STATE_IDLE; + + prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; + + LINK_INITIALIZE(&prScanInfo->rPendingMsgList); + + /* 4 <2> Reset link list of BSS_DESC_T */ + kalMemZero((PVOID) pucBSSBuff, SCN_MAX_BUFFER_SIZE); + + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + + for (i = 0; i < CFG_MAX_NUM_BSS_LIST; i++) { + + prBSSDesc = (P_BSS_DESC_T) pucBSSBuff; + + LINK_INSERT_TAIL(&prScanInfo->rFreeBSSDescList, &prBSSDesc->rLinkEntry); + + pucBSSBuff += ALIGN_4(sizeof(BSS_DESC_T)); + } + /* Check if the memory allocation consist with this initialization function */ + ASSERT(((ULONG) pucBSSBuff - (ULONG)&prScanInfo->aucScanBuffer[0]) == SCN_MAX_BUFFER_SIZE); + + /* reset freest channel information */ + prScanInfo->fgIsSparseChannelValid = FALSE; + + /* reset NLO state */ + prScanInfo->fgNloScanning = FALSE; + prScanInfo->fgPscnOnnning = FALSE; + + prScanInfo->prPscnParam = kalMemAlloc(sizeof(PSCN_PARAM_T), VIR_MEM_TYPE); + if (prScanInfo->prPscnParam) + kalMemZero(prScanInfo->prPscnParam, sizeof(PSCN_PARAM_T)); + +} /* end of scnInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used by SCN to uninitialize its variables +* +* @param (none) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scnUninit(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + DBGLOG(SCN, INFO, "->scnUninit()\n"); + + /* 4 <1> Reset STATE and Message List */ + prScanInfo->eCurrentState = SCAN_STATE_IDLE; + + prScanInfo->rLastScanCompletedTime = (OS_SYSTIME) 0; + + /* NOTE(Kevin): Check rPendingMsgList ? */ + + /* 4 <2> Reset link list of BSS_DESC_T */ + LINK_INITIALIZE(&prScanInfo->rFreeBSSDescList); + LINK_INITIALIZE(&prScanInfo->rBSSDescList); + + kalMemFree(prScanInfo->prPscnParam, VIR_MEM_TYPE, sizeof(PSCN_PARAM_T)); + +} /* end of scnUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + return scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByBssidAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucBSSID[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } else { + /* 20120206 frog: Equal BSSID but not SSID, SSID not hidden, + * SSID must be updated. */ + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen); + return prBssDesc; + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByTA(IN P_ADAPTER_T prAdapter, IN UINT_8 aucSrcAddr[]) +{ + return scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given Transmitter Address. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucSrcAddr Given Source Address(TA). +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchBssDescByTAAndSsid(IN P_ADAPTER_T prAdapter, + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucSrcAddr, aucSrcAddr)) { + if (fgCheckSsid == FALSE || prSsid == NULL) + return prBssDesc; + + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prSsid->aucSsid, prSsid->u4SsidLen)) { + return prBssDesc; + } else if (prDstBssDesc == NULL && prBssDesc->fgIsHiddenSSID == TRUE) { + prDstBssDesc = prBssDesc; + } + + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByTA() */ + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to given BSSID +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByBssidAndLatestUpdateTime(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + P_BSS_DESC_T prDstBssDesc = (P_BSS_DESC_T) NULL; + OS_SYSTIME rLatestUpdateTime = 0; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + if (!rLatestUpdateTime || CHECK_FOR_EXPIRATION(prBssDesc->rUpdateTime, rLatestUpdateTime)) { + prDstBssDesc = prBssDesc; + COPY_SYSTIME(rLatestUpdateTime, prBssDesc->rUpdateTime); + } + } + } + + return prDstBssDesc; + +} /* end of scanSearchBssDescByBssid() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDesc(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, IN UINT_8 aucBSSID[], IN UINT_8 aucSrcAddr[]) +{ + return scanSearchExistingBssDescWithSsid(prAdapter, eBSSType, aucBSSID, aucSrcAddr, FALSE, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Find the corresponding BSS Descriptor according to +* given eBSSType, BSSID and Transmitter Address +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBSSType BSS Type of incoming Beacon/ProbeResp frame. +* @param[in] aucBSSID Given BSSID of Beacon/ProbeResp frame. +* @param[in] aucSrcAddr Given source address (TA) of Beacon/ProbeResp frame. +* @param[in] fgCheckSsid Need to check SSID or not. (for multiple SSID with single BSSID cases) +* @param[in] prSsid Specified SSID +* +* @return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T +scanSearchExistingBssDescWithSsid(IN P_ADAPTER_T prAdapter, + IN ENUM_BSS_TYPE_T eBSSType, + IN UINT_8 aucBSSID[], + IN UINT_8 aucSrcAddr[], IN BOOLEAN fgCheckSsid, IN P_PARAM_SSID_T prSsid) +{ + P_SCAN_INFO_T prScanInfo; + P_BSS_DESC_T prBssDesc, prIBSSBssDesc; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + + + ASSERT(prAdapter); + ASSERT(aucSrcAddr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + switch (eBSSType) { + case BSS_TYPE_P2P_DEVICE: + fgCheckSsid = FALSE; + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_BOW_DEVICE: + { + prBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + + /* if (eBSSType == prBssDesc->eBSSType) */ + + return prBssDesc; + } + + case BSS_TYPE_IBSS: + { + prIBSSBssDesc = scanSearchBssDescByBssidAndSsid(prAdapter, aucBSSID, fgCheckSsid, prSsid); + prBssDesc = scanSearchBssDescByTAAndSsid(prAdapter, aucSrcAddr, fgCheckSsid, prSsid); + + /* NOTE(Kevin): + * Rules to maintain the SCAN Result: + * For AdHoc - + * CASE I We have TA1(BSSID1), but it change its BSSID to BSSID2 + * -> Update TA1 entry's BSSID. + * CASE II We have TA1(BSSID1), and get TA1(BSSID1) again + * -> Update TA1 entry's contain. + * CASE III We have a SCAN result TA1(BSSID1), and TA2(BSSID2). Sooner or + * later, TA2 merge into TA1, we get TA2(BSSID1) + * -> Remove TA2 first and then replace TA1 entry's TA with TA2, + * Still have only one entry of BSSID. + * CASE IV We have a SCAN result TA1(BSSID1), and another TA2 also merge into BSSID1. + * -> Replace TA1 entry's TA with TA2, Still have only one entry. + * CASE V New IBSS + * -> Add this one to SCAN result. + */ + if (prBssDesc) { + if ((!prIBSSBssDesc) || /* CASE I */ + (prBssDesc == prIBSSBssDesc)) { /* CASE II */ + + return prBssDesc; + } /* CASE III */ + + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + return prIBSSBssDesc; + } + + if (prIBSSBssDesc) { /* CASE IV */ + + return prIBSSBssDesc; + } + /* CASE V */ + break; /* Return NULL; */ + } + + default: + break; + } + + return (P_BSS_DESC_T) NULL; + +} /* end of scanSearchExistingBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given Remove Policy. +* +* @param[in] u4RemovePolicy Remove Policy. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveBssDescsByPolicy(IN P_ADAPTER_T prAdapter, IN UINT_32 u4RemovePolicy) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* DBGLOG(SCN, TRACE, ("Before Remove - Number Of SCAN Result = %ld\n", */ + /* prBSSDescList->u4NumElem)); */ + + if (u4RemovePolicy & SCN_RM_POLICY_TIMEOUT) { + P_BSS_DESC_T prBSSDescNext; + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { + + /* DBGLOG(SCN, TRACE, ("Remove TIMEOUT BSS DESC(%#x): + * MAC: %pM, Current Time = %08lx, Update Time = %08lx\n", */ + /* prBssDesc, prBssDesc->aucBSSID, rCurrentTime, prBssDesc->rUpdateTime)); */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + } else if (u4RemovePolicy & SCN_RM_POLICY_OLDEST_HIDDEN) { + P_BSS_DESC_T prBssDescOldest = (P_BSS_DESC_T) NULL; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if (!prBssDesc->fgIsHiddenSSID) + continue; + + if (!prBssDescOldest) { /* 1st element */ + prBssDescOldest = prBssDesc; + continue; + } + + if (TIME_BEFORE(prBssDesc->rUpdateTime, prBssDescOldest->rUpdateTime)) + prBssDescOldest = prBssDesc; + } + + if (prBssDescOldest) { + + /* DBGLOG(SCN, TRACE, ("Remove OLDEST HIDDEN BSS DESC(%#x): + * MAC: %pM, Update Time = %08lx\n", */ + /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescOldest); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescOldest->rLinkEntry); + } + } else if (u4RemovePolicy & SCN_RM_POLICY_SMART_WEAKEST) { + P_BSS_DESC_T prBssDescWeakest = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBssDescWeakestSameSSID = (P_BSS_DESC_T) NULL; + UINT_32 u4SameSSIDCount = 0; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + if ((!prBssDesc->fgIsHiddenSSID) && + (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, prConnSettings->aucSSID, prConnSettings->ucSSIDLen))) { + + u4SameSSIDCount++; + + if (!prBssDescWeakestSameSSID) + prBssDescWeakestSameSSID = prBssDesc; + else if (prBssDesc->ucRCPI < prBssDescWeakestSameSSID->ucRCPI) + prBssDescWeakestSameSSID = prBssDesc; + } + + if (!prBssDescWeakest) { /* 1st element */ + prBssDescWeakest = prBssDesc; + continue; + } + + if (prBssDesc->ucRCPI < prBssDescWeakest->ucRCPI) + prBssDescWeakest = prBssDesc; + + } + + if ((u4SameSSIDCount >= SCN_BSS_DESC_SAME_SSID_THRESHOLD) && (prBssDescWeakestSameSSID)) + prBssDescWeakest = prBssDescWeakestSameSSID; + + if (prBssDescWeakest) { + + /* DBGLOG(SCN, TRACE, ("Remove WEAKEST BSS DESC(%#x): MAC: %pM, Update Time = %08lx\n", */ + /* prBssDescOldest, prBssDescOldest->aucBSSID, prBssDescOldest->rUpdateTime)); */ + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDescWeakest); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDescWeakest->rLinkEntry); + } + } else if (u4RemovePolicy & SCN_RM_POLICY_ENTIRE) { + P_BSS_DESC_T prBSSDescNext; + + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if ((u4RemovePolicy & SCN_RM_POLICY_EXCLUDE_CONNECTED) && + (prBssDesc->fgIsConnected || prBssDesc->fgIsConnecting)) { + /* Don't remove the one currently we are connected. */ + continue; + } + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + + } + + return; + +} /* end of scanRemoveBssDescsByPolicy() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given BSSID. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBSSDescNext; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + +} /* end of scanRemoveBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Delete BSS Descriptors from current list according to given band configuration +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] eBand Given band +* @param[in] eNetTypeIndex AIS - Remove IBSS/Infrastructure BSS +* BOW - Remove BOW BSS +* P2P - Remove P2P BSS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +scanRemoveBssDescByBandAndNetwork(IN P_ADAPTER_T prAdapter, + IN ENUM_BAND_T eBand, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prBSSDescNext; + BOOLEAN fgToRemove; + + ASSERT(prAdapter); + ASSERT(eBand <= BAND_NUM); + ASSERT(eNetTypeIndex <= NETWORK_TYPE_INDEX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + if (eBand == BAND_NULL) + return; /* no need to do anything, keep all scan result */ + + /* Check if such BSS Descriptor exists in a valid list */ + LINK_FOR_EACH_ENTRY_SAFE(prBssDesc, prBSSDescNext, prBSSDescList, rLinkEntry, BSS_DESC_T) { + fgToRemove = FALSE; + + if (prBssDesc->eBand == eBand) { + switch (eNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS)) { + fgToRemove = TRUE; + } + break; + + case NETWORK_TYPE_P2P_INDEX: + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) + fgToRemove = TRUE; + break; + + case NETWORK_TYPE_BOW_INDEX: + if (prBssDesc->eBSSType == BSS_TYPE_BOW_DEVICE) + fgToRemove = TRUE; + break; + + default: + ASSERT(0); + break; + } + } + + if (fgToRemove == TRUE) { + /* Remove this BSS Desc from the BSS Desc list */ + LINK_REMOVE_KNOWN_ENTRY(prBSSDescList, prBssDesc); + + /* Return this BSS Desc to the free BSS Desc list. */ + LINK_INSERT_TAIL(prFreeBSSDescList, &prBssDesc->rLinkEntry); + } + } + +} /* end of scanRemoveBssDescByBand() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear the CONNECTION FLAG of a specified BSS Descriptor. +* +* @param[in] aucBSSID Given BSSID. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID scanRemoveConnFlagOfBssDescByBssid(IN P_ADAPTER_T prAdapter, IN UINT_8 aucBSSID[]) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + + ASSERT(prAdapter); + ASSERT(aucBSSID); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, aucBSSID)) { + prBssDesc->fgIsConnected = FALSE; + prBssDesc->fgIsConnecting = FALSE; + + /* BSSID is not unique, so need to traverse whols link-list */ + } + } + + return; + +} /* end of scanRemoveConnectionFlagOfBssDescByBssid() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate new BSS_DESC_T +* +* @param[in] prAdapter Pointer to the Adapter structure. +* +* @return Pointer to BSS Descriptor, if has free space. NULL, if has no space. +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAllocateBssDesc(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_LINK_T prFreeBSSDescList; + P_BSS_DESC_T prBssDesc; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prFreeBSSDescList = &prScanInfo->rFreeBSSDescList; + + LINK_REMOVE_HEAD(prFreeBSSDescList, prBssDesc, P_BSS_DESC_T); + + if (prBssDesc) { + P_LINK_T prBSSDescList; + + kalMemZero(prBssDesc, sizeof(BSS_DESC_T)); + +#if CFG_ENABLE_WIFI_DIRECT + LINK_INITIALIZE(&(prBssDesc->rP2pDeviceList)); + prBssDesc->fgIsP2PPresent = FALSE; +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + prBSSDescList = &prScanInfo->rBSSDescList; + + /* NOTE(Kevin): In current design, this new empty BSS_DESC_T will be + * inserted to BSSDescList immediately. + */ + LINK_INSERT_TAIL(prBSSDescList, &prBssDesc->rLinkEntry); + } + + return prBssDesc; + +} /* end of scanAllocateBssDesc() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This API parses Beacon/ProbeResp frame and insert extracted BSS_DESC_T +* with IEs into prAdapter->rWifiVar.rScanInfo.aucScanBuffer +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prSwRfb Pointer to the receiving frame buffer. +* +* @return Pointer to BSS Descriptor +* NULL if the Beacon/ProbeResp frame is invalid +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanAddToBssDesc(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_BSS_DESC_T prBssDesc = NULL; + UINT_16 u2CapInfo; + ENUM_BSS_TYPE_T eBSSType = BSS_TYPE_INFRASTRUCTURE; + + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset = 0; + + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; + P_IE_SSID_T prIeSsid = (P_IE_SSID_T) NULL; + P_IE_SUPPORTED_RATE_T prIeSupportedRate = (P_IE_SUPPORTED_RATE_T) NULL; + P_IE_EXT_SUPPORTED_RATE_T prIeExtSupportedRate = (P_IE_EXT_SUPPORTED_RATE_T) NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_8 ucHwChannelNum = 0; + UINT_8 ucIeDsChannelNum = 0; + UINT_8 ucIeHtChannelNum = 0; + BOOLEAN fgIsValidSsid = FALSE, fgEscape = FALSE; + PARAM_SSID_T rSsid; + UINT_64 u8Timestamp; + BOOLEAN fgIsNewBssDesc = FALSE; + + UINT_32 i; + UINT_8 ucSSIDChar; + + UINT_8 ucOuiType; + UINT_16 u2SubTypeVersion; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2CapInfo, &u2CapInfo); + WLAN_GET_FIELD_64(&prWlanBeaconFrame->au4Timestamp[0], &u8Timestamp); + + /* decide BSS type */ + switch (u2CapInfo & CAP_INFO_BSS_TYPE) { + case CAP_INFO_ESS: + /* It can also be Group Owner of P2P Group. */ + eBSSType = BSS_TYPE_INFRASTRUCTURE; + break; + + case CAP_INFO_IBSS: + eBSSType = BSS_TYPE_IBSS; + break; + case 0: + /* The P2P Device shall set the ESS bit of the Capabilities field + * in the Probe Response fame to 0 and IBSS bit to 0. (3.1.2.1.1) */ + eBSSType = BSS_TYPE_P2P_DEVICE; + break; + +#if CFG_ENABLE_BT_OVER_WIFI + /* @TODO: add rule to identify BOW beacons */ +#endif + + default: + DBGLOG(SCN, ERROR, "wrong bss type %d\n", (INT_32)(u2CapInfo & CAP_INFO_BSS_TYPE)); + return NULL; + } + + /* 4 <1.1> Pre-parse SSID IE */ + pucIE = prWlanBeaconFrame->aucInfoElem; + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) + u2IELength = CFG_IE_BUFFER_SIZE; + kalMemZero(&rSsid, sizeof(rSsid)); + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID) { + ucSSIDChar = '\0'; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsValidSsid = FALSE; + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && + * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + + if (ucSSIDChar) + fgIsValidSsid = TRUE; + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (fgIsValidSsid == TRUE) { + COPY_SSID(rSsid.aucSsid, + rSsid.u4SsidLen, SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); + } + } + fgEscape = TRUE; + break; + default: + break; + } + + if (fgEscape == TRUE) + break; + } + if (fgIsValidSsid) + DBGLOG(SCN, EVENT, "%s %pM channel %d\n", rSsid.aucSsid, prWlanBeaconFrame->aucBSSID, + HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); + else + DBGLOG(SCN, EVENT, "hidden ssid, %pM channel %d\n", prWlanBeaconFrame->aucBSSID, + HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr)); + /* 4 <1.2> Replace existing BSS_DESC_T or allocate a new one */ + prBssDesc = scanSearchExistingBssDescWithSsid(prAdapter, + eBSSType, + (PUINT_8) prWlanBeaconFrame->aucBSSID, + (PUINT_8) prWlanBeaconFrame->aucSrcAddr, + fgIsValidSsid, fgIsValidSsid == TRUE ? &rSsid : NULL); + + if (prBssDesc == (P_BSS_DESC_T) NULL) { + fgIsNewBssDesc = TRUE; + + do { + /* 4 <1.2.1> First trial of allocation */ + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) + break; + /* 4 <1.2.2> Hidden is useless, remove the oldest hidden ssid. (for passive scan) */ + scanRemoveBssDescsByPolicy(prAdapter, + (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_OLDEST_HIDDEN)); + + /* 4 <1.2.3> Second tail of allocation */ + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) + break; + /* 4 <1.2.4> Remove the weakest one */ + /* If there are more than half of BSS which has the same ssid as connection + * setting, remove the weakest one from them. + * Else remove the weakest one. + */ + scanRemoveBssDescsByPolicy(prAdapter, + (SCN_RM_POLICY_EXCLUDE_CONNECTED | SCN_RM_POLICY_SMART_WEAKEST)); + + /* 4 <1.2.5> reallocation */ + prBssDesc = scanAllocateBssDesc(prAdapter); + if (prBssDesc) + break; + /* 4 <1.2.6> no space, should not happen */ + DBGLOG(SCN, ERROR, "no bss desc available after remove policy\n"); + return NULL; + + } while (FALSE); + + } else { + OS_SYSTIME rCurrentTime; + + /* WCXRP00000091 */ + /* if the received strength is much weaker than the original one, */ + /* ignore it due to it might be received on the folding frequency */ + + GET_CURRENT_SYSTIME(&rCurrentTime); + + if (prBssDesc->eBSSType != eBSSType) { + prBssDesc->eBSSType = eBSSType; + } else if (HIF_RX_HDR_GET_CHNL_NUM(prSwRfb->prHifRxHdr) != prBssDesc->ucChannelNum && + prBssDesc->ucRCPI > prSwRfb->prHifRxHdr->ucRcpi) { + /* for signal strength is too much weaker and previous beacon is not stale */ + if ((prBssDesc->ucRCPI - prSwRfb->prHifRxHdr->ucRcpi) >= REPLICATED_BEACON_STRENGTH_THRESHOLD && + (rCurrentTime - prBssDesc->rUpdateTime) <= REPLICATED_BEACON_FRESH_PERIOD) { + DBGLOG(SCN, EVENT, "rssi is too much weaker and previous one is fresh\n"); + return prBssDesc; + } + /* for received beacons too close in time domain */ + else if (rCurrentTime - prBssDesc->rUpdateTime <= REPLICATED_BEACON_TIME_THRESHOLD) { + DBGLOG(SCN, EVENT, "receive beacon/probe reponses too close\n"); + return prBssDesc; + } + } + + /* if Timestamp has been reset, re-generate BSS DESC 'cause AP should have reset itself */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && u8Timestamp < prBssDesc->u8TimeStamp.QuadPart) { + BOOLEAN fgIsConnected, fgIsConnecting; + + /* set flag for indicating this is a new BSS-DESC */ + fgIsNewBssDesc = TRUE; + + /* backup 2 flags for APs which reset timestamp unexpectedly */ + fgIsConnected = prBssDesc->fgIsConnected; + fgIsConnecting = prBssDesc->fgIsConnecting; + scanRemoveBssDescByBssid(prAdapter, prBssDesc->aucBSSID); + + prBssDesc = scanAllocateBssDesc(prAdapter); + if (!prBssDesc) + return NULL; + + /* restore */ + prBssDesc->fgIsConnected = fgIsConnected; + prBssDesc->fgIsConnecting = fgIsConnecting; + } + } +#if 1 + + prBssDesc->u2RawLength = prSwRfb->u2PacketLen; + if (prBssDesc->u2RawLength > CFG_RAW_BUFFER_SIZE) + prBssDesc->u2RawLength = CFG_RAW_BUFFER_SIZE; + kalMemCopy(prBssDesc->aucRawBuf, prWlanBeaconFrame, prBssDesc->u2RawLength); +#endif + + /* NOTE: Keep consistency of Scan Record during JOIN process */ + if ((fgIsNewBssDesc == FALSE) && prBssDesc->fgIsConnecting) { + DBGLOG(SCN, INFO, "we're connecting this BSS(%pM) now, don't update it\n", + prBssDesc->aucBSSID); + return prBssDesc; + } + /* 4 <2> Get information from Fixed Fields */ + prBssDesc->eBSSType = eBSSType; /* Update the latest BSS type information. */ + + COPY_MAC_ADDR(prBssDesc->aucSrcAddr, prWlanBeaconFrame->aucSrcAddr); + + COPY_MAC_ADDR(prBssDesc->aucBSSID, prWlanBeaconFrame->aucBSSID); + + prBssDesc->u8TimeStamp.QuadPart = u8Timestamp; + + WLAN_GET_FIELD_16(&prWlanBeaconFrame->u2BeaconInterval, &prBssDesc->u2BeaconInterval); + + prBssDesc->u2CapInfo = u2CapInfo; + + /* 4 <2.1> Retrieve IEs for later parsing */ + u2IELength = (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]); + + if (u2IELength > CFG_IE_BUFFER_SIZE) { + u2IELength = CFG_IE_BUFFER_SIZE; + prBssDesc->fgIsIEOverflow = TRUE; + } else { + prBssDesc->fgIsIEOverflow = FALSE; + } + prBssDesc->u2IELength = u2IELength; + + kalMemCopy(prBssDesc->aucIEBuf, prWlanBeaconFrame->aucInfoElem, u2IELength); + + /* 4 <2.2> reset prBssDesc variables in case that AP has been reconfigured */ + prBssDesc->fgIsERPPresent = FALSE; + prBssDesc->fgIsHTPresent = FALSE; + prBssDesc->eSco = CHNL_EXT_SCN; + prBssDesc->fgIEWAPI = FALSE; +#if CFG_RSN_MIGRATION + prBssDesc->fgIERSN = FALSE; +#endif +#if CFG_PRIVACY_MIGRATION + prBssDesc->fgIEWPA = FALSE; +#endif + + /* 4 <3.1> Full IE parsing on SW_RFB_T */ + pucIE = prWlanBeaconFrame->aucInfoElem; + + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + + switch (IE_ID(pucIE)) { + case ELEM_ID_SSID: + if ((!prIeSsid) && /* NOTE(Kevin): for Atheros IOT #1 */ + (IE_LEN(pucIE) <= ELEM_MAX_LEN_SSID)) { + BOOLEAN fgIsHiddenSSID = FALSE; + + ucSSIDChar = '\0'; + + prIeSsid = (P_IE_SSID_T) pucIE; + + /* D-Link DWL-900AP+ */ + if (IE_LEN(pucIE) == 0) + fgIsHiddenSSID = TRUE; + /* Cisco AP1230A - (IE_LEN(pucIE) == 1) && (SSID_IE(pucIE)->aucSSID[0] == '\0') */ + /* Linksys WRK54G/WL520g - (IE_LEN(pucIE) == n) && + * (SSID_IE(pucIE)->aucSSID[0~(n-1)] == '\0') */ + else { + for (i = 0; i < IE_LEN(pucIE); i++) + ucSSIDChar |= SSID_IE(pucIE)->aucSSID[i]; + + if (!ucSSIDChar) + fgIsHiddenSSID = TRUE; + } + + /* Update SSID to BSS Descriptor only if SSID is not hidden. */ + if (!fgIsHiddenSSID) { + COPY_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + SSID_IE(pucIE)->aucSSID, SSID_IE(pucIE)->ucLength); + } +#if 0 + /* + After we connect to a hidden SSID, prBssDesc->aucSSID[] will + not be empty and prBssDesc->ucSSIDLen will not be 0, + so maybe we need to empty prBssDesc->aucSSID[] and set + prBssDesc->ucSSIDLen to 0 in prBssDesc to avoid that + UI still displays hidden SSID AP in scan list after + we disconnect the hidden SSID AP. + */ + else { + prBssDesc->aucSSID[0] = '\0'; + prBssDesc->ucSSIDLen = 0; + } +#endif + + } + break; + + case ELEM_ID_SUP_RATES: + /* NOTE(Kevin): Buffalo WHR-G54S's supported rate set IE exceed 8. + * IE_LEN(pucIE) == 12, "1(B), 2(B), 5.5(B), 6(B), 9(B), 11(B), + * 12(B), 18(B), 24(B), 36(B), 48(B), 54(B)" + */ + /* TP-LINK will set extra and incorrect ie with ELEM_ID_SUP_RATES */ + if ((!prIeSupportedRate) && (IE_LEN(pucIE) <= RATE_NUM)) + prIeSupportedRate = SUP_RATES_IE(pucIE); + break; + + case ELEM_ID_DS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_DS_PARAMETER_SET) + ucIeDsChannelNum = DS_PARAM_IE(pucIE)->ucCurrChnl; + break; + + case ELEM_ID_TIM: + if (IE_LEN(pucIE) <= ELEM_MAX_LEN_TIM) + prBssDesc->ucDTIMPeriod = TIM_IE(pucIE)->ucDTIMPeriod; + break; + + case ELEM_ID_IBSS_PARAM_SET: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_IBSS_PARAMETER_SET) + prBssDesc->u2ATIMWindow = IBSS_PARAM_IE(pucIE)->u2ATIMWindow; + break; + +#if 0 /* CFG_SUPPORT_802_11D */ + case ELEM_ID_COUNTRY_INFO: + prBssDesc->prIECountry = (P_IE_COUNTRY_T) pucIE; + break; +#endif + + case ELEM_ID_ERP_INFO: + if (IE_LEN(pucIE) == ELEM_MAX_LEN_ERP) + prBssDesc->fgIsERPPresent = TRUE; + break; + + case ELEM_ID_EXTENDED_SUP_RATES: + if (!prIeExtSupportedRate) + prIeExtSupportedRate = EXT_SUP_RATES_IE(pucIE); + break; + +#if CFG_RSN_MIGRATION + case ELEM_ID_RSN: + if (rsnParseRsnIE(prAdapter, RSN_IE(pucIE), &prBssDesc->rRSNInfo)) { + prBssDesc->fgIERSN = TRUE; + prBssDesc->u2RsnCap = prBssDesc->rRSNInfo.u2RsnCap; + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) + rsnCheckPmkidCache(prAdapter, prBssDesc); + } + break; +#endif + + case ELEM_ID_HT_CAP: + prBssDesc->fgIsHTPresent = TRUE; + break; + + case ELEM_ID_HT_OP: + if (IE_LEN(pucIE) != (sizeof(IE_HT_OP_T) - 2)) + break; + + if ((((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO) != CHNL_EXT_RES) { + prBssDesc->eSco = (ENUM_CHNL_EXT_T) + (((P_IE_HT_OP_T) pucIE)->ucInfo1 & HT_OP_INFO1_SCO); + } + ucIeHtChannelNum = ((P_IE_HT_OP_T) pucIE)->ucPrimaryChannel; + + break; + +#if CFG_SUPPORT_WAPI + case ELEM_ID_WAPI: + if (wapiParseWapiIE(WAPI_IE(pucIE), &prBssDesc->rIEWAPI)) + prBssDesc->fgIEWAPI = TRUE; + break; +#endif + + case ELEM_ID_VENDOR: /* ELEM_ID_P2P, ELEM_ID_WMM */ +#if CFG_PRIVACY_MIGRATION + if (rsnParseCheckForWFAInfoElem(prAdapter, pucIE, &ucOuiType, &u2SubTypeVersion)) { + if ((ucOuiType == VENDOR_OUI_TYPE_WPA) && (u2SubTypeVersion == VERSION_WPA)) { + + if (rsnParseWpaIE(prAdapter, WPA_IE(pucIE), &prBssDesc->rWPAInfo)) + prBssDesc->fgIEWPA = TRUE; + } + } +#endif + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if (p2pFuncParseCheckForP2PInfoElem(prAdapter, pucIE, &ucOuiType)) { + if (ucOuiType == VENDOR_OUI_TYPE_P2P) + prBssDesc->fgIsP2PPresent = TRUE; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + break; + + /* no default */ + } + } + + /* 4 <3.2> Save information from IEs - SSID */ + /* Update Flag of Hidden SSID for used in SEARCH STATE. */ + + /* NOTE(Kevin): in current driver, the ucSSIDLen == 0 represent + * all cases of hidden SSID. + * If the fgIsHiddenSSID == TRUE, it means we didn't get the ProbeResp with + * valid SSID. + */ + if (prBssDesc->ucSSIDLen == 0) + prBssDesc->fgIsHiddenSSID = TRUE; + else + prBssDesc->fgIsHiddenSSID = FALSE; + + /* 4 <3.3> Check rate information in related IEs. */ + if (prIeSupportedRate || prIeExtSupportedRate) { + rateGetRateSetFromIEs(prIeSupportedRate, + prIeExtSupportedRate, + &prBssDesc->u2OperationalRateSet, + &prBssDesc->u2BSSBasicRateSet, &prBssDesc->fgIsUnknownBssBasicRate); + } + /* 4 <4> Update information from HIF RX Header */ + { + prHifRxHdr = prSwRfb->prHifRxHdr; + + ASSERT(prHifRxHdr); + + /* 4 <4.1> Get TSF comparison result */ + prBssDesc->fgIsLargerTSF = HIF_RX_HDR_GET_TCL_FLAG(prHifRxHdr); + + /* 4 <4.2> Get Band information */ + prBssDesc->eBand = HIF_RX_HDR_GET_RF_BAND(prHifRxHdr); + + /* 4 <4.2> Get channel and RCPI information */ + ucHwChannelNum = HIF_RX_HDR_GET_CHNL_NUM(prHifRxHdr); + + if (BAND_2G4 == prBssDesc->eBand) { + + /* Update RCPI if in right channel */ + if (ucIeDsChannelNum >= 1 && ucIeDsChannelNum <= 14) { + + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucIeDsChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeDsChannelNum; + } else if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum <= 14) { + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucIeHtChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + /* 5G Band */ + else { + if (ucIeHtChannelNum >= 1 && ucIeHtChannelNum < 200) { + /* Receive Beacon/ProbeResp frame from adjacent channel. */ + if ((ucIeHtChannelNum == ucHwChannelNum) || (prHifRxHdr->ucRcpi > prBssDesc->ucRCPI)) + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + /* trust channel information brought by IE */ + prBssDesc->ucChannelNum = ucIeHtChannelNum; + } else { + /* Always update RCPI */ + prBssDesc->ucRCPI = prHifRxHdr->ucRcpi; + + prBssDesc->ucChannelNum = ucHwChannelNum; + } + } + } + + /* 4 <5> PHY type setting */ + prBssDesc->ucPhyTypeSet = 0; + + if (BAND_2G4 == prBssDesc->eBand) { + /* check if support 11n */ + if (prBssDesc->fgIsHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* check if support 11g */ + if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) || prBssDesc->fgIsERPPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_ERP; + + /* if not 11g only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_OFDM)) { + /* check if support 11b */ + if ((prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HR_DSSS; + } + } + } else { /* (BAND_5G == prBssDesc->eBande) */ + /* check if support 11n */ + if (prBssDesc->fgIsHTPresent) + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_HT; + + /* if not 11n only */ + if (!(prBssDesc->u2BSSBasicRateSet & RATE_SET_BIT_HT_PHY)) { + /* Support 11a definitely */ + prBssDesc->ucPhyTypeSet |= PHY_TYPE_BIT_OFDM; + + ASSERT(!(prBssDesc->u2OperationalRateSet & RATE_SET_HR_DSSS)); + } + } + + /* 4 <6> Update BSS_DESC_T's Last Update TimeStamp. */ + GET_CURRENT_SYSTIME(&prBssDesc->rUpdateTime); + + return prBssDesc; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Convert the Beacon or ProbeResp Frame in SW_RFB_T to scan result for query +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS It is a valid Scan Result and been sent to the host. +* @retval WLAN_STATUS_FAILURE It is not a valid Scan Result. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS scanAddScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBssDesc, IN P_SW_RFB_T prSwRfb) +{ + P_SCAN_INFO_T prScanInfo; + UINT_8 aucRatesEx[PARAM_MAX_LEN_RATES_EX]; + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame; + PARAM_MAC_ADDRESS rMacAddr; + PARAM_SSID_T rSsid; + ENUM_PARAM_NETWORK_TYPE_T eNetworkType; + PARAM_802_11_CONFIG_T rConfiguration; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_8 ucRateLen = 0; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prBssDesc->eBand == BAND_2G4) { + if ((prBssDesc->u2OperationalRateSet & RATE_SET_OFDM) + || prBssDesc->fgIsERPPresent) { + eNetworkType = PARAM_NETWORK_TYPE_OFDM24; + } else { + eNetworkType = PARAM_NETWORK_TYPE_DS; + } + } else { + ASSERT(prBssDesc->eBand == BAND_5G); + eNetworkType = PARAM_NETWORK_TYPE_OFDM5; + } + + if (prBssDesc->eBSSType == BSS_TYPE_P2P_DEVICE) { + /* NOTE(Kevin): Not supported by WZC(TBD) */ + return WLAN_STATUS_FAILURE; + } + + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + COPY_MAC_ADDR(rMacAddr, prWlanBeaconFrame->aucBSSID); + COPY_SSID(rSsid.aucSsid, rSsid.u4SsidLen, prBssDesc->aucSSID, prBssDesc->ucSSIDLen); + + rConfiguration.u4Length = sizeof(PARAM_802_11_CONFIG_T); + rConfiguration.u4BeaconPeriod = (UINT_32) prWlanBeaconFrame->u2BeaconInterval; + rConfiguration.u4ATIMWindow = prBssDesc->u2ATIMWindow; + rConfiguration.u4DSConfig = nicChannelNum2Freq(prBssDesc->ucChannelNum); + rConfiguration.rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + rateGetDataRatesFromRateSet(prBssDesc->u2OperationalRateSet, 0, aucRatesEx, &ucRateLen); + + /* NOTE(Kevin): Set unused entries, if any, at the end of the array to 0. + * from OID_802_11_BSSID_LIST + */ + for (i = ucRateLen; i < sizeof(aucRatesEx) / sizeof(aucRatesEx[0]); i++) + aucRatesEx[i] = 0; + + switch (prBssDesc->eBSSType) { + case BSS_TYPE_IBSS: + eOpMode = NET_TYPE_IBSS; + break; + + case BSS_TYPE_INFRASTRUCTURE: + case BSS_TYPE_P2P_DEVICE: + case BSS_TYPE_BOW_DEVICE: + default: + eOpMode = NET_TYPE_INFRA; + break; + } + + DBGLOG(SCN, TRACE, "ind %s %d\n", prBssDesc->aucSSID, prBssDesc->ucChannelNum); + +#if (CFG_SUPPORT_TDLS == 1) + { + if (flgTdlsTestExtCapElm == TRUE) { + /* only for RALINK AP */ + UINT8 *pucElm = (UINT8 *) (prSwRfb->pvHeader + prSwRfb->u2PacketLen); + + kalMemCopy(pucElm - 9, aucTdlsTestExtCapElm, 7); + prSwRfb->u2PacketLen -= 2; +/* prSwRfb->u2PacketLen += 7; */ + + DBGLOG(TDLS, INFO, + " %s: append ext cap element to %pM\n", + __func__, prBssDesc->aucBSSID); + } + } +#endif /* CFG_SUPPORT_TDLS */ + + if (prAdapter->rWifiVar.rScanInfo.fgNloScanning && + test_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag)) { + UINT_8 i = 0; + P_BSS_DESC_T *pprPendBssDesc = &prScanInfo->rNloParam.aprPendingBssDescToInd[0]; + + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprPendBssDesc[i]) + continue; + DBGLOG(SCN, INFO, + "indicate bss[%pM] before wiphy resume, need to indicate again after wiphy resume\n", + prBssDesc->aucBSSID); + pprPendBssDesc[i] = prBssDesc; + break; + } + } + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prSwRfb->pvHeader, + prSwRfb->u2PacketLen, prBssDesc->ucChannelNum, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + nicAddScanResult(prAdapter, + rMacAddr, + &rSsid, + prWlanBeaconFrame->u2CapInfo & CAP_INFO_PRIVACY ? 1 : 0, + RCPI_TO_dBm(prBssDesc->ucRCPI), + eNetworkType, + &rConfiguration, + eOpMode, + aucRatesEx, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen, + (PUINT_8) ((ULONG) (prSwRfb->pvHeader) + WLAN_MAC_MGMT_HEADER_LEN)); + + return WLAN_STATUS_SUCCESS; + +} /* end of scanAddScanResult() */ + +#if 1 + +BOOLEAN scanCheckBssIsLegal(IN P_ADAPTER_T prAdapter, P_BSS_DESC_T prBssDesc) +{ + BOOLEAN fgAddToScanResult = FALSE; + ENUM_BAND_T eBand = 0; + UINT_8 ucChannel = 0; + + ASSERT(prAdapter); + /* check the channel is in the legal doamin */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == TRUE) { + /* check ucChannelNum/eBand for adjacement channel filtering */ + if (cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel) == TRUE && + (eBand != prBssDesc->eBand || ucChannel != prBssDesc->ucChannelNum)) { + fgAddToScanResult = FALSE; + } else { + fgAddToScanResult = TRUE; + } + } + return fgAddToScanResult; + +} + +VOID scanReportBss2Cfg80211(IN P_ADAPTER_T prAdapter, IN ENUM_BSS_TYPE_T eBSSType, IN P_BSS_DESC_T SpecificprBssDesc) +{ + P_SCAN_INFO_T prScanInfo = (P_SCAN_INFO_T) NULL; + P_LINK_T prBSSDescList = (P_LINK_T) NULL; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + RF_CHANNEL_INFO_T rChannelInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prBSSDescList = &prScanInfo->rBSSDescList; + + DBGLOG(SCN, TRACE, "scanReportBss2Cfg80211\n"); + + if (SpecificprBssDesc) { + { + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, SpecificprBssDesc)) { + DBGLOG(SCN, TRACE, "Remove specific SSID[%s %d]\n", + SpecificprBssDesc->aucSSID, SpecificprBssDesc->ucChannelNum); + return; + } + + DBGLOG(SCN, TRACE, "Report Specific SSID[%s]\n", SpecificprBssDesc->aucSSID); + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + SpecificprBssDesc->ucChannelNum, + RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + } else { + + rChannelInfo.ucChannelNum = SpecificprBssDesc->ucChannelNum; + rChannelInfo.eBand = SpecificprBssDesc->eBand; + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) SpecificprBssDesc->aucRawBuf, + SpecificprBssDesc->u2RawLength, + &rChannelInfo, RCPI_TO_dBm(SpecificprBssDesc->ucRCPI)); + + } + +#if CFG_ENABLE_WIFI_DIRECT + SpecificprBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + /* 4 Auto Channel Selection:Record the AP Number */ + P_PARAM_CHN_LOAD_INFO prChnLoad; + UINT_8 ucIdx = 0; + + if (((prBssDesc->ucChannelNum > 0) && (prBssDesc->ucChannelNum <= 48)) + || (prBssDesc->ucChannelNum >= 147) /*non-DFS Channel */) { + if (prBssDesc->ucChannelNum <= HW_CHNL_NUM_MAX_2G4) { + ucIdx = prBssDesc->ucChannelNum - 1; + } else if (prBssDesc->ucChannelNum <= 48) { + ucIdx = (UINT_8) (HW_CHNL_NUM_MAX_2G4 + (prBssDesc->ucChannelNum - 34) / 4); + } else { + ucIdx = + (UINT_8) (HW_CHNL_NUM_MAX_2G4 + 4 + (prBssDesc->ucChannelNum - 149) / 4); + } + + if (ucIdx < MAX_AUTO_CHAL_NUM) { + prChnLoad = (P_PARAM_CHN_LOAD_INFO) & + (prAdapter->rWifiVar.rChnLoadInfo.rEachChnLoad[ucIdx]); + prChnLoad->ucChannel = prBssDesc->ucChannelNum; + prChnLoad->u2APNum++; + } else { + DBGLOG(SCN, WARN, "ACS: ChIdx > MAX_AUTO_CHAL_NUM\n"); + } + + } +#endif + /* check BSSID is legal channel */ + if (!scanCheckBssIsLegal(prAdapter, prBssDesc)) { + DBGLOG(SCN, TRACE, "Remove SSID[%s %d]\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + continue; + } + + if ((prBssDesc->eBSSType == eBSSType) +#if CFG_ENABLE_WIFI_DIRECT + || ((eBSSType == BSS_TYPE_P2P_DEVICE) && (prBssDesc->fgIsP2PReport == TRUE)) +#endif + ) { + + DBGLOG(SCN, TRACE, "Report ALL SSID[%s %d]\n", + prBssDesc->aucSSID, prBssDesc->ucChannelNum); + + if (eBSSType == BSS_TYPE_INFRASTRUCTURE) { + if (prBssDesc->u2RawLength != 0) { + kalIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + prBssDesc->ucChannelNum, + RCPI_TO_dBm(prBssDesc->ucRCPI)); + kalMemZero(prBssDesc->aucRawBuf, CFG_RAW_BUFFER_SIZE); + prBssDesc->u2RawLength = 0; + +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; +#endif + } + } else { +#if CFG_ENABLE_WIFI_DIRECT + if (prBssDesc->fgIsP2PReport == TRUE) { +#endif + rChannelInfo.ucChannelNum = prBssDesc->ucChannelNum; + rChannelInfo.eBand = prBssDesc->eBand; + + kalP2PIndicateBssInfo(prAdapter->prGlueInfo, + (PUINT_8) prBssDesc->aucRawBuf, + prBssDesc->u2RawLength, + &rChannelInfo, RCPI_TO_dBm(prBssDesc->ucRCPI)); + + /* do not clear it then we can pass the bss in Specific report */ + /* kalMemZero(prBssDesc->aucRawBuf,CFG_RAW_BUFFER_SIZE); */ + + /* + the BSS entry will not be cleared after scan done. + So if we dont receive the BSS in next scan, we cannot + pass it. We use u2RawLength for the purpose. + */ + /* prBssDesc->u2RawLength=0; */ +#if CFG_ENABLE_WIFI_DIRECT + prBssDesc->fgIsP2PReport = FALSE; + } +#endif + } + } + + } +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = TRUE; +#endif + + } + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse the content of given Beacon or ProbeResp Frame. +* +* @param[in] prSwRfb Pointer to the receiving SW_RFB_T structure. +* +* @retval WLAN_STATUS_SUCCESS if not report this SW_RFB_T to host +* @retval WLAN_STATUS_PENDING if report this SW_RFB_T to host as scan result +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS scanProcessBeaconAndProbeResp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_BSS_INFO_T prAisBssInfo; + P_WLAN_BEACON_FRAME_T prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) NULL; +#if CFG_SLT_SUPPORT + P_SLT_INFO_T prSltInfo = (P_SLT_INFO_T) NULL; +#endif + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + /* 4 <0> Ignore invalid Beacon Frame */ + if ((prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) < + (TIMESTAMP_FIELD_LEN + BEACON_INTERVAL_FIELD_LEN + CAP_INFO_FIELD_LEN)) { + /* to debug beacon length too small issue */ + UINT_32 u4MailBox0; + + nicGetMailbox(prAdapter, 0, &u4MailBox0); + DBGLOG(SCN, WARN, "if conn sys also get less length (0x5a means yes) %x\n", (UINT_32) u4MailBox0); + DBGLOG(SCN, WARN, "u2PacketLen %d, u2HeaderLen %d, payloadLen %d\n", + prSwRfb->u2PacketLen, prSwRfb->u2HeaderLen, + prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen); + /* dumpMemory8(prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + +#ifndef _lint + ASSERT(0); +#endif /* _lint */ + return rStatus; + } +#if CFG_SLT_SUPPORT + prSltInfo = &prAdapter->rWifiVar.rSltInfo; + + if (prSltInfo->fgIsDUT) { + DBGLOG(SCN, INFO, "\n\rBCN: RX\n"); + prSltInfo->u4BeaconReceiveCnt++; + return WLAN_STATUS_SUCCESS; + } else { + return WLAN_STATUS_SUCCESS; + } +#endif + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prWlanBeaconFrame = (P_WLAN_BEACON_FRAME_T) prSwRfb->pvHeader; + + /*ALPS01475157: don't show SSID on scan list for multicast MAC AP */ + if (IS_BMCAST_MAC_ADDR(prWlanBeaconFrame->aucSrcAddr)) { + DBGLOG(SCN, WARN, "received beacon/probe response from multicast AP\n"); + return rStatus; + } + + /* 4 <1> Parse and add into BSS_DESC_T */ + prBssDesc = scanAddToBssDesc(prAdapter, prSwRfb); + + if (prBssDesc) { + /* 4 <1.1> Beacon Change Detection for Connected BSS */ + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED && + ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA)) && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && + EQUAL_SSID(prBssDesc->aucSSID, prBssDesc->ucSSIDLen, prAisBssInfo->aucSSID, + prAisBssInfo->ucSSIDLen)) { + BOOLEAN fgNeedDisconnect = FALSE; + +#if CFG_SUPPORT_BEACON_CHANGE_DETECTION + /* <1.1.2> check if supported rate differs */ + if (prAisBssInfo->u2OperationalRateSet != prBssDesc->u2OperationalRateSet) + fgNeedDisconnect = TRUE; +#endif +#if CFG_SUPPORT_DETECT_SECURITY_MODE_CHANGE + if ( +#if CFG_SUPPORT_WAPI + (prAdapter->rWifiVar.rConnSettings.fgWapiMode == TRUE && + !wapiPerformPolicySelection(prAdapter, prBssDesc)) || +#endif + rsnCheckSecurityModeChanged(prAdapter, prAisBssInfo, prBssDesc)) { + DBGLOG(SCN, INFO, "Beacon security mode change detected\n"); + fgNeedDisconnect = FALSE; + aisBssSecurityChanged(prAdapter); + } +#endif + + /* <1.1.3> beacon content change detected, disconnect immediately */ + if (fgNeedDisconnect == TRUE) + aisBssBeaconTimeout(prAdapter); + } + /* 4 <1.1> Update AIS_BSS_INFO */ + if (((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE && prConnSettings->eOPMode != NET_TYPE_IBSS) + || (prBssDesc->eBSSType == BSS_TYPE_IBSS && prConnSettings->eOPMode != NET_TYPE_INFRA))) { + if (prAisBssInfo->eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* *not* checking prBssDesc->fgIsConnected anymore, + * due to Linksys AP uses " " as hidden SSID, and would have different BSS descriptor */ + if ((!prAisBssInfo->ucDTIMPeriod) && + EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prAisBssInfo->aucBSSID) && + (prAisBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && + ((prWlanBeaconFrame->u2FrameCtrl & MASK_FRAME_TYPE) == MAC_FRAME_BEACON)) { + + prAisBssInfo->ucDTIMPeriod = prBssDesc->ucDTIMPeriod; + + /* sync with firmware for beacon information */ + nicPmIndicateBssConnected(prAdapter, NETWORK_TYPE_AIS_INDEX); + } + } +#if CFG_SUPPORT_ADHOC + if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, + prConnSettings->ucSSIDLen) && + (prBssDesc->eBSSType == BSS_TYPE_IBSS) && (prAisBssInfo->eCurrentOPMode == OP_MODE_IBSS)) { + ibssProcessMatchedBeacon(prAdapter, prAisBssInfo, prBssDesc, + prSwRfb->prHifRxHdr->ucRcpi); + } +#endif /* CFG_SUPPORT_ADHOC */ + } + + rlmProcessBcn(prAdapter, + prSwRfb, + ((P_WLAN_BEACON_FRAME_T) (prSwRfb->pvHeader))->aucInfoElem, + (prSwRfb->u2PacketLen - prSwRfb->u2HeaderLen) - + (UINT_16) (OFFSET_OF(WLAN_BEACON_FRAME_BODY_T, aucInfoElem[0]))); + + /* 4 <3> Send SW_RFB_T to HIF when we perform SCAN for HOST */ + if (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE || prBssDesc->eBSSType == BSS_TYPE_IBSS) { + /* for AIS, send to host */ + if (prConnSettings->fgIsScanReqIssued || prAdapter->rWifiVar.rScanInfo.fgNloScanning) { + BOOLEAN fgAddToScanResult; + + fgAddToScanResult = scanCheckBssIsLegal(prAdapter, prBssDesc); + + if (fgAddToScanResult == TRUE) + rStatus = scanAddScanResult(prAdapter, prBssDesc, prSwRfb); + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + scanP2pProcessBeaconAndProbeResp(prAdapter, prSwRfb, &rStatus, prBssDesc, prWlanBeaconFrame); +#endif + } + + return rStatus; + +} /* end of scanProcessBeaconAndProbeResp() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Search the Candidate of BSS Descriptor for JOIN(Infrastructure) or +* MERGE(AdHoc) according to current Connection Policy. +* +* \return Pointer to BSS Descriptor, if found. NULL, if not found +*/ +/*----------------------------------------------------------------------------*/ +P_BSS_DESC_T scanSearchBssDescByPolicy(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + P_BSS_INFO_T prBssInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + P_SCAN_INFO_T prScanInfo; + + P_LINK_T prBSSDescList; + + P_BSS_DESC_T prBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prPrimaryBssDesc = (P_BSS_DESC_T) NULL; + P_BSS_DESC_T prCandidateBssDesc = (P_BSS_DESC_T) NULL; + + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + P_STA_RECORD_T prPrimaryStaRec; + P_STA_RECORD_T prCandidateStaRec = (P_STA_RECORD_T) NULL; + + OS_SYSTIME rCurrentTime; + + /* The first one reach the check point will be our candidate */ + BOOLEAN fgIsFindFirst = (BOOLEAN) FALSE; + + BOOLEAN fgIsFindBestRSSI = (BOOLEAN) FALSE; + BOOLEAN fgIsFindBestEncryptionLevel = (BOOLEAN) FALSE; + /* BOOLEAN fgIsFindMinChannelLoad = (BOOLEAN)FALSE; */ + + /* TODO(Kevin): Support Min Channel Load */ + /* UINT_8 aucChannelLoad[CHANNEL_NUM] = {0}; */ + + BOOLEAN fgIsFixedChannel; + ENUM_BAND_T eBand = 0; + UINT_8 ucChannel = 0; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetTypeIndex]); + + prAisSpecBssInfo = &(prAdapter->rWifiVar.rAisSpecificBssInfo); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + GET_CURRENT_SYSTIME(&rCurrentTime); + + /* check for fixed channel operation */ + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { +#if CFG_P2P_LEGACY_COEX_REVISE + fgIsFixedChannel = cnmAisDetectP2PChannel(prAdapter, &eBand, &ucChannel); +#else + fgIsFixedChannel = cnmAisInfraChannelFixed(prAdapter, &eBand, &ucChannel); +#endif + } else { + fgIsFixedChannel = FALSE; + } + +#if DBG + if (prConnSettings->ucSSIDLen < ELEM_MAX_LEN_SSID) + prConnSettings->aucSSID[prConnSettings->ucSSIDLen] = '\0'; +#endif + + DBGLOG(SCN, INFO, "SEARCH: Bss Num: %d, Look for SSID: %s, %pM Band=%d, channel=%d\n", + (UINT_32) prBSSDescList->u4NumElem, prConnSettings->aucSSID, + (prConnSettings->aucBSSID), eBand, ucChannel); + + /* 4 <1> The outer loop to search for a candidate. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + + /* TODO(Kevin): Update Minimum Channel Load Information here */ + + DBGLOG(SCN, TRACE, "SEARCH: [ %pM ], SSID:%s\n", + prBssDesc->aucBSSID, prBssDesc->aucSSID); + + /* 4 <2> Check PHY Type and attributes */ + /* 4 <2.1> Check Unsupported BSS PHY Type */ + if (!(prBssDesc->ucPhyTypeSet & (prAdapter->rWifiVar.ucAvailablePhyTypeSet))) { + DBGLOG(SCN, TRACE, "SEARCH: Ignore unsupported ucPhyTypeSet = %x\n", prBssDesc->ucPhyTypeSet); + continue; + } + /* 4 <2.2> Check if has unknown NonHT BSS Basic Rate Set. */ + if (prBssDesc->fgIsUnknownBssBasicRate) + continue; + /* 4 <2.3> Check if fixed operation cases should be aware */ + if (fgIsFixedChannel == TRUE && (prBssDesc->eBand != eBand || prBssDesc->ucChannelNum != ucChannel)) + continue; + /* 4 <2.4> Check if the channel is legal under regulatory domain */ + if (rlmDomainIsLegalChannel(prAdapter, prBssDesc->eBand, prBssDesc->ucChannelNum) == FALSE) + continue; + /* 4 <2.5> Check if this BSS_DESC_T is stale */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_BSS_DESC_REMOVE_TIMEOUT_SEC))) { + + BOOLEAN fgIsNeedToCheckTimeout = TRUE; + +#if CFG_SUPPORT_ROAMING + P_ROAMING_INFO_T prRoamingFsmInfo; + + prRoamingFsmInfo = (P_ROAMING_INFO_T) &(prAdapter->rWifiVar.rRoamingInfo); + if ((prRoamingFsmInfo->eCurrentState == ROAMING_STATE_DISCOVERY) || + (prRoamingFsmInfo->eCurrentState == ROAMING_STATE_ROAM)) { + if (++prRoamingFsmInfo->RoamingEntryTimeoutSkipCount < + ROAMING_ENTRY_TIMEOUT_SKIP_COUNT_MAX) { + fgIsNeedToCheckTimeout = FALSE; + DBGLOG(SCN, INFO, "SEARCH: Romaing skip SCN_BSS_DESC_REMOVE_TIMEOUT_SEC\n"); + } + } +#endif + + if (fgIsNeedToCheckTimeout == TRUE) { + DBGLOG(SCN, TRACE, "Ignore stale bss %pM\n", prBssDesc->aucBSSID); + continue; + } + } + /* 4 <3> Check if reach the excessive join retry limit */ + /* NOTE(Kevin): STA_RECORD_T is recorded by TA. */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) eNetTypeIndex, prBssDesc->aucSrcAddr); + + if (prStaRec) { + /* NOTE(Kevin): + * The Status Code is the result of a Previous Connection Request, + * we use this as SCORE for choosing a proper + * candidate (Also used for compare see <6>) + * The Reason Code is an indication of the reason why AP reject us, + * we use this Code for "Reject" + * a SCAN result to become our candidate(Like a blacklist). + */ +#if 0 /* TODO(Kevin): */ + if (prStaRec->u2ReasonCode != REASON_CODE_RESERVED) { + DBGLOG(SCN, INFO, "SEARCH: Ignore BSS with previous Reason Code = %d\n", + prStaRec->u2ReasonCode); + continue; + } else +#endif + if (prStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + /* NOTE(Kevin): greedy association - after timeout, we'll still + * try to associate to the AP whose STATUS of conection attempt + * was not success. + * We may also use (ucJoinFailureCount x JOIN_RETRY_INTERVAL_SEC) for + * time bound. + */ + if ((prStaRec->ucJoinFailureCount < JOIN_MAX_RETRY_FAILURE_COUNT) || + (CHECK_FOR_TIMEOUT(rCurrentTime, + prStaRec->rLastJoinTime, + SEC_TO_SYSTIME(JOIN_RETRY_INTERVAL_SEC)))) { + + /* NOTE(Kevin): Every JOIN_RETRY_INTERVAL_SEC interval, we can retry + * JOIN_MAX_RETRY_FAILURE_COUNT times. + */ + if (prStaRec->ucJoinFailureCount >= JOIN_MAX_RETRY_FAILURE_COUNT) + prStaRec->ucJoinFailureCount = 0; + DBGLOG(SCN, INFO, + "SEARCH: Try to join BSS again,Status Code=%d (Curr=%u/Last Join=%u)\n", + prStaRec->u2StatusCode, rCurrentTime, prStaRec->rLastJoinTime); + } else { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS which reach maximum Join Retry Count = %d\n", + JOIN_MAX_RETRY_FAILURE_COUNT); + continue; + } + + } + } + /* 4 <4> Check for various NETWORK conditions */ + if (eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + + /* 4 <4.1> Check BSS Type for the corresponding Operation Mode in Connection Setting */ + /* NOTE(Kevin): For NET_TYPE_AUTO_SWITCH, we will always pass following check. */ + if (((prConnSettings->eOPMode == NET_TYPE_INFRA) && + (prBssDesc->eBSSType != BSS_TYPE_INFRASTRUCTURE)) +#if CFG_SUPPORT_ADHOC + || ((prConnSettings->eOPMode == NET_TYPE_IBSS + || prConnSettings->eOPMode == NET_TYPE_DEDICATED_IBSS) + && (prBssDesc->eBSSType != BSS_TYPE_IBSS)) +#endif + ) { + + DBGLOG(SCN, TRACE, "Cur OPMode %d, Ignore eBSSType = %d\n", + prConnSettings->eOPMode, prBssDesc->eBSSType); + continue; + } + /* 4 <4.2> Check AP's BSSID if OID_802_11_BSSID has been set. */ + if ((prConnSettings->fgIsConnByBssidIssued) && + (prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE)) { + + if (UNEQUAL_MAC_ADDR(prConnSettings->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, TRACE, "SEARCH: Ignore due to BSSID was not matched!\n"); + continue; + } + } +#if CFG_SUPPORT_ADHOC + /* 4 <4.3> Check for AdHoc Mode */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + /* 4 <4.3.1> Check if this SCAN record has been updated recently for IBSS. */ + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS - e.g. IPN2220, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(SCN_ADHOC_BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCN, LOUD, + "SEARCH: Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + prBssDesc->aucBSSID); + continue; + } + /* 4 <4.3.2> Check Peer's capability */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, prBssDesc) == WLAN_STATUS_FAILURE) { + + if (prPrimaryBssDesc) + DBGLOG(SCN, INFO, + "SEARCH: BSS DESC MAC: %pM, not supported AdHoc Mode.\n", + prPrimaryBssDesc->aucBSSID); + + continue; + } + /* 4 <4.3.3> Compare TSF */ + if (prBssInfo->fgIsBeaconActivated && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prBssDesc->aucBSSID)) { + + DBGLOG(SCN, LOUD, + "SEARCH: prBssDesc->fgIsLargerTSF = %d\n", prBssDesc->fgIsLargerTSF); + + if (!prBssDesc->fgIsLargerTSF) { + DBGLOG(SCN, INFO, + "SEARCH: Ignore BSS DESC MAC: [ %pM ], Smaller TSF\n", + prBssDesc->aucBSSID); + continue; + } + } + } +#endif /* CFG_SUPPORT_ADHOC */ + + } +#if 0 /* TODO(Kevin): For IBSS */ + /* 4 <2.c> Check if this SCAN record has been updated recently for IBSS. */ + /* NOTE(Kevin): Because some STA may change its BSSID frequently after it + * create the IBSS, so we need to make sure we get the new one. + * For BSS, if the old record was matched, however it won't be able to pass + * the Join Process later. + */ + if (prBssDesc->eBSSType == BSS_TYPE_IBSS) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + prBssDesc->aucBSSID); + continue; + } + } + + if ((prBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) && + (prAdapter->eConnectionState == MEDIA_STATE_CONNECTED)) { + OS_SYSTIME rCurrentTime; + + GET_CURRENT_SYSTIME(&rCurrentTime); + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rUpdateTime, + SEC_TO_SYSTIME(BSS_DESC_TIMEOUT_SEC))) { + DBGLOG(SCAN, TRACE, "Skip old record of BSS Descriptor - BSSID:[%pM]\n\n", + (prBssDesc->aucBSSID)); + continue; + } + } + /* 4 <4B> Check for IBSS AdHoc Mode. */ + /* Skip if one or more BSS Basic Rate are not supported by current AdHocMode */ + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_IBSS) { + /* 4 <4B.1> Check if match the Capability of current IBSS AdHoc Mode. */ + if (ibssCheckCapabilityForAdHocMode(prAdapter, prPrimaryBssDesc) == WLAN_STATUS_FAILURE) { + + DBGLOG(SCAN, TRACE, + "Ignore BSS DESC MAC: %pM, Capability not supported for AdHoc Mode.\n", + prPrimaryBssDesc->aucBSSID); + + continue; + } + /* 4 <4B.2> IBSS Merge Decision Flow for SEARCH STATE. */ + if (prAdapter->fgIsIBSSActive && + UNEQUAL_MAC_ADDR(prBssInfo->aucBSSID, prPrimaryBssDesc->aucBSSID)) { + + if (!fgIsLocalTSFRead) { + NIC_GET_CURRENT_TSF(prAdapter, &rCurrentTsf); + + DBGLOG(SCAN, TRACE, + "\n\nCurrent TSF : %08lx-%08lx\n\n", + rCurrentTsf.u.HighPart, rCurrentTsf.u.LowPart); + } + + if (rCurrentTsf.QuadPart > prPrimaryBssDesc->u8TimeStamp.QuadPart) { + DBGLOG(SCAN, TRACE, + "Ignore BSS DESC MAC: [%pM], Current BSSID: [%pM].\n", + prPrimaryBssDesc->aucBSSID, prBssInfo->aucBSSID); + + DBGLOG(SCAN, TRACE, + "\n\nBSS's TSF : %08lx-%08lx\n\n", + prPrimaryBssDesc->u8TimeStamp.u.HighPart, + prPrimaryBssDesc->u8TimeStamp.u.LowPart); + + prPrimaryBssDesc->fgIsLargerTSF = FALSE; + continue; + } else { + prPrimaryBssDesc->fgIsLargerTSF = TRUE; + } + + } + } + /* 4 <5> Check the Encryption Status. */ + if (rsnPerformPolicySelection(prPrimaryBssDesc)) { + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + + fgIsFindFirst = FALSE; + } + } else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } + + /* For RSN Pre-authentication, update the PMKID canidate list for + same SSID and encrypt status */ + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAdapter->rWifiVar.rAisBssInfo.u4PmkidCandicateCount) + prAdapter->rWifiVar.rAisBssInfo.fgIndicatePMKID = rsnCheckPmkidCandicate(); + } +#endif + + prPrimaryBssDesc = (P_BSS_DESC_T) NULL; + + /* 4 <6> Check current Connection Policy. */ + switch (prConnSettings->eConnectionPolicy) { + case CONNECT_BY_SSID_BEST_RSSI: + /* Choose Hidden SSID to join only if the `fgIsEnableJoin...` is TRUE */ + if (prAdapter->rWifiVar.fgEnableJoinToHiddenSSID && prBssDesc->fgIsHiddenSSID) { + /* NOTE(Kevin): following if () statement means that + * If Target is hidden, then we won't connect when user specify SSID_ANY policy. + */ + if (prConnSettings->ucSSIDLen) { + prPrimaryBssDesc = prBssDesc; + fgIsFindBestRSSI = TRUE; + } + + } else if (EQUAL_SSID(prBssDesc->aucSSID, + prBssDesc->ucSSIDLen, + prConnSettings->aucSSID, prConnSettings->ucSSIDLen)) { + prPrimaryBssDesc = prBssDesc; + fgIsFindBestRSSI = TRUE; + + DBGLOG(SCN, TRACE, "SEARCH: fgIsFindBestRSSI=TRUE, %d, prPrimaryBssDesc=[ %pM ]\n", + prBssDesc->ucRCPI, prPrimaryBssDesc->aucBSSID); + } + break; + + case CONNECT_BY_SSID_ANY: + /* NOTE(Kevin): In this policy, we don't know the desired + * SSID from user, so we should exclude the Hidden SSID from scan list. + * And because we refuse to connect to Hidden SSID node at the beginning, so + * when the JOIN Module deal with a BSS_DESC_T which has fgIsHiddenSSID == TRUE, + * then the Connection Settings must be valid without doubt. + */ + if (!prBssDesc->fgIsHiddenSSID) { + prPrimaryBssDesc = prBssDesc; + fgIsFindFirst = TRUE; + } + break; + + case CONNECT_BY_BSSID: + if (EQUAL_MAC_ADDR(prBssDesc->aucBSSID, prConnSettings->aucBSSID)) + prPrimaryBssDesc = prBssDesc; + break; + + default: + break; + } + + /* Primary Candidate was not found */ + if (prPrimaryBssDesc == NULL) + continue; + /* 4 <7> Check the Encryption Status. */ + if (prPrimaryBssDesc->eBSSType == BSS_TYPE_INFRASTRUCTURE) { +#if CFG_SUPPORT_WAPI + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode) { + DBGLOG(SCN, TRACE, "SEARCH: fgWapiMode == 1\n"); + + if (wapiPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + fgIsFindFirst = TRUE; + } else { + /* Can't pass the Encryption Status Check, get next one */ + DBGLOG(SCN, TRACE, "SEARCH: WAPI cannot pass the Encryption Status Check!\n"); + continue; + } + } else +#endif +#if CFG_RSN_MIGRATION + if (rsnPerformPolicySelection(prAdapter, prPrimaryBssDesc)) { + if (prAisSpecBssInfo->fgCounterMeasure) { + DBGLOG(RSN, INFO, "Skip while at counter measure period!!!\n"); + continue; + } + + if (prPrimaryBssDesc->ucEncLevel > 0) { + fgIsFindBestEncryptionLevel = TRUE; + fgIsFindFirst = FALSE; + } +#if 0 + /* Update PMKID candicate list. */ + if (prAdapter->rWifiVar.rConnSettings.eAuthMode == AUTH_MODE_WPA2) { + rsnUpdatePmkidCandidateList(prPrimaryBssDesc); + if (prAisSpecBssInfo->u4PmkidCandicateCount) { + if (rsnCheckPmkidCandicate()) { + DBGLOG(RSN, WARN, + "Prepare a timer to indicate candidate %pM\n", + (prAisSpecBssInfo->arPmkidCache + [prAisSpecBssInfo->u4PmkidCacheCount]. + rBssidInfo.aucBssid))); + cnmTimerStopTimer(&prAisSpecBssInfo->rPreauthenticationTimer); + cnmTimerStartTimer(&prAisSpecBssInfo->rPreauthenticationTimer, + SEC_TO_MSEC + (WAIT_TIME_IND_PMKID_CANDICATE_SEC)); + } + } + } +#endif + } else { + /* Can't pass the Encryption Status Check, get next one */ + continue; + } +#endif + } else { + /* Todo:: P2P and BOW Policy Selection */ + } + + prPrimaryStaRec = prStaRec; + + /* 4 <8> Compare the Candidate and the Primary Scan Record. */ + if (!prCandidateBssDesc) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + + /* 4 <8.1> Condition - Get the first matched one. */ + if (fgIsFindFirst) + break; + } else { +#if 0 /* TODO(Kevin): For security(TBD) */ + /* 4 <6B> Condition - Choose the one with best Encryption Score. */ + if (fgIsFindBestEncryptionLevel) { + if (prCandidateBssDesc->ucEncLevel < prPrimaryBssDesc->ucEncLevel) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + + /* If reach here, that means they have the same Encryption Score. + */ + + /* 4 <6C> Condition - Give opportunity to the one we didn't connect before. */ + /* For roaming, only compare the candidates other than current associated BSSID. */ + if (!prCandidateBssDesc->fgIsConnected && !prPrimaryBssDesc->fgIsConnected) { + if ((prCandidateStaRec != (P_STA_RECORD_T) NULL) && + (prCandidateStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + + DBGLOG(SCAN, TRACE, + "So far -BSS DESC MAC: %pM has nonzero Status Code = %d\n", + prCandidateBssDesc->aucBSSID, + prCandidateStaRec->u2StatusCode); + + if (prPrimaryStaRec != (P_STA_RECORD_T) NULL) { + if (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL) { + + /* Give opportunity to the one with smaller rLastJoinTime */ + if (TIME_BEFORE(prCandidateStaRec->rLastJoinTime, + prPrimaryStaRec->rLastJoinTime)) { + continue; + } + /* We've connect to CANDIDATE recently, + * let us try PRIMARY now */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY's u2StatusCode = 0 */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } + /* PRIMARY has no StaRec - We didn't connet to PRIMARY before */ + else { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else { + if ((prPrimaryStaRec != (P_STA_RECORD_T) NULL) && + (prPrimaryStaRec->u2StatusCode != STATUS_CODE_SUCCESSFUL)) { + continue; + } + } + } +#endif + + /* 4 <6D> Condition - Visible SSID win Hidden SSID. */ + if (prCandidateBssDesc->fgIsHiddenSSID) { + if (!prPrimaryBssDesc->fgIsHiddenSSID) { + prCandidateBssDesc = prPrimaryBssDesc; /* The non Hidden SSID win. */ + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else { + if (prPrimaryBssDesc->fgIsHiddenSSID) + continue; + } + + /* 4 <6E> Condition - Choose the one with better RCPI(RSSI). */ + if (fgIsFindBestRSSI) { + /* TODO(Kevin): We shouldn't compare the actual value, we should + * allow some acceptable tolerance of some RSSI percentage here. + */ + DBGLOG(SCN, TRACE, + "Candidate [%pM]: RCPI = %d, joinFailCnt=%d, Primary [%pM]: RCPI = %d, joinFailCnt=%d\n", + prCandidateBssDesc->aucBSSID, + prCandidateBssDesc->ucRCPI, prCandidateBssDesc->ucJoinFailureCount, + prPrimaryBssDesc->aucBSSID, + prPrimaryBssDesc->ucRCPI, prPrimaryBssDesc->ucJoinFailureCount); + + ASSERT(!(prCandidateBssDesc->fgIsConnected && prPrimaryBssDesc->fgIsConnected)); + if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) { + /* give a chance to do join if join fail before + * SCN_BSS_DECRASE_JOIN_FAIL_CNT_SEC seconds + */ + if (CHECK_FOR_TIMEOUT(rCurrentTime, prBssDesc->rJoinFailTime, + SEC_TO_SYSTIME(SCN_BSS_JOIN_FAIL_CNT_RESET_SEC))) { + prBssDesc->ucJoinFailureCount = SCN_BSS_JOIN_FAIL_THRESOLD - + SCN_BSS_JOIN_FAIL_RESET_STEP; + DBGLOG(SCN, INFO, + "decrease join fail count for Bss %pM to %u, timeout second %d\n", + prBssDesc->aucBSSID, prBssDesc->ucJoinFailureCount, + SCN_BSS_JOIN_FAIL_CNT_RESET_SEC); + } + } + + /* NOTE: To prevent SWING, + * we do roaming only if target AP has at least 5dBm larger than us. */ + if (prCandidateBssDesc->fgIsConnected) { + if (prCandidateBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP <= + prPrimaryBssDesc->ucRCPI && + prPrimaryBssDesc->ucJoinFailureCount < SCN_BSS_JOIN_FAIL_THRESOLD) { + + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->fgIsConnected) { + if (prCandidateBssDesc->ucRCPI < + (prPrimaryBssDesc->ucRCPI + ROAMING_NO_SWING_RCPI_STEP) || + (prCandidateBssDesc->ucJoinFailureCount >= + SCN_BSS_JOIN_FAIL_THRESOLD)) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } else if (prPrimaryBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD) + continue; + else if (prCandidateBssDesc->ucJoinFailureCount >= SCN_BSS_JOIN_FAIL_THRESOLD || + prCandidateBssDesc->ucRCPI < prPrimaryBssDesc->ucRCPI) { + prCandidateBssDesc = prPrimaryBssDesc; + prCandidateStaRec = prPrimaryStaRec; + continue; + } + } +#if 0 + /* If reach here, that means they have the same Encryption Score, and + * both RSSI value are close too. + */ + /* 4 <6F> Seek the minimum Channel Load for less interference. */ + if (fgIsFindMinChannelLoad) { + /* Do nothing */ + /* TODO(Kevin): Check which one has minimum channel load in its channel */ + } +#endif + } + } + + + if (prCandidateBssDesc != NULL) { + DBGLOG(SCN, INFO, + "SEARCH: Candidate BSS: %pM\n", prCandidateBssDesc->aucBSSID); + } + + return prCandidateBssDesc; + +} /* end of scanSearchBssDescByPolicy() */ + +#if CFG_SUPPORT_AGPS_ASSIST +VOID scanReportScanResultToAgps(P_ADAPTER_T prAdapter) +{ + P_LINK_T prBSSDescList = &prAdapter->rWifiVar.rScanInfo.rBSSDescList; + P_BSS_DESC_T prBssDesc = NULL; + P_AGPS_AP_LIST_T prAgpsApList; + P_AGPS_AP_INFO_T prAgpsInfo; + P_SCAN_INFO_T prScanInfo = &prAdapter->rWifiVar.rScanInfo; + UINT_8 ucIndex = 0; + + prAgpsApList = kalMemAlloc(sizeof(AGPS_AP_LIST_T), VIR_MEM_TYPE); + if (!prAgpsApList) + return; + + prAgpsInfo = &prAgpsApList->arApInfo[0]; + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->rUpdateTime < prScanInfo->rLastScanCompletedTime) + continue; + COPY_MAC_ADDR(prAgpsInfo->aucBSSID, prBssDesc->aucBSSID); + prAgpsInfo->ePhyType = AGPS_PHY_G; + prAgpsInfo->u2Channel = prBssDesc->ucChannelNum; + prAgpsInfo->i2ApRssi = RCPI_TO_dBm(prBssDesc->ucRCPI); + prAgpsInfo++; + ucIndex++; + if (ucIndex == 32) + break; + } + prAgpsApList->ucNum = ucIndex; + GET_CURRENT_SYSTIME(&prScanInfo->rLastScanCompletedTime); + /* DBGLOG(SCN, INFO, ("num of scan list:%d\n", ucIndex)); */ + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_AP_LIST, (PUINT_8) prAgpsApList, sizeof(AGPS_AP_LIST_T)); + kalMemFree(prAgpsApList, VIR_MEM_TYPE, sizeof(AGPS_AP_LIST_T)); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c new file mode 100644 index 0000000000000..fac9f94428dd9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/scan_fsm.c @@ -0,0 +1,2136 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/scan_fsm.c#1 +*/ + +/*! \file "scan_fsm.c" + \brief This file defines the state transition function for SCAN FSM. + + The SCAN FSM is part of SCAN MODULE and responsible for performing basic SCAN + behavior as metioned in IEEE 802.11 2007 11.1.3.1 & 11.1.3.2 . +*/ + +/* +** Log: scan_fsm.c + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 14 2011 yuche.tsai + * [WCXRP00001095] [Volunteer Patch][Driver] Always Scan before enable Hot-Spot. + * Fix bug when unregister P2P network.. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search + * for more than one SSID in a single scanning request + * free mailbox message afte parsing is completed. + * + * 07 18 2011 cp.wu + * [WCXRP00000858] [MT5931][Driver][Firmware] Add support for scan to search + * for more than one SSID in a single scanning request + * add framework in driver domain for supporting new SCAN_REQ_V2 for more than 1 SSID support + * as well as uProbeDelay in NDIS 6.x driver model + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cp.wu + * [WCXRP00000604] [MT6620 Wi-Fi][Driver] Surpress Klockwork Warning + * surpress klock warning with code path rewritten + * + * 03 18 2011 cm.chang + * [WCXRP00000576] [MT6620 Wi-Fi][Driver][FW] Remove P2P compile option in scan req/cancel command + * As CR title + * + * 02 18 2011 yuche.tsai + * [WCXRP00000478] [Volunteer Patch][MT6620][Driver] Probe request frame + * during search phase do not contain P2P wildcard SSID. + * Take P2P wildcard SSID into consideration. + * + * 01 27 2011 yuche.tsai + * [WCXRP00000399] [Volunteer Patch][MT6620/MT5931][Driver] Fix scan side effect after P2P module separate. + * Fix scan channel extension issue when p2p module is not registered. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * add interface for RLM to trigger OBSS-SCAN. + * + * 08 16 2010 yuche.tsai + * NULL + * Fix bug for processing queued scan request. + * + * 08 11 2010 yuche.tsai + * NULL + * Add a function for returning channel. + * + * 08 05 2010 yuche.tsai + * NULL + * Update SCAN FSM for support P2P Device discovery scan. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 07 26 2010 yuche.tsai + * + * Add option of channel extension while cancelling scan request. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 20 2010 cp.wu + * + * pass band information for scan in an efficient way by mapping ENUM_BAND_T into UINT_8.. + * + * 07 19 2010 cp.wu + * + * due to FW/DRV won't be sync. precisely, some strict assertions should be eased. + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * SCN module is now able to handle multiple concurrent scanning requests + * + * 07 16 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * bugfix for SCN migration + * 1) modify QUEUE_CONCATENATE_QUEUES() so it could be used to concatence with an empty queue + * 2) before AIS issues scan request, network(BSS) needs to be activated first + * 3) only invoke COPY_SSID when using specified SSID for scan + * + * 07 15 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * driver no longer generates probe request frames + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * pass band with channel number information as scan parameter + * + * 07 14 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * remove timer in DRV-SCN. + * + * 07 09 2010 cp.wu + * + * 1) separate AIS_FSM state for two kinds of scanning. (OID triggered scan, and scan-for-connection) + * 2) eliminate PRE_BSS_DESC_T, Beacon/PrebResp is now parsed in single pass + * 3) implment DRV-SCN module, currently only accepts single scan request, + * other request will be directly dropped by returning BUSY + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * take use of RLM module for parsing/generating HT IEs for 11n capability + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * when returning to SCAN_IDLE state, send a correct message to source FSM. + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * comment out RLM APIs by CFG_RLM_MIGRATION. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add scan_fsm into building. + * + * 05 14 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine the order of Stop TX Queue and Switch Channel + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Update pause/resume/flush API to new Bitmap API + * + * 05 12 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Add Power Management - Legacy PS-POLL support. + * + * 03 18 2010 kevin.huang + * [BORA00000663][WIFISYS][New Feature] AdHoc Mode Support + * Ignore the PROBE_DELAY state if the value of Probe Delay == 0 + * + * 03 10 2010 kevin.huang + * [BORA00000654][WIFISYS][New Feature] CNM Module - Ch Manager Support + * Add Channel Manager for arbitration of JOIN and SCAN Req + * + * 02 23 2010 kevin.huang + * [BORA00000603][WIFISYS] [New Feature] AAA Module Support + * Add support scan channel 1~14 and update scan result's frequency infou1rwduu`wvpghlqg|n`slk+mpdkb + * + * 01 08 2010 kevin.huang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * Add set RX Filter to receive BCN from different BSSID during SCAN + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Nov 25 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Remove flag of CFG_TEST_MGMT_FSM + * + * Nov 20 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Change parameter of scanSendProbeReqFrames() + * + * Nov 16 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Update scnFsmSteps() + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * Fix typo + * + * Nov 5 2009 mtk01461 + * [BORA00000018] Integrate WIFI part into BORA for the 1st time + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugScanState[SCAN_STATE_NUM] = { + (PUINT_8) DISP_STRING("SCAN_STATE_IDLE"), + (PUINT_8) DISP_STRING("SCAN_STATE_SCANNING"), +}; + +/*lint -restore */ +#endif /* DBG */ + +#define CURRENT_PSCN_VERSION 1 +#define RSSI_MARGIN_DEFAULT 5 +#define MAX_PERIOD 200000 + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmSteps(IN P_ADAPTER_T prAdapter, IN ENUM_SCAN_STATE_T eNextState) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prMsgHdr; + + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + do { + +#if DBG + DBGLOG(SCN, STATE, "TRANSITION: [%s] -> [%s]\n", + apucDebugScanState[prScanInfo->eCurrentState], apucDebugScanState[eNextState]); +#else + DBGLOG(SCN, STATE, "[%d] TRANSITION: [%d] -> [%d]\n", + DBG_SCN_IDX, prScanInfo->eCurrentState, eNextState); +#endif + + /* NOTE(Kevin): This is the only place to change the eCurrentState(except initial) */ + prScanInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; + + switch (prScanInfo->eCurrentState) { + case SCAN_STATE_IDLE: + /* check for pending scanning requests */ + if (!LINK_IS_EMPTY(&(prScanInfo->rPendingMsgList))) { + /* load next message from pending list as scan parameters */ + LINK_REMOVE_HEAD(&(prScanInfo->rPendingMsgList), prMsgHdr, P_MSG_HDR_T); + + if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ) prMsgHdr); + } else { + scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2) prMsgHdr); + } + + /* switch to next state */ + eNextState = SCAN_STATE_SCANNING; + fgIsTransition = TRUE; + + cnmMemFree(prAdapter, prMsgHdr); + } + break; + + case SCAN_STATE_SCANNING: + if (prScanParam->fgIsScanV2 == FALSE) + scnSendScanReq(prAdapter); + else + scnSendScanReqV2(prAdapter); + break; + + default: + ASSERT(0); + break; + + } + } while (fgIsTransition); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqExtCh(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ_EXT_CH rCmdScanReq;*/ + P_CMD_SCAN_REQ_EXT_CH prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_EXT_CH), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) + return; + + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_EXT_CH)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + if (prScanParam->ucSSIDNum == 1) { + COPY_SSID(prCmdScanReq->aucSSID, + prCmdScanReq->ucSSIDLength, + prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); + } + + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_EXT_CH, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + else if (prCmdScanReq->ucSSIDLength > 32) + kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_EXT_CH)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReq(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ rCmdScanReq;*/ + P_CMD_SCAN_REQ prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanParam->ucChannelListNum > 32) { + scnSendScanReqExtCh(prAdapter); + } else { + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) { + DBGLOG(SCN, INFO, "alloc CmdScanReq fail"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + if (prScanParam->ucSSIDNum == 1) { + COPY_SSID(prCmdScanReq->aucSSID, + prCmdScanReq->ucSSIDLength, + prScanParam->aucSpecifiedSSID[0], prScanParam->ucSpecifiedSSIDLen[0]); + } + + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. + * (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif +#if CFG_ENABLE_FAST_SCAN + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_AIS_INDEX) + prCmdScanReq->u2ChannelDwellTime = CFG_FAST_SCAN_DWELL_TIME; +#endif + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + else if (prCmdScanReq->ucSSIDLength > 32) + kalSendAeeWarning("wlan", "wrong ssid length %d", prCmdScanReq->ucSSIDLength); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V2 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqV2ExtCh(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ_V2_EXT_CH rCmdScanReq;*/ + P_CMD_SCAN_REQ_V2_EXT_CH prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_V2_EXT_CH), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) + return; + + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + for (i = 0; i < prScanParam->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], prScanParam->ucSpecifiedSSIDLen[i]); + } + + prCmdScanReq->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_V2_EXT_CH, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_V2_EXT_CH)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Generate CMD_ID_SCAN_REQ_V2 command +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnSendScanReqV2(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + /*CMD_SCAN_REQ_V2 rCmdScanReq;*/ + P_CMD_SCAN_REQ_V2 prCmdScanReq; + UINT_32 i; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanParam->ucChannelListNum > 32) { + scnSendScanReqV2ExtCh(prAdapter); + } else { + prCmdScanReq = kalMemAlloc(sizeof(CMD_SCAN_REQ_V2), VIR_MEM_TYPE); + if (prCmdScanReq == NULL) { + DBGLOG(SCN, INFO, "alloc CmdScanReq v2 fail"); + return; + } + /* send command packet for scan */ + kalMemZero(prCmdScanReq, sizeof(CMD_SCAN_REQ_V2)); + + prCmdScanReq->ucSeqNum = prScanParam->ucSeqNum; + prCmdScanReq->ucNetworkType = (UINT_8) prScanParam->eNetTypeIndex; + prCmdScanReq->ucScanType = (UINT_8) prScanParam->eScanType; + prCmdScanReq->ucSSIDType = prScanParam->ucSSIDType; + + for (i = 0; i < prScanParam->ucSSIDNum; i++) { + COPY_SSID(prCmdScanReq->arSSID[i].aucSsid, + prCmdScanReq->arSSID[i].u4SsidLen, + prScanParam->aucSpecifiedSSID[i], prScanParam->ucSpecifiedSSIDLen[i]); + } + + prCmdScanReq->u2ProbeDelayTime = (UINT_8) prScanParam->u2ProbeDelayTime; + prCmdScanReq->ucChannelType = (UINT_8) prScanParam->eScanChannel; + + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + /* P2P would use: + * 1. Specified Listen Channel of passive scan for LISTEN state. + * 2. Specified Listen Channel of Target Device of active scan for SEARCH state. + * (Target != NULL) + */ + prCmdScanReq->ucChannelListNum = prScanParam->ucChannelListNum; + + for (i = 0; i < prCmdScanReq->ucChannelListNum; i++) { + prCmdScanReq->arChannelList[i].ucBand = (UINT_8) prScanParam->arChnlInfoList[i].eBand; + + prCmdScanReq->arChannelList[i].ucChannelNum = + (UINT_8) prScanParam->arChnlInfoList[i].ucChannelNum; + } + } +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prCmdScanReq->u2ChannelDwellTime = prScanParam->u2PassiveListenInterval; +#endif + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdScanReq->u2IELen = prScanParam->u2IELen; + else + prCmdScanReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdScanReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdScanReq->u2IELen); + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_REQ_V2, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + OFFSET_OF(CMD_SCAN_REQ_V2, aucIE) + prCmdScanReq->u2IELen, + (PUINT_8) prCmdScanReq, NULL, 0); + /* sanity check for some scan parameters */ + if (prCmdScanReq->ucScanType >= SCAN_TYPE_NUM) + kalSendAeeWarning("wlan", "wrong scan type %d", prCmdScanReq->ucScanType); + else if (prCmdScanReq->ucChannelType >= SCAN_CHANNEL_NUM) + kalSendAeeWarning("wlan", "wrong channel type %d", prCmdScanReq->ucChannelType); + else if (prCmdScanReq->ucChannelType != SCAN_CHANNEL_SPECIFIED && + prCmdScanReq->ucChannelListNum != 0) + kalSendAeeWarning("wlan", + "channel list is not NULL but channel type is not specified"); + else if (prCmdScanReq->ucNetworkType >= NETWORK_TYPE_INDEX_NUM) + kalSendAeeWarning("wlan", "wrong network type %d", prCmdScanReq->ucNetworkType); + else if (prCmdScanReq->ucSSIDType >= BIT(4)) /* ssid type is wrong */ + kalSendAeeWarning("wlan", "wrong ssid type %d", prCmdScanReq->ucSSIDType); + + kalMemFree(prCmdScanReq, VIR_MEM_TYPE, sizeof(CMD_SCAN_REQ_V2)); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgStart(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + + ASSERT(prMsgHdr); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState == SCAN_STATE_IDLE) { + if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + scnFsmHandleScanMsg(prAdapter, (P_MSG_SCN_SCAN_REQ) prMsgHdr); + } else if (prMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + scnFsmHandleScanMsgV2(prAdapter, (P_MSG_SCN_SCAN_REQ_V2) prMsgHdr); + } else { + /* should not deliver to this function */ + ASSERT(0); + } + + cnmMemFree(prAdapter, prMsgHdr); + scnFsmSteps(prAdapter, SCAN_STATE_SCANNING); + } else { + LINK_INSERT_TAIL(&prScanInfo->rPendingMsgList, &prMsgHdr->rLinkEntry); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmMsgAbort(IN P_ADAPTER_T prAdapter, IN P_MSG_HDR_T prMsgHdr) +{ + P_MSG_SCN_SCAN_CANCEL prScanCancel; + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + CMD_SCAN_CANCEL rCmdScanCancel; + + ASSERT(prMsgHdr); + + prScanCancel = (P_MSG_SCN_SCAN_CANCEL) prMsgHdr; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + if (prScanInfo->eCurrentState != SCAN_STATE_IDLE) { + if (prScanCancel->ucSeqNum == prScanParam->ucSeqNum && + prScanCancel->ucNetTypeIndex == (UINT_8) prScanParam->eNetTypeIndex) { + /* send cancel message to firmware domain */ + rCmdScanCancel.ucSeqNum = prScanParam->ucSeqNum; + +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + rCmdScanCancel.ucIsExtChannel = (UINT_8) prScanCancel->fgIsChannelExt; + else + rCmdScanCancel.ucIsExtChannel = (UINT_8) FALSE; +#endif + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SCAN_CANCEL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SCAN_CANCEL), (PUINT_8) &rCmdScanCancel, NULL, 0); + + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, + (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_CANCELLED); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + scnFsmRemovePendingMsg(prAdapter, prScanCancel->ucSeqNum, prScanCancel->ucNetTypeIndex); + } + } + + cnmMemFree(prAdapter, prMsgHdr); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing (Legacy) +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsg(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + if (prScanParam->ucSSIDType & (SCAN_REQ_SSID_SPECIFIED | SCAN_REQ_SSID_P2P_WILDCARD)) { + prScanParam->ucSSIDNum = 1; + + COPY_SSID(prScanParam->aucSpecifiedSSID[0], + prScanParam->ucSpecifiedSSIDLen[0], prScanReqMsg->aucSSID, prScanReqMsg->ucSSIDLength); + + /* reset SSID length to zero for rest array entries */ + for (i = 1; i < SCN_SSID_MAX_NUM; i++) + prScanParam->ucSpecifiedSSIDLen[i] = 0; + } else { + prScanParam->ucSSIDNum = 0; + + for (i = 0; i < SCN_SSID_MAX_NUM; i++) + prScanParam->ucSpecifiedSSIDLen[i] = 0; + } + + prScanParam->u2ProbeDelayTime = 0; + prScanParam->eScanChannel = prScanReqMsg->eScanChannel; + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) + prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; + else + prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; + + kalMemCopy(prScanParam->arChnlInfoList, + prScanReqMsg->arChnlInfoList, sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); + } + + if (prScanReqMsg->u2IELen <= MAX_IE_LENGTH) + prScanParam->u2IELen = prScanReqMsg->u2IELen; + else + prScanParam->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; +#endif + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Scan Message Parsing - V2 with multiple SSID support +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmHandleScanMsgV2(IN P_ADAPTER_T prAdapter, IN P_MSG_SCN_SCAN_REQ_V2 prScanReqMsg) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + UINT_32 i; + + ASSERT(prAdapter); + ASSERT(prScanReqMsg); + ASSERT(prScanReqMsg->ucSSIDNum <= SCN_SSID_MAX_NUM); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + prScanParam->eScanType = prScanReqMsg->eScanType; + prScanParam->eNetTypeIndex = (ENUM_NETWORK_TYPE_INDEX_T) prScanReqMsg->ucNetTypeIndex; + prScanParam->ucSSIDType = prScanReqMsg->ucSSIDType; + prScanParam->ucSSIDNum = prScanReqMsg->ucSSIDNum; + + for (i = 0; i < prScanReqMsg->ucSSIDNum; i++) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], + prScanReqMsg->prSsid[i].aucSsid, (UINT_8) prScanReqMsg->prSsid[i].u4SsidLen); + } + + prScanParam->u2ProbeDelayTime = prScanReqMsg->u2ProbeDelay; + prScanParam->eScanChannel = prScanReqMsg->eScanChannel; + if (prScanParam->eScanChannel == SCAN_CHANNEL_SPECIFIED) { + if (prScanReqMsg->ucChannelListNum <= MAXIMUM_OPERATION_CHANNEL_LIST) + prScanParam->ucChannelListNum = prScanReqMsg->ucChannelListNum; + else + prScanParam->ucChannelListNum = MAXIMUM_OPERATION_CHANNEL_LIST; + + kalMemCopy(prScanParam->arChnlInfoList, + prScanReqMsg->arChnlInfoList, sizeof(RF_CHANNEL_INFO_T) * prScanParam->ucChannelListNum); + } + + if (prScanReqMsg->u2IELen <= MAX_IE_LENGTH) + prScanParam->u2IELen = prScanReqMsg->u2IELen; + else + prScanParam->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prScanParam->aucIE, prScanReqMsg->aucIE, prScanParam->u2IELen); +#if CFG_ENABLE_WIFI_DIRECT + if (prScanParam->eNetTypeIndex == NETWORK_TYPE_P2P_INDEX) + prScanParam->u2PassiveListenInterval = prScanReqMsg->u2ChannelDwellTime; +#endif + prScanParam->ucSeqNum = prScanReqMsg->ucSeqNum; + + if (prScanReqMsg->rMsgHdr.eMsgId == MID_RLM_SCN_SCAN_REQ) + prScanParam->fgIsObssScan = TRUE; + else + prScanParam->fgIsObssScan = FALSE; + + prScanParam->fgIsScanV2 = TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Remove pending scan request +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnFsmRemovePendingMsg(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_HDR_T prPendingMsgHdr, prPendingMsgHdrNext, prRemoveMsgHdr = NULL; + P_LINK_ENTRY_T prRemoveLinkEntry = NULL; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* traverse through rPendingMsgList for removal */ + LINK_FOR_EACH_ENTRY_SAFE(prPendingMsgHdr, + prPendingMsgHdrNext, &(prScanInfo->rPendingMsgList), rLinkEntry, MSG_HDR_T) { + if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ) { + P_MSG_SCN_SCAN_REQ prScanReqMsg = (P_MSG_SCN_SCAN_REQ) prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsg->ucSeqNum && ucNetTypeIndex == prScanReqMsg->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsg->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } else if (prPendingMsgHdr->eMsgId == MID_AIS_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_BOW_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_P2P_SCN_SCAN_REQ_V2 + || prPendingMsgHdr->eMsgId == MID_RLM_SCN_SCAN_REQ_V2) { + P_MSG_SCN_SCAN_REQ_V2 prScanReqMsgV2 = (P_MSG_SCN_SCAN_REQ_V2) prPendingMsgHdr; + + if (ucSeqNum == prScanReqMsgV2->ucSeqNum && ucNetTypeIndex == prScanReqMsgV2->ucNetTypeIndex) { + prRemoveLinkEntry = &(prScanReqMsgV2->rMsgHdr.rLinkEntry); + prRemoveMsgHdr = prPendingMsgHdr; + } + } + + if (prRemoveLinkEntry) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, ucSeqNum, ucNetTypeIndex, SCAN_STATUS_CANCELLED); + + /* remove from pending list */ + LINK_REMOVE_KNOWN_ENTRY(&(prScanInfo->rPendingMsgList), prRemoveLinkEntry); + cnmMemFree(prAdapter, prRemoveMsgHdr); + + break; + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventScanDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_SCAN_DONE prScanDone) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + /* buffer empty channel information */ + if (prScanParam->eScanChannel == SCAN_CHANNEL_FULL || prScanParam->eScanChannel == SCAN_CHANNEL_2G4) { + if (prScanDone->ucSparseChannelValid) { + prScanInfo->fgIsSparseChannelValid = TRUE; + prScanInfo->rSparseChannel.eBand = (ENUM_BAND_T) prScanDone->rSparseChannel.ucBand; + prScanInfo->rSparseChannel.ucChannelNum = prScanDone->rSparseChannel.ucChannelNum; + } else { + prScanInfo->fgIsSparseChannelValid = FALSE; + } + } + + if (prScanInfo->eCurrentState == SCAN_STATE_SCANNING && prScanDone->ucSeqNum == prScanParam->ucSeqNum) { + /* generate scan-done event for caller */ + scnFsmGenerateScanDoneMsg(prAdapter, + prScanParam->ucSeqNum, (UINT_8) prScanParam->eNetTypeIndex, SCAN_STATUS_DONE); + + /* switch to next pending scan */ + scnFsmSteps(prAdapter, SCAN_STATE_IDLE); + } else { + DBGLOG(SCN, WARN, "Unexpected SCAN-DONE event: SeqNum = %d, Current State = %d\n", + prScanDone->ucSeqNum, prScanInfo->eCurrentState); + } + +} /* end of scnEventScanDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +scnFsmGenerateScanDoneMsg(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSeqNum, IN UINT_8 ucNetTypeIndex, IN ENUM_SCAN_STATUS eScanStatus) +{ + P_SCAN_INFO_T prScanInfo; + P_SCAN_PARAM_T prScanParam; + P_MSG_SCN_SCAN_DONE prScanDoneMsg; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prScanParam = &prScanInfo->rScanParam; + + DBGLOG(SCN, INFO, "Rcv Scan Done, NetIdx %d, Obss %d, Status %d, Seq %d\n", + ucNetTypeIndex, prScanParam->fgIsObssScan, eScanStatus, ucSeqNum); + prScanDoneMsg = (P_MSG_SCN_SCAN_DONE) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_SCN_SCAN_DONE)); + if (!prScanDoneMsg) { + ASSERT(0); /* Can't indicate SCAN FSM Complete */ + return; + } + + if (prScanParam->fgIsObssScan == TRUE) { + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_RLM_SCAN_DONE; + } else { + switch ((ENUM_NETWORK_TYPE_INDEX_T) ucNetTypeIndex) { + case NETWORK_TYPE_AIS_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_AIS_SCAN_DONE; + break; + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_P2P_SCAN_DONE; + break; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW_INDEX: + prScanDoneMsg->rMsgHdr.eMsgId = MID_SCN_BOW_SCAN_DONE; + break; +#endif + + default: + ASSERT(0); + break; + } + } + + prScanDoneMsg->ucSeqNum = ucSeqNum; + prScanDoneMsg->ucNetTypeIndex = ucNetTypeIndex; + prScanDoneMsg->eScanStatus = eScanStatus; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prScanDoneMsg, MSG_SEND_METHOD_BUF); + +} /* end of scnFsmGenerateScanDoneMsg() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Query for most sparse channel +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnQuerySparseChannel(IN P_ADAPTER_T prAdapter, P_ENUM_BAND_T prSparseBand, PUINT_8 pucSparseChannel) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prScanInfo->fgIsSparseChannelValid == TRUE) { + if (prSparseBand) + *prSparseBand = prScanInfo->rSparseChannel.eBand; + + if (pucSparseChannel) + *pucSparseChannel = prScanInfo->rSparseChannel.ucChannelNum; + + return TRUE; + } else { + return FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Event handler for NLO done event +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID scnEventNloDone(IN P_ADAPTER_T prAdapter, IN P_EVENT_NLO_DONE_T prNloDone) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + if (prScanInfo->fgNloScanning == TRUE) { + DBGLOG(SCN, INFO, "scnEventNloDone Current State = %d\n", prScanInfo->eCurrentState); + + kalSchedScanResults(prAdapter->prGlueInfo); + + if (prNloParam->fgStopAfterIndication == TRUE) + prScanInfo->fgNloScanning = FALSE; + + kalMemZero(&prNloParam->aprPendingBssDescToInd[0], + CFG_SCAN_SSID_MATCH_MAX_NUM * sizeof(P_BSS_DESC_T)); + } else { + DBGLOG(SCN, INFO, "Unexpected NLO-DONE event\n"); + } + +} + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for starting scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +scnFsmSchedScanRequest(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucSsidNum, + IN P_PARAM_SSID_T prSsid, IN UINT_32 u4IeLength, IN PUINT_8 pucIe, IN UINT_16 u2Interval) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + P_CMD_NLO_REQ prCmdNloReq; + UINT_32 i, j; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + if (prScanInfo->fgNloScanning) { + DBGLOG(SCN, INFO, "prScanInfo->fgNloScanning == TRUE already scanning\n"); + return TRUE; + } + + prScanInfo->fgNloScanning = TRUE; + + /* 1. load parameters */ + prScanParam->ucSeqNum++; + /* prScanParam->ucBssIndex = prAdapter->prAisBssInfo->ucBssIndex; */ + + prNloParam->fgStopAfterIndication = TRUE; + prNloParam->ucFastScanIteration = 0; + prNloParam->u2FastScanPeriod = u2Interval; + prNloParam->u2SlowScanPeriod = u2Interval; + + if (prScanParam->ucSSIDNum > CFG_SCAN_SSID_MAX_NUM) + prScanParam->ucSSIDNum = CFG_SCAN_SSID_MAX_NUM; + else + prScanParam->ucSSIDNum = ucSsidNum; + + if (prNloParam->ucMatchSSIDNum > CFG_SCAN_SSID_MATCH_MAX_NUM) + prNloParam->ucMatchSSIDNum = CFG_SCAN_SSID_MATCH_MAX_NUM; + else + prNloParam->ucMatchSSIDNum = ucSsidNum; + + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { + if (i < CFG_SCAN_SSID_MAX_NUM) { + COPY_SSID(prScanParam->aucSpecifiedSSID[i], + prScanParam->ucSpecifiedSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); + } + + COPY_SSID(prNloParam->aucMatchSSID[i], + prNloParam->ucMatchSSIDLen[i], prSsid[i].aucSsid, (UINT_8) prSsid[i].u4SsidLen); + + prNloParam->aucCipherAlgo[i] = 0; + prNloParam->au2AuthAlgo[i] = 0; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prNloParam->aucChannelHint[i][j] = 0; + } + + /* 2. prepare command for sending */ + prCmdNloReq = (P_CMD_NLO_REQ) cnmMemAlloc(prAdapter, RAM_TYPE_BUF, sizeof(CMD_NLO_REQ) + prScanParam->u2IELen); + + if (!prCmdNloReq) { + ASSERT(0); /* Can't initiate NLO operation */ + return FALSE; + } + + /* 3. send command packet for NLO operation */ + kalMemZero(prCmdNloReq, sizeof(CMD_NLO_REQ)); + + prCmdNloReq->ucSeqNum = prScanParam->ucSeqNum; + /* prCmdNloReq->ucBssIndex = prScanParam->ucBssIndex; */ + + prCmdNloReq->ucNetworkType = prScanParam->eNetTypeIndex; + prCmdNloReq->ucScanType = (UINT_8) prScanParam->eScanType; + + prCmdNloReq->fgStopAfterIndication = prNloParam->fgStopAfterIndication; + prCmdNloReq->ucFastScanIteration = prNloParam->ucFastScanIteration; + prCmdNloReq->u2FastScanPeriod = prNloParam->u2FastScanPeriod; + prCmdNloReq->u2SlowScanPeriod = prNloParam->u2SlowScanPeriod; + prCmdNloReq->ucEntryNum = prNloParam->ucMatchSSIDNum; + for (i = 0; i < prNloParam->ucMatchSSIDNum; i++) { + COPY_SSID(prCmdNloReq->arNetworkList[i].aucSSID, + prCmdNloReq->arNetworkList[i].ucSSIDLength, + prNloParam->aucMatchSSID[i], prNloParam->ucMatchSSIDLen[i]); + + prCmdNloReq->arNetworkList[i].ucCipherAlgo = prNloParam->aucCipherAlgo[i]; + prCmdNloReq->arNetworkList[i].u2AuthAlgo = prNloParam->au2AuthAlgo[i]; + + for (j = 0; j < SCN_NLO_NETWORK_CHANNEL_NUM; j++) + prCmdNloReq->arNetworkList[i].ucNumChannelHint[j] = prNloParam->aucChannelHint[i][j]; + } + + if (prScanParam->u2IELen <= MAX_IE_LENGTH) + prCmdNloReq->u2IELen = prScanParam->u2IELen; + else + prCmdNloReq->u2IELen = MAX_IE_LENGTH; + + if (prScanParam->u2IELen) + kalMemCopy(prCmdNloReq->aucIE, prScanParam->aucIE, sizeof(UINT_8) * prCmdNloReq->u2IELen); +#if !CFG_SUPPORT_GSCN + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NLO_REQ, + TRUE, + FALSE, + TRUE, + nicCmdEventSetCommon, + nicOidCmdTimeoutCommon, + sizeof(CMD_NLO_REQ) + prCmdNloReq->u2IELen, (PUINT_8) prCmdNloReq, NULL, 0); + +#else + scnPSCNFsm(prAdapter, PSCN_RESET, prCmdNloReq, NULL, NULL, NULL, FALSE, FALSE, FALSE, FALSE); +#endif + cnmMemFree(prAdapter, (PVOID) prCmdNloReq); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for stopping scheduled scan +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmSchedScanStopRequest(IN P_ADAPTER_T prAdapter) +{ + P_SCAN_INFO_T prScanInfo; + P_NLO_PARAM_T prNloParam; + P_SCAN_PARAM_T prScanParam; + CMD_NLO_CANCEL rCmdNloCancel; + + ASSERT(prAdapter); + + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prNloParam = &prScanInfo->rNloParam; + prScanParam = &prNloParam->rScanParam; + + /* send cancel message to firmware domain */ + rCmdNloCancel.ucSeqNum = prScanParam->ucSeqNum; + +#if !CFG_SUPPORT_GSCN + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_NLO_CANCEL, + TRUE, + FALSE, + TRUE, + nicCmdEventSetStopSchedScan, + nicOidCmdTimeoutCommon, sizeof(CMD_NLO_CANCEL), (PUINT_8)(&rCmdNloCancel), NULL, 0); +#else + + scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, NULL, TRUE, FALSE, FALSE, FALSE); +#endif + + prScanInfo->fgNloScanning = FALSE; + + return TRUE; +} + +#if CFG_SUPPORT_GSCN + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set PSCN action +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNAction(IN P_ADAPTER_T prAdapter, IN UINT_8 ucPscanAct) +{ + CMD_SET_PSCAN_ENABLE rCmdPscnAction; + P_SCAN_INFO_T prScanInfo; + + DBGLOG(SCN, TRACE, "scnFsmPSCNAction Act = %d\n", ucPscanAct); + + rCmdPscnAction.ucPscanAct = ucPscanAct; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (ucPscanAct == DISABLE) + prScanInfo->fgPscnOnnning = FALSE; + if (ucPscanAct == ENABLE) + prScanInfo->fgPscnOnnning = TRUE; + + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ENABLE, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SET_PSCAN_ENABLE), (PUINT_8) &rCmdPscnAction, NULL, 0); + + DBGLOG(SCN, INFO, "scnFsmPSCNAction Act = %d is Set to FW\n", ucPscanAct); + return TRUE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set PSCN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetParam(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + UINT_8 i, j; + + i = 0; + j = 0; + + ASSERT(prAdapter); + /*prCmdPscnParam->u4BasePeriod = prCmdPscnParam->u4BasePeriod;*/ +#if 0 + DBGLOG(SCN, TRACE, + "rCmdPscnParam: Period[%u],NumCache[%u],Threshold[%u],NumBkts[%u],fgGSCN[%d] fgNLO[%d] fgBatch[%d]\n", + prCmdPscnParam->rCmdGscnReq.u4BasePeriod, prCmdPscnParam->rCmdGscnReq.ucNumScnToCache, + prCmdPscnParam->rCmdGscnReq.u4BufferThreshold, prCmdPscnParam->rCmdGscnReq.u4NumBuckets, + prCmdPscnParam->fgGScnEnable, prCmdPscnParam->fgNLOScnEnable, prCmdPscnParam->fgBatchScnEnable)); + + for (i = 0; i < prCmdPscnParam->rCmdGscnReq.u4NumBuckets; i++) { + DBGLOG(SCN, TRACE, "rCmdPscnParam.rCmdGscnParam.arChannelBucket[%d] has channel: ", i); + DBGLOG(SCN, TRACE, + "band[%u], Index[%u] NumChannels[%u], ucBktFreqMultiple[%u] Flag[%u]\n", + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].eBand, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].u2BucketIndex, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucBucketFreqMultiple, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucReportFlag)); + for (j = 0; j < prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels; j++) + DBGLOG(SCN, TRACE, + " %d, ", prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].arChannelList[j].ucChannel); + DBGLOG(SCN, TRACE, "\n"); + } +#endif + + if (1 /*prScanInfo->fgPscnOnnning == FALSE */) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCAN_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SET_PSCAN_PARAM), (PUINT_8) prCmdPscnParam, NULL, 0); + + DBGLOG(SCN, TRACE, "CMD_ID_SET_PSCAN_PARAM is set to FW !!!!!!!!!!\n"); + return TRUE; + } + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set hotlist +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetHotlist(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_HOTLIST_BSSID prCmdPscnAddHotlist) +{ + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + memcpy(&rCmdPscnAddHotlist.aucMacAddr, &(prCmdPscnAddHotlist->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + /* rCmdPscnAddHotlist.aucMacAddr = prCmdPscnAddHotlist->aucMacAddr; */ + rCmdPscnAddHotlist.ucFlags = prCmdPscnAddHotlist->ucFlags; + + if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ADD_HOTLIST_BSSID, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_PSCAN_ADD_HOTLIST_BSSID), (PUINT_8) &rCmdPscnAddHotlist, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_ADD_SW_BSSID +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNAddSWCBssId(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_ADD_SWC_BSSID prCmdPscnAddSWCBssId) +{ + CMD_SET_PSCAN_ADD_SWC_BSSID rCmdPscnAddSWCBssId; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + memcpy(&rCmdPscnAddSWCBssId.aucMacAddr, &(prCmdPscnAddSWCBssId->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + /* rCmdPscnAddSWCBssId.aucMacAddr = prCmdPscnAddSWCBssId->aucMacAddr; */ + rCmdPscnAddSWCBssId.i4RssiHighThreshold = prCmdPscnAddSWCBssId->i4RssiHighThreshold; + rCmdPscnAddSWCBssId.i4RssiLowThreshold = prCmdPscnAddSWCBssId->i4RssiLowThreshold; + + if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_ADD_SW_BSSID, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_SET_PSCAN_ADD_SWC_BSSID), (PUINT_8) &rCmdPscnAddSWCBssId, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmPSCNSetMacAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_SET_PSCAN_MAC_ADDR prCmdPscnSetMacAddr) +{ + CMD_SET_PSCAN_MAC_ADDR rCmdPscnSetMacAddr; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + /* rCmdPscnSetMacAddr.aucMacAddr = prCmdPscnSetMacAddr->aucMacAddr; */ + memcpy(&rCmdPscnSetMacAddr.aucMacAddr, &(prCmdPscnSetMacAddr->aucMacAddr), sizeof(MAC_ADDR_LEN)); + + rCmdPscnSetMacAddr.ucFlags = prCmdPscnSetMacAddr->ucFlags; + rCmdPscnSetMacAddr.ucVersion = prCmdPscnSetMacAddr->ucVersion; + + if (1 /* (prScanInfo->fgPscnOnnning == TRUE */) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PSCN_MAC_ADDR, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_SET_PSCAN_MAC_ADDR), (PUINT_8) &rCmdPscnSetMacAddr, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN no need to add the hotlist ??? */ + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set GSCN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnSetGSCNParam(IN P_ADAPTER_T prAdapter, IN P_PARAM_WIFI_GSCAN_CMD_PARAMS prCmdGscnParam) +{ + /*CMD_GSCN_REQ_T rCmdGscnParam;*/ + P_CMD_GSCN_REQ_T rCmdGscnParamp; + P_SCAN_INFO_T prScanInfo; + UINT_8 ucChannelBuckIndex; + UINT_8 i; + + ASSERT(prAdapter); + rCmdGscnParamp = kalMemAlloc(sizeof(CMD_GSCN_REQ_T), VIR_MEM_TYPE); + if (rCmdGscnParamp == NULL) { + DBGLOG(SCN, INFO, "alloc CmdGscnParam fail\n"); + return TRUE; + } + kalMemZero(rCmdGscnParamp, sizeof(CMD_GSCN_REQ_T)); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + rCmdGscnParamp->u4NumBuckets = prCmdGscnParam->num_buckets; + rCmdGscnParamp->u4BasePeriod = prCmdGscnParam->base_period; + DBGLOG(SCN, INFO, + "u4BasePeriod[%d], u4NumBuckets[%d]\n", rCmdGscnParamp->u4BasePeriod, rCmdGscnParamp->u4NumBuckets); + for (ucChannelBuckIndex = 0; ucChannelBuckIndex < prCmdGscnParam->num_buckets; ucChannelBuckIndex++) { + DBGLOG(SCN, TRACE, "assign channels to bucket[%d]\n", ucChannelBuckIndex); + for (i = 0; i < prCmdGscnParam->buckets[ucChannelBuckIndex].num_channels; i++) { + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucChannel = + (UINT_8) nicFreq2ChannelNum(prCmdGscnParam->buckets[ucChannelBuckIndex]. + channels[i].channel * 1000); + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucPassive = + (UINT_8) prCmdGscnParam->buckets[ucChannelBuckIndex].channels[i].passive; + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].u4DwellTimeMs = + (UINT_8) prCmdGscnParam->buckets[ucChannelBuckIndex].channels[i].dwellTimeMs; + + DBGLOG(SCN, TRACE, "[ucChannel %d, ucPassive %d, u4DwellTimeMs %d\n", + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucChannel, + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].ucPassive, + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].arChannelList[i].u4DwellTimeMs); + + } + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].u2BucketIndex = + (UINT_16) prCmdGscnParam->buckets[ucChannelBuckIndex].bucket; + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].eBand = + prCmdGscnParam->buckets[ucChannelBuckIndex].band; + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucBucketFreqMultiple = + (prCmdGscnParam->buckets[ucChannelBuckIndex].period / prCmdGscnParam->base_period); + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucNumChannels = + prCmdGscnParam->buckets[ucChannelBuckIndex].num_channels; + rCmdGscnParamp->arChannelBucket[ucChannelBuckIndex].ucReportFlag = + prCmdGscnParam->buckets[ucChannelBuckIndex].report_events; + + /* printk("\n"); */ + } + + DBGLOG(SCN, INFO, "scnSetGSCNParam ---> scnPSCNFsm PSCN_RESET\n"); + + scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, rCmdGscnParamp, NULL, FALSE, FALSE, FALSE, FALSE); + kalMemFree(rCmdGscnParamp, VIR_MEM_TYPE, sizeof(CMD_GSCN_REQ_T)); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine PNO Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +scnSubCombineNLOtoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prNewCmdNloReq, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prNewCmdNloReq) { + prCmdPscnParam->fgNLOScnEnable = TRUE; + memcpy(&prCmdPscnParam->rCmdNloReq, prNewCmdNloReq, sizeof(CMD_NLO_REQ)); + } else if (prScanInfo->prPscnParam->fgNLOScnEnable) { + memcpy(&prCmdPscnParam->rCmdNloReq, &prScanInfo->prPscnParam->rCurrentCmdNloReq, sizeof(CMD_NLO_REQ)); + } else + prCmdPscnParam->fgNLOScnEnable = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine Batcht Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +scnSubCombineBatchSCNtoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_BATCH_REQ_T prNewCmdBatchReq, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + if (prNewCmdBatchReq) { + prCmdPscnParam->fgBatchScnEnable = TRUE; + memcpy(&prCmdPscnParam->rCmdBatchReq, prNewCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); + } else if (prScanInfo->prPscnParam->fgBatchScnEnable) { + memcpy(&prCmdPscnParam->rCmdBatchReq, &prScanInfo->prPscnParam->rCurrentCmdBatchReq, + sizeof(CMD_BATCH_REQ_T)); + } else + prCmdPscnParam->fgBatchScnEnable = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +scnSubCombineGSCNtoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + P_SCAN_INFO_T prScanInfo; + UINT_32 ucPeriodMin = MAX_PERIOD; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prCmdPscnParam->fgGScnEnable = FALSE; + + DBGLOG(SCN, TRACE, "scnSubCombineGSCNtoPSCN fgGScnParamSet %d fgGScnConfigSet %d\n", + prScanInfo->fgGScnParamSet, prScanInfo->fgGScnConfigSet); + + if (prNewCmdGscnReq) { + DBGLOG(SCN, INFO, "setup prNewCmdGscnReq\n"); + prScanInfo->fgGScnParamSet = TRUE; + memcpy(&prCmdPscnParam->rCmdGscnReq, prNewCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + if (ucPeriodMin > prNewCmdGscnReq->u4BasePeriod) + prCmdPscnParam->u4BasePeriod = prNewCmdGscnReq->u4BasePeriod; + } else if (prScanInfo->fgGScnParamSet) { + DBGLOG(SCN, INFO, "no new prNewCmdGscnReq but there is a old one\n"); + memcpy(&prCmdPscnParam->rCmdGscnReq, &prScanInfo->prPscnParam->rCurrentCmdGscnReq, + sizeof(CMD_GSCN_REQ_T)); + prCmdPscnParam->u4BasePeriod = prScanInfo->prPscnParam->u4BasePeriod; + } else + prScanInfo->fgGScnParamSet = FALSE; + + if (prNewCmdGscnConfig) { + DBGLOG(SCN, INFO, "set up prNewCmdGscnConfig\n"); + memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + prScanInfo->fgGScnConfigSet = TRUE; + prCmdPscnParam->rCmdGscnReq.u4BufferThreshold = prNewCmdGscnConfig->u4BufferThreshold; + prCmdPscnParam->rCmdGscnReq.ucNumScnToCache = (UINT_8) prNewCmdGscnConfig->u4NumScnToCache; + } else if (prScanInfo->fgGScnConfigSet) { + DBGLOG(SCN, INFO, "no new prNewCmdGscnConfig but there is a old one\n"); + memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + prCmdPscnParam->rCmdGscnReq.u4BufferThreshold = + prScanInfo->prPscnParam->rCurrentCmdGscnReq.u4BufferThreshold; + prCmdPscnParam->rCmdGscnReq.ucNumScnToCache = + (UINT_8) prScanInfo->prPscnParam->rCurrentCmdGscnReq.ucNumScnToCache; + } else + prScanInfo->fgGScnConfigSet = FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +VOID +scnRemoveFromPSCN(IN P_ADAPTER_T prAdapter, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, + IN BOOLEAN fgRemoveGSCNfromPSCN, IN P_CMD_SET_PSCAN_PARAM prCmdPscnParam) +{ + P_SCAN_INFO_T prScanInfo; + UINT_8 ucPscanAct = DISABLE; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + { + DBGLOG(SCN, INFO, "remove NLO or Batch or GSCN from PSCN--->NLO=%d, BSN=%d, GSN=%d\n", + fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); + + if (fgRemoveNLOfromPSCN) { + memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + prCmdPscnParam->fgNLOScnEnable = FALSE; + kalMemZero(&prCmdPscnParam->rCmdNloReq, sizeof(CMD_NLO_REQ)); + kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdNloReq, sizeof(CMD_NLO_REQ)); + } + if (fgRemoveBatchSCNfromPSCN) { + memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + prCmdPscnParam->fgBatchScnEnable = FALSE; + kalMemZero(&prCmdPscnParam->rCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); + kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdBatchReq, sizeof(CMD_BATCH_REQ_T)); + } + if (fgRemoveGSCNfromPSCN) { + memcpy(prCmdPscnParam, prScanInfo->prPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + prCmdPscnParam->fgGScnEnable = FALSE; + prScanInfo->fgGScnParamSet = FALSE; + kalMemZero(&prCmdPscnParam->rCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + kalMemZero(&prScanInfo->prPscnParam->rCurrentCmdGscnReq, sizeof(CMD_GSCN_REQ_T)); + } + + if (!fgRemoveNLOfromPSCN && !fgRemoveBatchSCNfromPSCN && !fgRemoveGSCNfromPSCN) { + /* prCmdPscnParam->fgIsPeriodicallyScn = FALSE; */ + prScanInfo->fgPscnOnnning = FALSE; + scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); + scnFsmPSCNAction(prAdapter, ucPscanAct); + } else { + /* prCmdPscnParam->fgIsPeriodicallyScn = TRUE; */ + scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); + DBGLOG(SCN, INFO, " disable NLO or GSCN or Batch but fgIsPeriodicallyScn = TRUE <-----\n"); + } + } + +} + +#if 1 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Combine GSCN , Batch, PNO Scan params into PSCAN param +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ + +BOOLEAN +scnCombineParamsIntoPSCN(IN P_ADAPTER_T prAdapter, + IN P_CMD_NLO_REQ prNewCmdNloReq, + IN P_CMD_BATCH_REQ_T prNewCmdBatchReq, + IN P_CMD_GSCN_REQ_T prNewCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN) +{ + P_SCAN_INFO_T prScanInfo; + /* CMD_SET_PSCAN_PARAM rCmdPscnParam; */ + P_CMD_SET_PSCAN_PARAM prCmdPscnParam; + /* UINT_8 i, j = 0; */ + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + prCmdPscnParam = (P_CMD_SET_PSCAN_PARAM) kalMemAlloc(sizeof(CMD_SET_PSCAN_PARAM), VIR_MEM_TYPE); + if (!prCmdPscnParam) { + DBGLOG(SCN, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); + return -ENOMEM; + } + kalMemZero(prCmdPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + + prCmdPscnParam->ucVersion = CURRENT_PSCN_VERSION; + + if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { + scnRemoveFromPSCN(prAdapter, + fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN, prCmdPscnParam); + } else { + DBGLOG(SCN, INFO, "combine GSCN or Batch or NLO to PSCN --->\n"); + + scnSubCombineNLOtoPSCN(prAdapter, prNewCmdNloReq, prCmdPscnParam); + scnSubCombineBatchSCNtoPSCN(prAdapter, prNewCmdBatchReq, prCmdPscnParam); + if (prNewCmdGscnReq) + scnSubCombineGSCNtoPSCN(prAdapter, prNewCmdGscnReq, NULL, prCmdPscnParam); + if (prNewCmdGscnConfig) + scnSubCombineGSCNtoPSCN(prAdapter, NULL, prNewCmdGscnConfig, prCmdPscnParam); + /* scnFsmPSCNSetParam(prAdapter, prCmdPscnParam); */ + +#if 0 + DBGLOG(SCN, TRACE, "combine GSCN or Batch or NLO to PSCN <--- rCmdPscnParam\n"); + DBGLOG(SCN, TRACE, + "Period[%u], NumCache[%u], Threshold[%u], NumBuckets[%u],GSCNEn[%d] NLOEn[%d] BatchEn[%d]\n", + prCmdPscnParam->rCmdGscnReq.u4BasePeriod, prCmdPscnParam->rCmdGscnReq.ucNumScnToCache, + prCmdPscnParam->rCmdGscnReq.u4BufferThreshold, prCmdPscnParam->rCmdGscnReq.u4NumBuckets, + prCmdPscnParam->fgGScnEnable, prCmdPscnParam->fgNLOScnEnable, + prCmdPscnParam->fgBatchScnEnable)); + + for (i = 0; i < prCmdPscnParam->rCmdGscnReq.u4NumBuckets; i++) { + DBGLOG(SCN, TRACE, "rCmdPscnParam.rCmdGscnParam.arChannelBucket[%d] has channel: ", i); + DBGLOG(SCN, TRACE, + "band[%u], ChnBkt[%u] NumChns[%u], BktFreqMltpl[%u] Flag[%u]\n", + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].eBand, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].u2BucketIndex, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucBucketFreqMultiple, + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucReportFlag)); + for (j = 0; j < prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].ucNumChannels; j++) { + DBGLOG(SCN, TRACE, " %d, ", + prCmdPscnParam->rCmdGscnReq.arChannelBucket[i].arChannelList[j].ucChannel); + } + DBGLOG(SCN, TRACE, "\n"); + } +#endif + } + + memcpy(prScanInfo->prPscnParam, prCmdPscnParam, sizeof(CMD_SET_PSCAN_PARAM)); + kalMemFree(prCmdPscnParam, VIR_MEM_TYPE, sizeof(CMD_SET_PSCAN_PARAM)); + return TRUE; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmSetGSCNConfig(IN P_ADAPTER_T prAdapter, IN P_CMD_GSCN_SCN_COFIG_T prCmdGscnScnConfig) +{ + CMD_GSCN_SCN_COFIG_T rCmdGscnScnConfig; + + ASSERT(prAdapter); + memcpy(&rCmdGscnScnConfig, prCmdGscnScnConfig, sizeof(CMD_GSCN_SCN_COFIG_T)); + DBGLOG(SCN, TRACE, "rCmdGscnScnConfig: u4BufferThreshold; [%d] ucNumApPerScn [%d] ucNumScnToCache [%d]\n", + rCmdGscnScnConfig.u4BufferThreshold, + rCmdGscnScnConfig.ucNumApPerScn, + rCmdGscnScnConfig.u4NumScnToCache); + + scnPSCNFsm(prAdapter, PSCN_RESET, NULL, NULL, NULL, &rCmdGscnScnConfig, FALSE, FALSE, FALSE, FALSE); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief handler for Set CMD_ID_SET_PSCN_MAC_ADDR +* +* \param[in] +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN scnFsmGetGSCNResult(IN P_ADAPTER_T prAdapter, IN P_CMD_GET_GSCAN_RESULT_T prGetGscnScnResultCmd) +{ + CMD_GET_GSCAN_RESULT_T rGetGscnScnResultCmd; + P_SCAN_INFO_T prScanInfo; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + memcpy(&rGetGscnScnResultCmd, prGetGscnScnResultCmd, sizeof(CMD_GET_GSCAN_RESULT_T)); + DBGLOG(SCN, INFO, "rGetGscnScnResultCmd: ucGetNum [%d] fgFlush [%d]\n", + rGetGscnScnResultCmd.u4Num, rGetGscnScnResultCmd.ucFlush); + + if (prScanInfo->fgPscnOnnning && prScanInfo->prPscnParam->fgGScnEnable) { + wlanSendSetQueryCmd(prAdapter, + CMD_ID_GET_GSCN_SCN_RESULT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_GET_GSCAN_RESULT_T), (PUINT_8) &rGetGscnScnResultCmd, NULL, 0); + return TRUE; + } + /* debug msg, No PSCN, Sched SCAN GSCN ongoing ??? */ + return FALSE; + +} + +VOID +scnPSCNFsm(IN P_ADAPTER_T prAdapter, + ENUM_PSCAN_STATE_T eNextPSCNState, + IN P_CMD_NLO_REQ prCmdNloReq, + IN P_CMD_BATCH_REQ_T prCmdBatchReq, + IN P_CMD_GSCN_REQ_T prCmdGscnReq, + IN P_CMD_GSCN_SCN_COFIG_T prNewCmdGscnConfig, + IN BOOLEAN fgRemoveNLOfromPSCN, + IN BOOLEAN fgRemoveBatchSCNfromPSCN, IN BOOLEAN fgRemoveGSCNfromPSCN, IN BOOLEAN fgEnableGSCN) +{ + P_SCAN_INFO_T prScanInfo; + BOOLEAN fgTransitionState = FALSE; + + ASSERT(prAdapter); + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + + do { + fgTransitionState = FALSE; + + DBGLOG(SCN, STATE, "eCurrentPSCNState=%d, eNextPSCNState=%d\n", + prScanInfo->eCurrentPSCNState, eNextPSCNState); + + switch (prScanInfo->eCurrentPSCNState) { + case PSCN_IDLE: + if (eNextPSCNState == PSCN_RESET) { + if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { + DBGLOG(SCN, TRACE, "Unexpected remove NLO/BATCH/GSCN request\n"); + eNextPSCNState = PSCN_IDLE; + break; + } + + if (prCmdNloReq || prCmdBatchReq) { + DBGLOG(SCN, TRACE, "PSCN_IDLE->PSCN_RESET,.... scnFsmPSCNActionDISABLE\n"); + /*TBD check PSCAN is ongoing */ + scnFsmPSCNAction(prAdapter, DISABLE); + break; + } + + } else if (eNextPSCNState == PSCN_SCANNING) { + if (fgEnableGSCN) { + if (prScanInfo->fgPscnOnnning) + scnFsmPSCNAction(prAdapter, DISABLE); + if (prScanInfo->fgGScnParamSet) { + DBGLOG(SCN, TRACE, + "PSCN_IDLE->PSCN_SCANNING,.... scnFsmPSCNActionENABLE\n"); + prScanInfo->prPscnParam->fgGScnEnable = TRUE; + scnFsmPSCNSetParam(prAdapter, + (P_CMD_SET_PSCAN_PARAM)prScanInfo->prPscnParam); + scnFsmPSCNAction(prAdapter, ENABLE); + eNextPSCNState = PSCN_SCANNING; + } + } + } + break; + + case PSCN_RESET: + scnCombineParamsIntoPSCN(prAdapter, + prCmdNloReq, + prCmdBatchReq, + prCmdGscnReq, + prNewCmdGscnConfig, + fgRemoveNLOfromPSCN, fgRemoveBatchSCNfromPSCN, fgRemoveGSCNfromPSCN); + + if (!prScanInfo->prPscnParam->fgNLOScnEnable && !prScanInfo->prPscnParam->fgBatchScnEnable + && !prScanInfo->prPscnParam->fgGScnEnable) { + DBGLOG(SCN, TRACE, + "PSCN_RESET->PSCN_IDLE,.... fgNLOScnEnable/fgBatchScnEnable/fgGScnEnable false\n"); + eNextPSCNState = PSCN_IDLE; + } else { + if (prScanInfo->prPscnParam->fgNLOScnEnable + || prScanInfo->prPscnParam->fgBatchScnEnable) { + scnFsmPSCNSetParam(prAdapter, (P_CMD_SET_PSCAN_PARAM) prScanInfo->prPscnParam); + scnFsmPSCNAction(prAdapter, ENABLE); + eNextPSCNState = PSCN_SCANNING; + DBGLOG(SCN, TRACE, + "PSCN_RESET->PSCN_SCANNING,.... fgNLOScnEnable/fgBatchScnEnable ENABLE\n"); + } + } + break; + + case PSCN_SCANNING: + if (eNextPSCNState == PSCN_RESET) { + if (fgRemoveNLOfromPSCN || fgRemoveBatchSCNfromPSCN || fgRemoveGSCNfromPSCN) { + DBGLOG(SCN, TRACE, + "PSCN_SCANNING->PSCN_RESET,.... fgRemoveNLOfromPSCN/fgRemoveBatchSCNfromPSCN/fgRemoveGSCNfromPSCN\n"); + scnFsmPSCNAction(prAdapter, DISABLE); + break; + } + + if (prCmdNloReq || prCmdBatchReq || prCmdGscnReq || prNewCmdGscnConfig) { + DBGLOG(SCN, TRACE, + "PSCN_SCANNING->PSCN_RESET,.... prCmdNloReq/prCmdBatchReq/prCmdGscnReq/prNewCmdGscnConfig\n"); + scnFsmPSCNAction(prAdapter, DISABLE); + break; + } + + } else if (eNextPSCNState == PSCN_SCANNING) { + if (fgEnableGSCN) { + if (prScanInfo->prPscnParam->fgGScnEnable && (!prScanInfo->fgPscnOnnning)) { + DBGLOG(SCN, TRACE, + "PSCN_SCANNING->PSCN_SCANNING,.... fgGScnEnable/!fgPscnOnnning\n"); + /* scnFsmPSCNAction(prAdapter, ENABLE); */ + eNextPSCNState = PSCN_SCANNING; + } else { + + DBGLOG(SCN, TRACE, + "PSCN_SCANNING->PSCN_SCANNING,.... fgGScnEnable/!fgPscnOnnning\n"); + } + } + } + eNextPSCNState = PSCN_SCANNING; + break; + + default: + DBGLOG(SCN, WARN, "Unexpected state\n"); + ASSERT(0); + break; + } + + DBGLOG(SCN, STATE, "eCurrentState %d , eNextPSCNState %d\n", + prScanInfo->eCurrentPSCNState, eNextPSCNState); + if (prScanInfo->eCurrentPSCNState != eNextPSCNState) + fgTransitionState = TRUE; + + prScanInfo->eCurrentPSCNState = eNextPSCNState; + } while (fgTransitionState); + +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c new file mode 100644 index 0000000000000..29eb8d4e7d92f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/sec_fsm.c @@ -0,0 +1,1112 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/sec_fsm.c#1 +*/ + +/*! \file "sec_fsm.c" + \brief This is the file implement security check state machine. + + In security module, do the port control check after success join to an AP, + and the path to NORMAL TR, the state machine handle these state transition. +*/ + +/* +** Log: sec_fsm.c + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Adjust code for DBG and CONFIG_XLOG. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 03 29 2011 wh.su + * [WCXRP00000248] [MT6620 Wi-Fi][FW]Fixed the Klockwork error + * fixed the kclocwork error. + * + * 01 26 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * . + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Fix Compile Error when DBG is disabled. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 24 2010 wh.su + * NULL + * [WCXRP00005002][MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 19 2010 wh.su + * NULL + * adding the tx pkt call back handle for countermeasure. + * + * 07 19 2010 wh.su + * + * fixed the compilng error at debug mode. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * modify some code for concurrent network. + * + * 06 19 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * consdier the concurrent network setting. + * + * 05 28 2010 wh.su + * [BORA00000626][MT6620] Refine the remove key flow for WHQL testing + * fixed the ad-hoc wpa-none send non-encrypted frame issue. + * + * 05 24 2010 kevin.huang + * [BORA00000794][WIFISYS][New Feature]Power Management Support + * Refine authSendAuthFrame() for NULL STA_RECORD_T case and minimum deauth interval. + * + * 04 24 2010 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * g_aprBssInfo[] depends on CFG_SUPPORT_P2P and CFG_SUPPORT_BOW + * + * 04 13 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the Klocwork error and refine the class error message. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * Fixed the pre-authentication timer not correctly init issue, + * and modify the security related callback function prototype. + * + * 03 01 2010 wh.su + * [BORA00000605][WIFISYS] Phase3 Integration + * Refine the variable and parameter for security. + * + * 01 27 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * add and fixed some security function. + * + * 01 13 2010 wh.su + * [BORA00000476][Wi-Fi][firmware] Add the security module initialize code + * fixed the compiling warning + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine some code + * + * Dec 4 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * refine the code + * + * Dec 1 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * code refine + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the function name + * + * Nov 19 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adjust the state machine, to meet the firmware security design v1.1 + * + * Nov 18 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_RSN_MIGRATION + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if DBG +/*lint -save -e64 Type mismatch */ +static PUINT_8 apucDebugSecState[SEC_STATE_NUM] = { + (PUINT_8) DISP_STRING("SEC_STATE_INIT"), + (PUINT_8) DISP_STRING("SEC_STATE_INITIATOR_PORT_BLOCKED"), + (PUINT_8) DISP_STRING("SEC_STATE_RESPONDER_PORT_BLOCKED"), + (PUINT_8) DISP_STRING("SEC_STATE_CHECK_OK"), + (PUINT_8) DISP_STRING("SEC_STATE_SEND_EAPOL"), + (PUINT_8) DISP_STRING("SEC_STATE_SEND_DEAUTH"), + (PUINT_8) DISP_STRING("SEC_STATE_COUNTERMEASURE"), +}; + +/*lint -restore */ +#endif /* DBG */ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + P_AIS_SPECIFIC_BSS_INFO_T prAisSpecBssInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + +#if 1 /* MT6620 */ + /* At MT5921, is ok, but at MT6620, firmware base ASIC, the firmware */ + /* will lost these data, thus, driver have to keep the wep material and */ + /* setting to firmware while awake from D3. */ +#endif + + prSecInfo->eCurrentState = SEC_STATE_INIT; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + if (IS_STA_IN_AIS(prSta)) { + prAisSpecBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + prAisSpecBssInfo->u4RsnaLastMICFailTime = 0; + prAisSpecBssInfo->fgCheckEAPoLTxDone = FALSE; + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer, + (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEapolTxTimeout, (ULONG) prSta); + + cnmTimerInitTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + (PFN_MGMT_TIMEOUT_FUNC) secFsmEventEndOfCounterMeasure, (ULONG) prSta); + + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do uninitialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the STA record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID /* whsu:Todo: */ +secFsmUnInit(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + + prSecInfo->fg2nd1xSend = FALSE; + prSecInfo->fgKeyStored = FALSE; + + /* nicPrivacyRemoveWlanTable(prSta->ucWTEntry); */ + + if (IS_STA_IN_AIS(prSta)) { + cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); + cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* STANDBY to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to INITIATOR_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_INITIATOR_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INIT to RESPONDER_PORT_BLOCKED. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INIT_to_RESPONDER_PORT_BLOCKED(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* INITIATOR_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_INITIATOR_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* RESPONDER_PORT_BLOCKED to CHECK_OK. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_RESPONDER_PORT_BLOCKED_to_CHECK_OK(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + secSetPortBlocked(prAdapter, prSta, FALSE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* CHECK_OK to SEND_EAPOL +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_CHECK_OK_to_SEND_EAPOL(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + ASSERT(prSta); + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prAisBssInfo->fgCheckEAPoLTxDone = TRUE; + + /* cnmTimerStartTimer(prAdapter, */ + /* &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer, */ + /* SEC_TO_MSEC(EAPOL_REPORT_SEND_TIMEOUT_INTERVAL_SEC)); */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_EAPOL to SEND_DEAUTH. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - none +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_SEND_EAPOL_to_SEND_DEAUTH(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + /* Compose deauth frame to AP, a call back function for tx done */ + if (authSendDeauthFrame(prAdapter, + prSta, + (P_SW_RFB_T) NULL, + REASON_CODE_MIC_FAILURE, + (PFN_TX_DONE_HANDLER) secFsmEventDeauthTxDone) != WLAN_STATUS_SUCCESS) { + ASSERT(FALSE); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_SEND_DEAUTH_to_COUNTERMEASURE(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + ASSERT(prAdapter); + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + /* Start the 60 sec timer */ + cnmTimerStartTimer(prAdapter, + &prAdapter->rWifiVar.rAisSpecificBssInfo.rRsnaBlockTrafficTimer, + SEC_TO_MSEC(COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do action part while in STATE transition of +* SEND_DEAUTH to COUNTERMEASURE. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +static inline VOID secFsmTrans_COUNTERMEASURE_to_INIT(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + + /* Clear the counter measure flag */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The Core FSM engine of security module. +* +* \param[in] prSta Pointer to the Sta record +* \param[in] eNextState Enum value of next sec STATE +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmSteps(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta, IN ENUM_SEC_STATE_T eNextState) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + ASSERT(prSecInfo); + + DEBUGFUNC("secFsmSteps"); + do { + /* Do entering Next State */ + prSecInfo->ePreviousState = prSecInfo->eCurrentState; + + /* Do entering Next State */ +#if DBG + DBGLOG(RSN, STATE, "\n %pM TRANSITION: [%s] -> [%s]\n\n", + prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState], apucDebugSecState[eNextState]); +#else + DBGLOG(RSN, STATE, "\n %pM [%d] TRANSITION: [%d] -> [%d]\n\n", + prSta->aucMacAddr, DBG_RSN_IDX, prSecInfo->eCurrentState, eNextState); +#endif + prSecInfo->eCurrentState = eNextState; + + fgIsTransition = (BOOLEAN) FALSE; +#if 0 + /* Do tasks of the State that we just entered */ + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + break; + case SEC_STATE_INITIATOR_PORT_BLOCKED: + break; + case SEC_STATE_RESPONDER_PORT_BLOCKED: + break; + case SEC_STATE_CHECK_OK: + break; + case SEC_STATE_SEND_EAPOL: + break; + case SEC_STATE_SEND_DEAUTH: + break; + case SEC_STATE_COUNTERMEASURE: + break; + default: + ASSERT(0); /* Make sure we have handle all STATEs */ + break; + } +#endif + } while (fgIsTransition); + + return; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do initialization of Security FSM and all variables in +* SEC_INFO_T. +* +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventStart(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + ENUM_SEC_STATE_T eNextState; + + DBGLOG(RSN, TRACE, "secFsmRunEventStart\n"); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + DBGLOG(RSN, TRACE, "secFsmRunEventStart for sta %pM network %d\n", + prSta->aucMacAddr, prSta->ucNetTypeIndex); + + prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + /* prSta->fgTransmitKeyExist = FALSE; */ + /* whsu:: nicPrivacySetStaDefaultWTIdx(prSta); */ + +#if 1 /* Since the 1x and key can set to firmware in order, always enter the check ok state */ + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); +#else + if (IS_STA_IN_AIS(prSta->eStaType)) { + if (secRsnKeyHandshakeEnabled(prAdapter) == TRUE +#if CFG_SUPPORT_WAPI + || (prAdapter->rWifiVar.rConnSettings.fgWapiMode) +#endif + ) { + prSta->fgTransmitKeyExist = FALSE; + /* nicPrivacyInitialize(prSta->ucNetTypeIndex); */ + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); + } else { + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, CHECK_OK); + } + } +#if CFG_ENABLE_WIFI_DIRECT || CFG_ENABLE_BT_OVER_WIFI +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_BT_OVER_WIFI + else if ((prSta->eStaType == STA_TYPE_BOW_CLIENT) || (prSta->eStaType == STA_TYPE_P2P_GC)) { +#elif CFG_ENABLE_WIFI_DIRECT + else if (prSta->eStaType == STA_TYPE_P2P_GC) { +#elif CFG_ENABLE_BT_OVER_WIFI + else if (prSta->eStaType == STA_TYPE_BOW_CLIENT) { +#endif + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, RESPONDER_PORT_BLOCKED); + } +#endif + else + SEC_STATE_TRANSITION(prAdapter, prSta, INIT, INITIATOR_PORT_BLOCKED); +#endif + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + +} /* secFsmRunEventStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function called by reset procedure to force the sec fsm enter +* idle state +* +* \param[in] ucNetTypeIdx The Specific Network type index +* \param[in] prSta Pointer to the Sta record +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventAbort(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + + DBGLOG(RSN, TRACE, "secFsmEventAbort for sta %pM network %d\n", + prSta->aucMacAddr, prSta->ucNetTypeIndex); + + ASSERT(prSta); + + if (!prSta) + return; + + if (!IS_STA_IN_AIS(prSta)) + return; + + prSecInfo = (P_SEC_INFO_T) &prSta->rSecInfo; + + prSta->fgTransmitKeyExist = FALSE; + + secSetPortBlocked(prAdapter, prSta, TRUE); + + if (prSecInfo == NULL) + return; + + if (IS_STA_IN_AIS(prSta)) { + + prAdapter->rWifiVar.rAisSpecificBssInfo.fgTransmitKeyExist = FALSE; + + if (prSecInfo->eCurrentState == SEC_STATE_SEND_EAPOL) { + if (prAdapter->rWifiVar.rAisSpecificBssInfo.fgCheckEAPoLTxDone == FALSE) { + DBGLOG(RSN, TRACE, "EAPOL STATE not match the flag\n"); + /* cnmTimerStopTimer(prAdapter, &prAdapter->rWifiVar. + * rAisSpecificBssInfo.rRsnaEAPoLReportTimeoutTimer); */ + } + } + } + prSecInfo->eCurrentState = SEC_STATE_INIT; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "2nd EAPoL Tx is sending" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEvent2ndEapolTx(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + /* BOOLEAN fgIsTransition = (BOOLEAN)FALSE; */ + + DEBUGFUNC("secFsmRunEvent2ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED: + case SEC_STATE_CHECK_OK: + prSecInfo->fg2nd1xSend = TRUE; + break; + default: +#if DBG + DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, WARN, "Rcv 2nd EAPoL at [%d]\n", prSecInfo->eCurrentState); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEvent2ndEapolTx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "4th EAPoL Tx is Tx done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEvent4ndEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + P_CMD_802_11_KEY prStoredKey; + + DEBUGFUNC("secFsmRunEvent4ndEapolTx"); + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INITIATOR_PORT_BLOCKED: + case SEC_STATE_CHECK_OK: + prSecInfo->fg2nd1xSend = FALSE; + if (prSecInfo->fgKeyStored) { + prStoredKey = (P_CMD_802_11_KEY) prSecInfo->aucStoredKey; + + /* prSta = rxmLookupStaRecIndexFromTA(prStoredKey->aucPeerAddr); */ + /* if (nicPrivacySetKeyEntry(prStoredKey, prSta->ucWTEntry) == FALSE) */ + /* DBGLOG(RSN, WARN, ("nicPrivacySetKeyEntry() fail,..\n")); */ + + /* key update */ + prSecInfo->fgKeyStored = FALSE; + prSta->fgTransmitKeyExist = TRUE; + } + if (prSecInfo->eCurrentState == SEC_STATE_INITIATOR_PORT_BLOCKED) + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + break; + default: + +#if DBG + DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at %s\n", apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, WARN, "Rcv thh EAPoL Tx done at [%d]\n", prSecInfo->eCurrentState); +#endif + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEvent4ndEapolTx */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Pairwise key installed" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \retval TRUE The key can be installed to HW +* \retval FALSE The kay conflict with the current key, abort it +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN secFsmEventPTKInstalled(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgStatus = TRUE; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + ASSERT(prSta); + + prSecInfo = &prSta->rSecInfo; + if (prSecInfo == NULL) + return TRUE; /* Not PTK */ + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAdd), + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + eNextState = prSecInfo->eCurrentState; + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_INIT: + /* Legacy wep, wpa-none */ + break; + + case SEC_STATE_INITIATOR_PORT_BLOCKED: + if (prSecInfo->fg2nd1xSend) + ; + else + SEC_STATE_TRANSITION(prAdapter, prSta, INITIATOR_PORT_BLOCKED, CHECK_OK); + break; + + case SEC_STATE_RESPONDER_PORT_BLOCKED: + SEC_STATE_TRANSITION(prAdapter, prSta, RESPONDER_PORT_BLOCKED, CHECK_OK); + break; + + case SEC_STATE_CHECK_OK: + break; + + default: + fgStatus = FALSE; + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return fgStatus; + +} /* end of secFsmRunEventPTKInstalled() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Counter Measure" to SEC FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventStartCounterMeasure(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prSta) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventStartCounterMeasure"); + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = &prSta->rSecInfo; + + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + prAdapter->rWifiVar.rAisSpecificBssInfo.u4RsnaLastMICFailTime = 0; + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_CHECK_OK: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = TRUE; + + /* dls port control */ + SEC_STATE_TRANSITION(prAdapter, prSta, CHECK_OK, SEND_EAPOL); + } + break; + + default: + break; + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + + return; + +} /* secFsmRunEventStartCounterMeasure */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "802.1x EAPoL Tx Done" to Sec FSM. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventEapolTxDone(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + P_AIS_SPECIFIC_BSS_INFO_T prAisBssInfo; + + DEBUGFUNC("secFsmRunEventEapolTxDone"); + + ASSERT(prStaRec); + + if (rTxDoneStatus != TX_RESULT_SUCCESS) { + DBGLOG(RSN, INFO, "Error EAPoL fram fail to send!!\n"); + /* ASSERT(0); */ + return; + } + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prAisBssInfo = &prAdapter->rWifiVar.rAisSpecificBssInfo; + + ASSERT(prAisBssInfo); + + prSecInfo = &prStaRec->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_EAPOL: + if (prAisBssInfo->fgCheckEAPoLTxDone == FALSE) + ASSERT(0); + + prAisBssInfo->fgCheckEAPoLTxDone = FALSE; + /* cnmTimerStopTimer(prAdapter, &prAisBssInfo->rRsnaEAPoLReportTimeoutTimer); */ + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_EAPOL, SEND_DEAUTH); + break; + default: + break; + } + + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prStaRec, eNextState); + + return; + +} /* secFsmRunEventEapolTxDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will indicate an Event of "Deauth frame Tx Done" to Sec FSM. +* +* \param[in] pMsduInfo Pointer to the Msdu Info +* \param[in] rStatus The Tx done status +* +* \return - +* +* \note after receive deauth frame, callback function call this +*/ +/*----------------------------------------------------------------------------*/ +VOID +secFsmEventDeauthTxDone(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventDeauthTxDone"); + + ASSERT(prMsduInfo); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + ASSERT(prStaRec); + + if (!prStaRec) + return; + + if (!IS_STA_IN_AIS(prStaRec)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = (P_SEC_INFO_T) &prStaRec->rSecInfo; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prStaRec->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prStaRec->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + + DBGLOG(RSN, TRACE, "Set timer %d\n", COUNTER_MEASURE_TIMEOUT_INTERVAL_SEC); + + SEC_STATE_TRANSITION(prAdapter, prStaRec, SEND_DEAUTH, COUNTERMEASURE); + + break; + + default: + ASSERT(0); + break; + } + +} /* secFsmRunEventDeauthTxDone */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will check the eapol error frame fail to send issue. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventEapolTxTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParm) +{ + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("secFsmRunEventEapolTxTimeout"); + + prStaRec = (P_STA_RECORD_T) ulParm; + + ASSERT(prStaRec); + + /* Todo:: How to handle the Eapol Error fail to send case? */ + ASSERT(0); + + return; + +} /* secFsmEventEapolTxTimeout */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will stop the counterMeasure duration. +* +* \param[in] prSta Pointer to the Sta record +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID secFsmEventEndOfCounterMeasure(IN P_ADAPTER_T prAdapter, ULONG ulParm) +{ + P_STA_RECORD_T prSta; + P_SEC_INFO_T prSecInfo; + ENUM_SEC_STATE_T eNextState; + BOOLEAN fgIsTransition = (BOOLEAN) FALSE; + + DEBUGFUNC("secFsmRunEventEndOfCounterMeasure"); + + prSta = (P_STA_RECORD_T) ulParm; + + ASSERT(prSta); + + if (!IS_STA_IN_AIS(prSta)) { + DBGLOG(RSN, INFO, "Counter Measure should occur at AIS network!!\n"); + /* ASSERT(0); */ + return; + } + + prSecInfo = &prSta->rSecInfo; + eNextState = prSecInfo->eCurrentState; + +#if DBG + DBGLOG(RSN, TRACE, "%pM Sec state %s\n", prSta->aucMacAddr, + apucDebugSecState[prSecInfo->eCurrentState]); +#else + DBGLOG(RSN, TRACE, "%pM Sec state [%d]\n", prSta->aucMacAddr, prSecInfo->eCurrentState); +#endif + + switch (prSecInfo->eCurrentState) { + case SEC_STATE_SEND_DEAUTH: + { + prAdapter->rWifiVar.rAisSpecificBssInfo.fgCounterMeasure = FALSE; + + SEC_STATE_TRANSITION(prAdapter, prSta, COUNTERMEASURE, INIT); + } + break; + + default: + ASSERT(0); + } + + /* Call arbFsmSteps() when we are going to change ARB STATE */ + if (prSecInfo->eCurrentState != eNextState) + secFsmSteps(prAdapter, prSta, eNextState); + +} /* end of secFsmRunEventEndOfCounterMeasure */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c new file mode 100644 index 0000000000000..ab3fcc028375b --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/stats.c @@ -0,0 +1,1342 @@ +/* +** Id: stats.c#1 +*/ + +/*! \file stats.c + \brief This file includes statistics support. +*/ + +/* +** Log: stats.c + * + * 07 17 2014 samp.lin + * NULL + * Initial version. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +enum EVENT_TYPE { + EVENT_RX, + EVENT_TX, + EVENT_TX_DONE +}; +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +static WLAN_STATUS +statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +UINT_64 u8DrvOwnStart, u8DrvOwnEnd; +UINT32 u4DrvOwnMax = 0; +#define CFG_USER_LOAD 0 +static UINT_16 su2TxDoneCfg = CFG_DHCP | CFG_ICMP | CFG_EAPOL; +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display all environment log. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + STA_RECORD_T *prStaRec; + UINT32 u4NumOfInfo, u4InfoId; + UINT32 u4RxErrBitmap; + STATS_INFO_ENV_T *prInfo; + UINT32 u4Total, u4RateId; + +/* +[wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. +[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event +[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 +[wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: + +[wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) + TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, + bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) + RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) + BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) + OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) + ERR (1st: total number of tx err, 2nd ~ 7st: total number of + WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, + WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) + +[wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) + TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) + +[wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) + RX (1st: latest RCPI, 2nd: chan num) + BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) + OK (number of rx packets without error, number of rx packets to OS) + ERR (number of rx packets with error) + +[wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + CCK MODE (1 2 5.5 11M) +[wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) +[wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) + MIXED MODE (number of rx packets with MCS0 ~ MCS15) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) + delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) + delay from MAC start TX to MAC TX done + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) + delay from HIF to MAC TX done (min, avg, max_system time for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) + delay from driver to MAC TX done (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) + delay from MAC to HIF (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) + delay from HIF to Driver OS (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) + delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) + delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) + delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) + Channel idle time, scan count, channel change count, empty tx quota count, + power save change count from active to PS, maximum delay from PS to active +*/ + + /* init */ + prAdapter = prGlueInfo->prAdapter; + /*prInfo = &rStatsInfoEnv;*/ + prInfo = kalMemAlloc(sizeof(STATS_INFO_ENV_T), VIR_MEM_TYPE); + if (prInfo == NULL) { + DBGLOG(RX, INFO, "prInfo alloc fail"); + return; + } + + kalMemZero(prInfo, sizeof(STATS_INFO_ENV_T)); + + if (u4InBufLen > sizeof(STATS_INFO_ENV_T)) + u4InBufLen = sizeof(STATS_INFO_ENV_T); + + /* parse */ + u4NumOfInfo = *(UINT32 *) prInBuf; + u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); + + /* print */ + for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { + /* + use u4InBufLen, not sizeof(rStatsInfoEnv) + because the firmware version maybe not equal to driver version + */ + kalMemCopy(prInfo, prInBuf + 8, u4InBufLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prInfo->ucStaRecIdx); + if (prStaRec == NULL) + continue; + + DBGLOG(RX, INFO, " Display stats for [%pM]: %uB\n", + prStaRec->aucMacAddr, (UINT32) sizeof(STATS_INFO_ENV_T)); + + if (prStaRec->ucStatsGenDisplayCnt++ > 10) { + /* display general statistics information every 10 * (5 or 10s) */ + DBGLOG(RX, INFO, " TBA(0x%x %u) RBA(0x%x %u)\n", + prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, + prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize); + prStaRec->ucStatsGenDisplayCnt = 0; + } + + if (prInfo->u4TxDataCntErr == 0) { + DBGLOG(RX, INFO, " TOS(%u) OK(%u %u)\n", + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK); + } else { + DBGLOG(RX, INFO, " TOS(%u) OK(%u %u) ERR(%u)\n", + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, prInfo->u4TxDataCntErr); + DBGLOG(RX, INFO, " ERR type(%u %u %u %u %u %u)\n", + prInfo->u4TxDataCntErrType[0], prInfo->u4TxDataCntErrType[1], + prInfo->u4TxDataCntErrType[2], prInfo->u4TxDataCntErrType[3], + prInfo->u4TxDataCntErrType[4], prInfo->u4TxDataCntErrType[5]); + } + + for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4TxRateCntNonHT[u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " non-HT TRATE (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], + prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], + prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], + prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], + prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], + prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], + prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], + prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15]); + } + if (prInfo->u4TxRateCntNonHT[0] > 0) { + DBGLOG(RX, INFO, " HT TRATE (1M %u) (%u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); + } else { + DBGLOG(RX, INFO, " HT TRATE (%u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7]); + } + + if ((prStaRec->u4RxReorderFallAheadCnt != 0) || + (prStaRec->u4RxReorderFallBehindCnt != 0) || (prStaRec->u4RxReorderHoleCnt != 0)) { + DBGLOG(RX, INFO, " TREORDER (%u %u %u)\n", + prStaRec->u4RxReorderFallAheadCnt, + prStaRec->u4RxReorderFallBehindCnt, prStaRec->u4RxReorderHoleCnt); + } + + if (prInfo->u4RxDataCntErr == 0) { + DBGLOG(RX, INFO, " ROK(%u %u)\n", + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt); + } else { + DBGLOG(RX, INFO, " ROK(%u %u) ERR(%u)\n", + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, + prInfo->u4RxDataCntErr); + } + + for (u4RateId = 1, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[0][u4RateId] + prInfo->u4RxRateRetryCnt[0][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[0][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, + " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], + prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], + prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], + prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], + prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], + prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], + prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], + prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], + prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], + prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], + prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], + prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], + prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], + prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], + prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15]); + } else { + DBGLOG(RX, INFO, " RCCK (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[0][0], + prInfo->u4RxRateCnt[0][1], + prInfo->u4RxRateCnt[0][2], + prInfo->u4RxRateCnt[0][3], + prInfo->u4RxRateCnt[0][4], + prInfo->u4RxRateCnt[0][5], + prInfo->u4RxRateCnt[0][6], + prInfo->u4RxRateCnt[0][7], + prInfo->u4RxRateCnt[0][8], + prInfo->u4RxRateCnt[0][9], + prInfo->u4RxRateCnt[0][10], + prInfo->u4RxRateCnt[0][11], + prInfo->u4RxRateCnt[0][12], + prInfo->u4RxRateCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateCnt[0][15]); + } + } else { + if ((prInfo->u4RxRateCnt[0][0] + prInfo->u4RxRateRetryCnt[0][0]) > 0) { + DBGLOG(RX, INFO, " RCCK (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0]); + } + } + + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[1][u4RateId] + prInfo->u4RxRateRetryCnt[1][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[1][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, + " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u)(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], + prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], + prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], + prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], + prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], + prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], + prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], + prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], + prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], + prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], + prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], + prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], + prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], + prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], + prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15]); + } else { + DBGLOG(RX, INFO, " ROFDM (%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[1][0], + prInfo->u4RxRateCnt[1][1], + prInfo->u4RxRateCnt[1][2], + prInfo->u4RxRateCnt[1][3], + prInfo->u4RxRateCnt[1][4], + prInfo->u4RxRateCnt[1][5], + prInfo->u4RxRateCnt[1][6], + prInfo->u4RxRateCnt[1][7], + prInfo->u4RxRateCnt[1][8], + prInfo->u4RxRateCnt[1][9], + prInfo->u4RxRateCnt[1][10], + prInfo->u4RxRateCnt[1][11], + prInfo->u4RxRateCnt[1][12], + prInfo->u4RxRateCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateCnt[1][15]); + } + } + + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateCnt[2][u4RateId] + prInfo->u4RxRateRetryCnt[2][u4RateId]; + if (u4Total > 0) { + for (u4RateId = 0, u4Total = 0; u4RateId < 16; u4RateId++) + u4Total += prInfo->u4RxRateRetryCnt[2][u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " RHT\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], + prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], + prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], + prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], + prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], + prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], + prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7]); + } else { + DBGLOG(RX, INFO, " RHT (%u %u %u %u %u %u %u %u)\n", + prInfo->u4RxRateCnt[2][0], + prInfo->u4RxRateCnt[2][1], + prInfo->u4RxRateCnt[2][2], + prInfo->u4RxRateCnt[2][3], + prInfo->u4RxRateCnt[2][4], + prInfo->u4RxRateCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateCnt[2][7]); + } + } + + /* RX drop counts */ + for (u4RateId = 0, u4Total = 0; u4RateId < 20; u4RateId++) + u4Total += prInfo->u4NumOfRxDrop[u4RateId]; + if (u4Total > 0) { + DBGLOG(RX, INFO, " RX Drop Count: (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n" + " (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", + prInfo->u4NumOfRxDrop[0], prInfo->u4NumOfRxDrop[1], + prInfo->u4NumOfRxDrop[2], prInfo->u4NumOfRxDrop[3], + prInfo->u4NumOfRxDrop[4], prInfo->u4NumOfRxDrop[5], + prInfo->u4NumOfRxDrop[6], prInfo->u4NumOfRxDrop[7], + prInfo->u4NumOfRxDrop[8], prInfo->u4NumOfRxDrop[9], + prInfo->u4NumOfRxDrop[10], prInfo->u4NumOfRxDrop[11], + prInfo->u4NumOfRxDrop[12], prInfo->u4NumOfRxDrop[13], + prInfo->u4NumOfRxDrop[14], prInfo->u4NumOfRxDrop[15], + prInfo->u4NumOfRxDrop[16], prInfo->u4NumOfRxDrop[17], + prInfo->u4NumOfRxDrop[18], prInfo->u4NumOfRxDrop[19]); + } + + /* delay from HIF RX to HIF RX Done */ + if (((prInfo->u4StayIntMinHR2HRD[1] + prInfo->u4StayIntAvgHR2HRD[1] + + prInfo->u4StayIntMaxHR2HRD[1]) > 0) || + ((prInfo->u4StayIntMinHR2HRD[2] + prInfo->u4StayIntAvgHR2HRD[2] + + prInfo->u4StayIntMaxHR2HRD[2]) > 0)) { + DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], + prInfo->u4StayIntMaxHR2HRD[0], + prInfo->u4StayIntMinHR2HRD[1], prInfo->u4StayIntAvgHR2HRD[1], + prInfo->u4StayIntMaxHR2HRD[1], + prInfo->u4StayIntMinHR2HRD[2], prInfo->u4StayIntAvgHR2HRD[2], + prInfo->u4StayIntMaxHR2HRD[2]); + } else { + DBGLOG(RX, INFO, " StayIntR_HR2HRD us (%u %u %u)\n", + prInfo->u4StayIntMinHR2HRD[0], prInfo->u4StayIntAvgHR2HRD[0], + prInfo->u4StayIntMaxHR2HRD[0]); + } + + /* others */ + DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%x)\n", + prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, + prInfo->u4NumOfChanChange, prInfo->u4CurrChnlInfo); +#if CFG_SUPPORT_THERMO_THROTTLING + prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; +#endif + /* reset */ + kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); + kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); + kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); + prStaRec->u4StatsRxPassToOsCnt = 0; + prStaRec->u4RxReorderFallAheadCnt = 0; + prStaRec->u4RxReorderFallBehindCnt = 0; + prStaRec->u4RxReorderHoleCnt = 0; + } + + STATS_DRIVER_OWN_RESET(); + kalMemFree(prInfo, VIR_MEM_TYPE, sizeof(STATS_INFO_ENV_T)); +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display all environment log. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void statsInfoEnvDisplay(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + STA_RECORD_T *prStaRec; + UINT32 u4NumOfInfo, u4InfoId; + UINT32 u4RxErrBitmap; + STATS_INFO_ENV_T rStatsInfoEnv, *prInfo; + +/* +[wlan] statsInfoEnvRequest: (INIT INFO) statsInfoEnvRequest cmd ok. +[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event +[wlan] statsEventHandle: (INIT INFO) statsEventHandle: Rcv a event: 0 +[wlan] statsInfoEnvDisplay: (INIT INFO) Display stats for [00:0c:43:31:35:97]: + +[wlan] statsInfoEnvDisplay: (INIT INFO) TPAM(0x0) RTS(0 0) BA(0x1 0) OK(9 9 xxx) ERR(0 0 0 0 0 0 0) + TPAM (bit0: enable 40M, bit1: enable 20 short GI, bit2: enable 40 short GI, + bit3: use 40M TX, bit4: use short GI TX, bit5: use no ack) + RTS (1st: current use RTS/CTS, 2nd: ever use RTS/CTS) + BA (1st: TX session BA bitmap for TID0 ~ TID7, 2nd: peer receive maximum agg number) + OK (1st: total number of tx packet from host, 2nd: total number of tx ok, system time last TX OK) + ERR (1st: total number of tx err, 2nd ~ 7st: total number of + WLAN_STATUS_BUFFER_RETAINED, WLAN_STATUS_PACKET_FLUSHED, WLAN_STATUS_PACKET_AGING_TIMEOUT, + WLAN_STATUS_PACKET_MPDU_ERROR, WLAN_STATUS_PACKET_RTS_ERROR, WLAN_STATUS_PACKET_LIFETIME_ERROR) + +[wlan] statsInfoEnvDisplay: (INIT INFO) TRATE (6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (0 0 0 0 0 0 0 3) + TX rate count (1M 2 5.5 11 NA NA NA NA 48 24 12 6 54 36 18 9) (MCS0 ~ MCS7) + +[wlan] statsInfoEnvDisplay: (INIT INFO) RX(148 1 0) BA(0x1 64) OK(2 2) ERR(0) + RX (1st: latest RCPI, 2nd: chan num) + BA (1st: RX session BA bitmap for TID0 ~ TID7, 2nd: our receive maximum agg number) + OK (number of rx packets without error, number of rx packets to OS) + ERR (number of rx packets with error) + +[wlan] statsInfoEnvDisplay: (INIT INFO) RCCK (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + CCK MODE (1 2 5.5 11M) +[wlan] statsInfoEnvDisplay: (INIT INFO) ROFDM (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + OFDM MODE (NA NA NA NA 6 9 12 18 24 36 48 54M) +[wlan] statsInfoEnvDisplay: (INIT INFO) RHT (0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0) + MIXED MODE (number of rx packets with MCS0 ~ MCS15) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntH2M us (29 29 32) (0 0 0) (0 0 0) + delay from HIF to MAC own bit=1 (min, avg, max for 500B) (min, avg, max for 1000B) (min, avg, max for others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) AirTime us (608 864 4480) (0 0 0) (0 0 0) + delay from MAC start TX to MAC TX done + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayInt us (795 1052 4644_4504) (0 0 0_0) (0 0 0_0) + delay from HIF to MAC TX done (min, avg, max_system time for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntD2T us (795 1052 4644) (0 0 0) (0 0 0) + delay from driver to MAC TX done (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_M2H us (37 40 58) (0 0 0) (0 0 0) + delay from MAC to HIF (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayIntR_H2D us (0 0 0) (0 0 0) (0 0 0) + delay from HIF to Driver OS (min, avg, max for 500B) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCntD2H unit:10ms (10 0 0 0) + delay count from Driver to HIF (count in 0~10ms, 10~20ms, 20~30ms, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt unit:1ms (6 3 0 1) + delay count from HIF to TX DONE (count in 0~1ms, 1~5ms, 5~10ms, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) StayCnt (0~1161:7) (1161~2322:2) (2322~3483:0) (3483~4644:0) (4644~:1) + delay count from HIF to TX DONE (count in 0~1161 ticks, 1161~2322, 2322~3483, 3483~4644, others) + +[wlan] statsInfoEnvDisplay: (INIT INFO) OTHER (61877) (0) (38) (0) (0) (0ms) + Channel idle time, scan count, channel change count, empty tx quota count, + power save change count from active to PS, maximum delay from PS to active +*/ + + /* init */ + prAdapter = prGlueInfo->prAdapter; + prInfo = &rStatsInfoEnv; + kalMemZero(&rStatsInfoEnv, sizeof(rStatsInfoEnv)); + + if (u4InBufLen > sizeof(rStatsInfoEnv)) + u4InBufLen = sizeof(rStatsInfoEnv); + + /* parse */ + u4NumOfInfo = *(UINT32 *) prInBuf; + u4RxErrBitmap = *(UINT32 *) (prInBuf + 4); + + /* print */ + for (u4InfoId = 0; u4InfoId < u4NumOfInfo; u4InfoId++) { + /* + use u4InBufLen, not sizeof(rStatsInfoEnv) + because the firmware version maybe not equal to driver version + */ + kalMemCopy(&rStatsInfoEnv, prInBuf + 8, u4InBufLen); + + prStaRec = cnmGetStaRecByIndex(prAdapter, rStatsInfoEnv.ucStaRecIdx); + if (prStaRec == NULL) + continue; + + DBGLOG(RX, INFO, " Display stats V%d.%d for [%pM]: %uB %ums\n", + prInfo->ucFwVer[0], prInfo->ucFwVer[1], + (prStaRec->aucMacAddr), (UINT32) sizeof(STATS_INFO_ENV_T), + prInfo->u4ReportSysTime); + DBGLOG(RX, INFO, "TPAM(0x%x)RTS(%u %u)BA(0x%x %u)OS(%u)OK(%u %u)ERR(%u %u %u %u %u %u %u)\n", + prInfo->ucTxParam, + prInfo->fgTxIsRtsUsed, prInfo->fgTxIsRtsEverUsed, + prInfo->ucTxAggBitmap, prInfo->ucTxPeerAggMaxSize, + (UINT32) prGlueInfo->rNetDevStats.tx_packets, + prInfo->u4TxDataCntAll, prInfo->u4TxDataCntOK, + prInfo->u4TxDataCntErr, prInfo->u4TxDataCntErrType[0], + prInfo->u4TxDataCntErrType[1], prInfo->u4TxDataCntErrType[2], + prInfo->u4TxDataCntErrType[3], prInfo->u4TxDataCntErrType[4], + prInfo->u4TxDataCntErrType[5])); + + DBGLOG(RX, INFO, "TRATE(%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u)\n", + prInfo->u4TxRateCntNonHT[0], prInfo->u4TxRateCntNonHT[1], + prInfo->u4TxRateCntNonHT[2], prInfo->u4TxRateCntNonHT[3], + prInfo->u4TxRateCntNonHT[4], prInfo->u4TxRateCntNonHT[5], + prInfo->u4TxRateCntNonHT[6], prInfo->u4TxRateCntNonHT[7], + prInfo->u4TxRateCntNonHT[8], prInfo->u4TxRateCntNonHT[9], + prInfo->u4TxRateCntNonHT[10], prInfo->u4TxRateCntNonHT[11], + prInfo->u4TxRateCntNonHT[12], prInfo->u4TxRateCntNonHT[13], + prInfo->u4TxRateCntNonHT[14], prInfo->u4TxRateCntNonHT[15], + prInfo->u4TxRateCntHT[0], prInfo->u4TxRateCntHT[1], + prInfo->u4TxRateCntHT[2], prInfo->u4TxRateCntHT[3], + prInfo->u4TxRateCntHT[4], prInfo->u4TxRateCntHT[5], + prInfo->u4TxRateCntHT[6], prInfo->u4TxRateCntHT[7])); + + DBGLOG(RX, INFO, " TREORDER (%u %u %u)\n", + prStaRec->u4RxReorderFallAheadCnt, + prStaRec->u4RxReorderFallBehindCnt, prStaRec->u4RxReorderHoleCnt); + + DBGLOG(RX, INFO, " RX(%u %u %u) BA(0x%x %u) OK(%u %u) ERR(%u)\n", + prInfo->ucRcvRcpi, prInfo->ucHwChanNum, prInfo->fgRxIsShortGI, + prInfo->ucRxAggBitmap, prInfo->ucRxAggMaxSize, + prInfo->u4RxDataCntAll, prStaRec->u4StatsRxPassToOsCnt, prInfo->u4RxDataCntErr); + + DBGLOG(RX, INFO, " RX Free MAC DESC(%u %u %u %u %u %u) Free HIF DESC(%u %u %u %u %u %u)\n", + prInfo->u4RxMacFreeDescCnt[0], prInfo->u4RxMacFreeDescCnt[1], + prInfo->u4RxMacFreeDescCnt[2], prInfo->u4RxMacFreeDescCnt[3], + prInfo->u4RxMacFreeDescCnt[4], prInfo->u4RxMacFreeDescCnt[5], + prInfo->u4RxHifFreeDescCnt[0], prInfo->u4RxHifFreeDescCnt[1], + prInfo->u4RxHifFreeDescCnt[2], prInfo->u4RxHifFreeDescCnt[3], + prInfo->u4RxHifFreeDescCnt[4], prInfo->u4RxHifFreeDescCnt[5])); + + DBGLOG(RX, INFO, " RCCK (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[0][0], prInfo->u4RxRateRetryCnt[0][0], + prInfo->u4RxRateCnt[0][1], prInfo->u4RxRateRetryCnt[0][1], + prInfo->u4RxRateCnt[0][2], prInfo->u4RxRateRetryCnt[0][2], + prInfo->u4RxRateCnt[0][3], prInfo->u4RxRateRetryCnt[0][3], + prInfo->u4RxRateCnt[0][4], prInfo->u4RxRateRetryCnt[0][4], + prInfo->u4RxRateCnt[0][5], prInfo->u4RxRateRetryCnt[0][5], + prInfo->u4RxRateCnt[0][6], prInfo->u4RxRateRetryCnt[0][6], + prInfo->u4RxRateCnt[0][7], prInfo->u4RxRateRetryCnt[0][7], + prInfo->u4RxRateCnt[0][8], prInfo->u4RxRateRetryCnt[0][8], + prInfo->u4RxRateCnt[0][9], prInfo->u4RxRateRetryCnt[0][9], + prInfo->u4RxRateCnt[0][10], prInfo->u4RxRateRetryCnt[0][10], + prInfo->u4RxRateCnt[0][11], prInfo->u4RxRateRetryCnt[0][11], + prInfo->u4RxRateCnt[0][12], prInfo->u4RxRateRetryCnt[0][12], + prInfo->u4RxRateCnt[0][13], prInfo->u4RxRateRetryCnt[0][13], + prInfo->u4RxRateCnt[0][14], prInfo->u4RxRateRetryCnt[0][14], + prInfo->u4RxRateCnt[0][15], prInfo->u4RxRateRetryCnt[0][15])); + DBGLOG(RX, INFO, " ROFDM (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[1][0], prInfo->u4RxRateRetryCnt[1][0], + prInfo->u4RxRateCnt[1][1], prInfo->u4RxRateRetryCnt[1][1], + prInfo->u4RxRateCnt[1][2], prInfo->u4RxRateRetryCnt[1][2], + prInfo->u4RxRateCnt[1][3], prInfo->u4RxRateRetryCnt[1][3], + prInfo->u4RxRateCnt[1][4], prInfo->u4RxRateRetryCnt[1][4], + prInfo->u4RxRateCnt[1][5], prInfo->u4RxRateRetryCnt[1][5], + prInfo->u4RxRateCnt[1][6], prInfo->u4RxRateRetryCnt[1][6], + prInfo->u4RxRateCnt[1][7], prInfo->u4RxRateRetryCnt[1][7], + prInfo->u4RxRateCnt[1][8], prInfo->u4RxRateRetryCnt[1][8], + prInfo->u4RxRateCnt[1][9], prInfo->u4RxRateRetryCnt[1][9], + prInfo->u4RxRateCnt[1][10], prInfo->u4RxRateRetryCnt[1][10], + prInfo->u4RxRateCnt[1][11], prInfo->u4RxRateRetryCnt[1][11], + prInfo->u4RxRateCnt[1][12], prInfo->u4RxRateRetryCnt[1][12], + prInfo->u4RxRateCnt[1][13], prInfo->u4RxRateRetryCnt[1][13], + prInfo->u4RxRateCnt[1][14], prInfo->u4RxRateRetryCnt[1][14], + prInfo->u4RxRateCnt[1][15], prInfo->u4RxRateRetryCnt[1][15])); + DBGLOG(RX, INFO, " RHT (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n" + "(%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u) (%u %u)\n", + prInfo->u4RxRateCnt[2][0], prInfo->u4RxRateRetryCnt[2][0], + prInfo->u4RxRateCnt[2][1], prInfo->u4RxRateRetryCnt[2][1], + prInfo->u4RxRateCnt[2][2], prInfo->u4RxRateRetryCnt[2][2], + prInfo->u4RxRateCnt[2][3], prInfo->u4RxRateRetryCnt[2][3], + prInfo->u4RxRateCnt[2][4], prInfo->u4RxRateRetryCnt[2][4], + prInfo->u4RxRateCnt[2][5], prInfo->u4RxRateRetryCnt[2][5], + prInfo->u4RxRateCnt[2][6], prInfo->u4RxRateRetryCnt[2][6], + prInfo->u4RxRateCnt[2][7], prInfo->u4RxRateRetryCnt[2][7], + prInfo->u4RxRateCnt[2][8], prInfo->u4RxRateRetryCnt[2][8], + prInfo->u4RxRateCnt[2][9], prInfo->u4RxRateRetryCnt[2][9], + prInfo->u4RxRateCnt[2][10], prInfo->u4RxRateRetryCnt[2][10], + prInfo->u4RxRateCnt[2][11], prInfo->u4RxRateRetryCnt[2][11], + prInfo->u4RxRateCnt[2][12], prInfo->u4RxRateRetryCnt[2][12], + prInfo->u4RxRateCnt[2][13], prInfo->u4RxRateRetryCnt[2][13], + prInfo->u4RxRateCnt[2][14], prInfo->u4RxRateRetryCnt[2][14], + prInfo->u4RxRateCnt[2][15], prInfo->u4RxRateRetryCnt[2][15])); + + /* delay from HIF to MAC */ + DBGLOG(RX, INFO, " StayIntH2M us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinH2M[0], prInfo->u4StayIntAvgH2M[0], + prInfo->u4StayIntMaxH2M[0], + prInfo->u4StayIntMinH2M[1], prInfo->u4StayIntAvgH2M[1], + prInfo->u4StayIntMaxH2M[1], + prInfo->u4StayIntMinH2M[2], prInfo->u4StayIntAvgH2M[2], + prInfo->u4StayIntMaxH2M[2])); + /* delay from MAC to TXDONE */ + DBGLOG(RX, INFO, " AirTime us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4AirDelayMin[0] << 5, prInfo->u4AirDelayAvg[0] << 5, + prInfo->u4AirDelayMax[0] << 5, + prInfo->u4AirDelayMin[1] << 5, prInfo->u4AirDelayAvg[1] << 5, + prInfo->u4AirDelayMax[1] << 5, + prInfo->u4TxDataCntAll, (prInfo->u4AirDelayAvg[2] << 5) / (prInfo->u4TxDataCntAll), + (prInfo->u4AirDelayAvg[2] << 5) / 400000)); + prAdapter->u4AirDelayTotal = (prInfo->u4AirDelayTotal << 5) / 400000; + /* delay from HIF to TXDONE */ + DBGLOG(RX, INFO, " StayInt us (%u %u %u_%u) (%u %u %u_%u) (%u %u %u_%u)\n", + prInfo->u4StayIntMin[0], prInfo->u4StayIntAvg[0], + prInfo->u4StayIntMax[0], prInfo->u4StayIntMaxSysTime[0], + prInfo->u4StayIntMin[1], prInfo->u4StayIntAvg[1], + prInfo->u4StayIntMax[1], prInfo->u4StayIntMaxSysTime[1], + prInfo->u4StayIntMin[2], prInfo->u4StayIntAvg[2], + prInfo->u4StayIntMax[2], prInfo->u4StayIntMaxSysTime[2])); + /* delay from Driver to TXDONE */ + DBGLOG(RX, INFO, " StayIntD2T us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinD2T[0], prInfo->u4StayIntAvgD2T[0], + prInfo->u4StayIntMaxD2T[0], + prInfo->u4StayIntMinD2T[1], prInfo->u4StayIntAvgD2T[1], + prInfo->u4StayIntMaxD2T[1], + prInfo->u4StayIntMinD2T[2], prInfo->u4StayIntAvgD2T[2], + prInfo->u4StayIntMaxD2T[2])); + + /* delay from RXDONE to HIF */ + DBGLOG(RX, INFO, " StayIntR_M2H us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prInfo->u4StayIntMinRx[0], prInfo->u4StayIntAvgRx[0], + prInfo->u4StayIntMaxRx[0], + prInfo->u4StayIntMinRx[1], prInfo->u4StayIntAvgRx[1], + prInfo->u4StayIntMaxRx[1], + prInfo->u4StayIntMinRx[2], prInfo->u4StayIntAvgRx[2], prInfo->u4StayIntMaxRx[2])); + /* delay from HIF to OS */ + DBGLOG(RX, INFO, " StayIntR_H2D us (%u %u %u) (%u %u %u) (%u %u %u)\n", + prStaRec->u4StayIntMinRx[0], prStaRec->u4StayIntAvgRx[0], + prStaRec->u4StayIntMaxRx[0], + prStaRec->u4StayIntMinRx[1], prStaRec->u4StayIntAvgRx[1], + prStaRec->u4StayIntMaxRx[1], + prStaRec->u4StayIntMinRx[2], prStaRec->u4StayIntAvgRx[2], + prStaRec->u4StayIntMaxRx[2])); + + /* count based on delay from OS to HIF */ + DBGLOG(RX, INFO, " StayCntD2H unit:%dms (%d %d %d %d)\n", + STATS_STAY_INT_D2H_CONST, + prInfo->u4StayIntD2HByConst[0], prInfo->u4StayIntD2HByConst[1], + prInfo->u4StayIntD2HByConst[2], prInfo->u4StayIntD2HByConst[3]); + + /* count based on different delay from HIF to TX DONE */ + DBGLOG(RX, INFO, " StayCnt unit:%dms (%d %d %d %d)\n", + STATS_STAY_INT_CONST, + prInfo->u4StayIntByConst[0], prInfo->u4StayIntByConst[1], + prInfo->u4StayIntByConst[2], prInfo->u4StayIntByConst[3]); + DBGLOG(RX, INFO, " StayCnt (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~%d:%d) (%d~:%d)\n", + 0, prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntCnt[0], + prInfo->u4StayIntMaxPast / 4, prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntCnt[1], + prInfo->u4StayIntMaxPast / 2, prInfo->u4StayIntMaxPast * 3 / 4, + prInfo->u4StayIntCnt[2], prInfo->u4StayIntMaxPast * 3 / 4, prInfo->u4StayIntMaxPast, + prInfo->u4StayIntCnt[3], prInfo->u4StayIntMaxPast, prInfo->u4StayIntCnt[4])); + + /* channel idle time */ + DBGLOG(RX, INFO, " Idle Time (slot): (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u) (%u)\n", + prInfo->au4ChanIdleCnt[0], prInfo->au4ChanIdleCnt[1], + prInfo->au4ChanIdleCnt[2], prInfo->au4ChanIdleCnt[3], + prInfo->au4ChanIdleCnt[4], prInfo->au4ChanIdleCnt[5], + prInfo->au4ChanIdleCnt[6], prInfo->au4ChanIdleCnt[7], + prInfo->au4ChanIdleCnt[8], prInfo->au4ChanIdleCnt[9])); + + /* BT coex */ + DBGLOG(RX, INFO, " BT coex (0x%x)\n", prInfo->u4BtContUseTime); + + /* others */ + DBGLOG(RX, INFO, " OTHER (%u) (%u) (%u) (%u) (%u) (%ums) (%uus)\n", + prInfo->u4RxFifoFullCnt, prAdapter->ucScanTime, + prInfo->u4NumOfChanChange, prStaRec->u4NumOfNoTxQuota, + prInfo->ucNumOfPsChange, prInfo->u4PsIntMax, u4DrvOwnMax / 1000); + + /* reset */ + kalMemZero(prStaRec->u4StayIntMinRx, sizeof(prStaRec->u4StayIntMinRx)); + kalMemZero(prStaRec->u4StayIntAvgRx, sizeof(prStaRec->u4StayIntAvgRx)); + kalMemZero(prStaRec->u4StayIntMaxRx, sizeof(prStaRec->u4StayIntMaxRx)); + prStaRec->u4StatsRxPassToOsCnt = 0; + prStaRec->u4RxReorderFallAheadCnt = 0; + prStaRec->u4RxReorderFallBehindCnt = 0; + prStaRec->u4RxReorderHoleCnt = 0; + } + + STATS_DRIVER_OWN_RESET(); +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to request firmware to feedback statistics. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +statsInfoEnvRequest(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + STATS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* sanity check */ + if (fgIsUnderSuspend == true) + return WLAN_STATUS_SUCCESS; /* do not request stats after early suspend */ + + /* init command buffer */ + prCmdContent = (STATS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = STATS_CORE_CMD_ENV_REQUEST; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_STATS, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(STATS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(RX, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return WLAN_STATUS_RESOURCES; + } + + DBGLOG(RX, INFO, "%s cmd ok.\n", __func__); + return WLAN_STATUS_SUCCESS; +} + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle any statistics event. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID statsEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + UINT32 u4EventId; + + /* sanity check */ +/* DBGLOG(RX, INFO, */ +/* (" %s: Rcv a event\n", __FUNCTION__)); */ + + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(UINT32 *) prInBuf; + u4InBufLen -= 4; + +/* DBGLOG(RX, INFO, */ +/* (" %s: Rcv a event: %d\n", __FUNCTION__, u4EventId)); */ + + switch (u4EventId) { + case STATS_HOST_EVENT_ENV_REPORT: + statsInfoEnvDisplay(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to detect if we can request firmware to feedback statistics. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] ucStaRecIndex The station index +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID statsEnvReportDetect(ADAPTER_T *prAdapter, UINT8 ucStaRecIndex) +{ + STA_RECORD_T *prStaRec; + OS_SYSTIME rCurTime; + STATS_CMD_CORE_T rCmd; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if (prStaRec == NULL) + return; + + prStaRec->u4StatsEnvTxCnt++; + GET_CURRENT_SYSTIME(&rCurTime); + + if (prStaRec->rStatsEnvTxPeriodLastTime == 0) { + prStaRec->rStatsEnvTxLastTime = rCurTime; + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + return; + } + + if (prStaRec->u4StatsEnvTxCnt > STATS_ENV_TX_CNT_REPORT_TRIGGER) { + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxLastTime, + SEC_TO_SYSTIME(STATS_ENV_TX_CNT_REPORT_TRIGGER_SEC))) { + rCmd.ucStaRecIdx = ucStaRecIndex; + statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); + + prStaRec->rStatsEnvTxLastTime = rCurTime; + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + prStaRec->u4StatsEnvTxCnt = 0; + return; + } + } + + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rStatsEnvTxPeriodLastTime, SEC_TO_SYSTIME(STATS_ENV_TIMEOUT_SEC))) { + rCmd.ucStaRecIdx = ucStaRecIndex; + statsInfoEnvRequest(prAdapter, &rCmd, 0, NULL); + + prStaRec->rStatsEnvTxPeriodLastTime = rCurTime; + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prStaRec Pointer to the STA_RECORD_T structure +* \param[in] prSwRfb Pointer to the received packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsEnvRxDone(STA_RECORD_T *prStaRec, SW_RFB_T *prSwRfb) +{ + UINT32 u4LenId; + UINT32 u4CurTime, u4DifTime; + + /* sanity check */ + if (prStaRec == NULL) + return; + + /* stats: rx done count */ + prStaRec->u4StatsRxPassToOsCnt++; + + /* get length partition ID */ + u4LenId = 0; + if (prSwRfb->u2PacketLen < STATS_STAY_INT_BYTE_THRESHOLD) { + u4LenId = 0; + } else { + if ((STATS_STAY_INT_BYTE_THRESHOLD <= prSwRfb->u2PacketLen) && + (prSwRfb->u2PacketLen < (STATS_STAY_INT_BYTE_THRESHOLD << 1))) { + u4LenId = 1; + } else + u4LenId = 2; + } + + /* stats: rx delay */ + u4CurTime = kalGetTimeTick(); + + if ((u4CurTime > prSwRfb->rRxTime) && (prSwRfb->rRxTime != 0)) { + u4DifTime = u4CurTime - prSwRfb->rRxTime; + + if (prStaRec->u4StayIntMinRx[u4LenId] == 0) /* impossible */ + prStaRec->u4StayIntMinRx[u4LenId] = 0xffffffff; + + if (u4DifTime > prStaRec->u4StayIntMaxRx[u4LenId]) + prStaRec->u4StayIntMaxRx[u4LenId] = u4DifTime; + else if (u4DifTime < prStaRec->u4StayIntMinRx[u4LenId]) + prStaRec->u4StayIntMinRx[u4LenId] = u4DifTime; + + prStaRec->u4StayIntAvgRx[u4LenId] += u4DifTime; + if (prStaRec->u4StayIntAvgRx[u4LenId] != u4DifTime) + prStaRec->u4StayIntAvgRx[u4LenId] >>= 1; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +UINT_64 StatsEnvTimeGet(VOID) +{ + /* TODO: use better API to get time to save time, jiffies unit is 10ms, too large */ + +/* struct timeval tv; */ + +/* do_gettimeofday(&tv); */ +/* return tv.tv_usec + tv.tv_sec * (UINT_64)1000000; */ + + UINT_64 u8Clk; +/* UINT32 *pClk = &u8Clk; */ + + u8Clk = sched_clock(); /* unit: naro seconds */ +/* printk(" sched_clock() = %x %x %u\n", pClk[0], pClk[1], sizeof(jiffies)); */ + + return (UINT_64) u8Clk; /* sched_clock *//* jiffies size = 4B */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle rx done. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsEnvTxTime2Hif(MSDU_INFO_T *prMsduInfo, HIF_TX_HEADER_T *prHwTxHeader) +{ + UINT_64 u8SysTime, u8SysTimeIn; + UINT32 u4TimeDiff; + + u8SysTime = StatsEnvTimeGet(); + u8SysTimeIn = GLUE_GET_PKT_XTIME(prMsduInfo->prPacket); + +/* printk(" hif: 0x%x %u %u %u\n", */ +/* prMsduInfo->prPacket, StatsEnvTimeGet(), u8SysTime, GLUE_GET_PKT_XTIME(prMsduInfo->prPacket)); */ + + if ((u8SysTimeIn > 0) && (u8SysTime > u8SysTimeIn)) { + u8SysTime = u8SysTime - u8SysTimeIn; + u4TimeDiff = (UINT32) u8SysTime; + u4TimeDiff = u4TimeDiff / 1000; /* ns to us */ + + /* pass the delay between OS to us and we to HIF */ + if (u4TimeDiff > 0xFFFF) + *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) 0xFFFF; /* 65535 us */ + else + *(UINT16 *) prHwTxHeader->aucReserved = (UINT16) u4TimeDiff; + +/* printk(" u4TimeDiff: %u\n", u4TimeDiff); */ + } else { + prHwTxHeader->aucReserved[0] = 0; + prHwTxHeader->aucReserved[1] = 0; + } +} + +static VOID statsParsePktInfo(PUINT_8 pucPkt, UINT_8 status, UINT_8 eventType, P_MSDU_INFO_T prMsduInfo) +{ + /* get ethernet protocol */ + UINT_16 u2EtherType = (pucPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pucPkt[ETH_TYPE_LEN_OFFSET + 1]); + PUINT_8 pucEthBody = &pucPkt[ETH_HLEN]; + + switch (u2EtherType) { + case ETH_P_ARP: + { + UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + if (eventType == EVENT_TX) + prMsduInfo->fgIsBasicRate = TRUE; + + if ((su2TxDoneCfg & CFG_ARP) == 0) + break; + + switch (eventType) { + case EVENT_RX: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(RX, INFO, " Arp Req From IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(RX, INFO, " Arp Rsp from IP: %d.%d.%d.%d\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + break; + case EVENT_TX: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(TX, INFO, " Arp Req to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(TX, INFO, " Arp Rsp to IP: %d.%d.%d.%d\n", + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(TX, INFO, " Arp Req to IP: %d.%d.%d.%d\n", status, + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(TX, INFO, " Arp Rsp to IP: %d.%d.%d.%d\n", status, + pucEthBody[24], pucEthBody[25], pucEthBody[26], pucEthBody[27]); + break; + } + break; + } + case ETH_P_IP: + { + UINT_8 ucIpProto = pucEthBody[9]; /* IP header without options */ + UINT_8 ucIpVersion = (pucEthBody[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + UINT_16 u2IpId = pucEthBody[4]<<8 | pucEthBody[5]; + + if (ucIpVersion != IPVERSION) + break; + + switch (ucIpProto) { + case IP_PRO_ICMP: + { + /* the number of ICMP packets is seldom so we print log here */ + UINT_8 ucIcmpType; + UINT_16 u2IcmpId, u2IcmpSeq; + PUINT_8 pucIcmp = &pucEthBody[20]; + + ucIcmpType = pucIcmp[0]; + /* don't log network unreachable packet */ + if (((su2TxDoneCfg & CFG_ICMP) == 0) || ucIcmpType == 3) + break; + u2IcmpId = *(UINT_16 *) &pucIcmp[4]; + u2IcmpSeq = *(UINT_16 *) &pucIcmp[6]; + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " ICMP: Type %d, Id BE 0x%04x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " ICMP: Type %d, Id 0x04%x, Seq BE 0x%04x\n", + ucIcmpType, u2IcmpId, u2IcmpSeq); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " Type %d, Id 0x%04x, Seq 0x%04x\n", + status, ucIcmpType, u2IcmpId, u2IcmpSeq); + break; + } + break; + } + case IP_PRO_UDP: + { + /* the number of DHCP packets is seldom so we print log here */ + PUINT_8 pucUdp = &pucEthBody[20]; + PUINT_8 pucUdpPayload = &pucUdp[8]; + UINT_16 u2UdpDstPort; + UINT_16 u2UdpSrcPort; + + u2UdpDstPort = (pucUdp[2] << 8) | pucUdp[3]; + u2UdpSrcPort = (pucUdp[0] << 8) | pucUdp[1]; + /* dhcp */ + if ((u2UdpDstPort == UDP_PORT_DHCPS) || (u2UdpDstPort == UDP_PORT_DHCPC)) { + UINT_32 u4TransID = pucUdpPayload[4]<<24 | pucUdpPayload[5]<<16 | + pucUdpPayload[6]<<8 | pucUdpPayload[7]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + u2IpId, pucUdpPayload[0], u4TransID); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + u2IpId, pucUdpPayload[0], u4TransID); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + prMsduInfo->fgIsBasicRate = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, + " DHCP: IPID 0x%02x, MsgType 0x%x, TransID 0x%08x\n", + status, u2IpId, pucUdpPayload[0], u4TransID); + break; + } + } else if (u2UdpDstPort == UDP_PORT_DNS) { /* tx dns */ + UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; + if (eventType == EVENT_TX) + prMsduInfo->fgIsBasicRate = TRUE; + + if ((su2TxDoneCfg & CFG_DNS) == 0) + break; + if (eventType == EVENT_TX) { + DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + } else if (eventType == EVENT_TX_DONE) + DBGLOG(TX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", + status, u2IpId, u2TransId); + } else if (u2UdpSrcPort == UDP_PORT_DNS && eventType == EVENT_RX) { /* rx dns */ + UINT_16 u2TransId = (pucUdpPayload[0] << 8) | pucUdpPayload[1]; + + if ((su2TxDoneCfg & CFG_DNS) == 0) + break; + DBGLOG(RX, INFO, " DNS: IPID 0x%02x, TransID 0x%04x\n", u2IpId, u2TransId); + } else if ((su2TxDoneCfg & CFG_UDP) != 0) { + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " UDP: IPID 0x%04x\n", u2IpId); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", u2IpId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " UDP: IPID 0x%04x\n", status, u2IpId); + break; + } + } + break; + } + case IP_PRO_TCP: + if ((su2TxDoneCfg & CFG_TCP) == 0) + break; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " TCP: IPID 0x%04x\n", u2IpId); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", u2IpId); + prMsduInfo->fgNeedTxDoneStatus = TRUE; + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " TCP: IPID 0x%04x\n", status, u2IpId); + break; + } + break; + } + break; + } + case ETH_P_PRE_1X: + DBGLOG(RX, INFO, "pre-1x\n"); + case ETH_P_1X: + { + PUINT_8 pucEapol = pucEthBody; + UINT_8 ucEapolType = pucEapol[1]; + + switch (ucEapolType) { + case 0: /* eap packet */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", + pucEapol[4], pucEapol[5], pucEapol[7]); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d\n", + status, pucEapol[4], pucEapol[5], pucEapol[7]); + break; + } + break; + case 1: /* eapol start */ + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " EAPOL: start\n"); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " EAPOL: start\n"); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " EAPOL: start\n", status); + break; + } + break; + case 3: /* key */ + { + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + break; + case EVENT_TX: + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + u2KeyInfo, + pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x...\n", + status, u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], + pucEapol[20], pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24]); + break; + } + + break; + } + } + break; + } + case ETH_WPI_1X: + { + UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ + UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; + UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; + + switch (eventType) { + case EVENT_RX: + DBGLOG(RX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX: + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + break; + case EVENT_TX_DONE: + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + status, ucSubType, u2Length, u2Seq); + break; + } + break; + } + } +} +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display rx packet information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsRxPktInfoDisplay(UINT_8 *pPkt) +{ + statsParsePktInfo(pPkt, 0, EVENT_RX, NULL); +#if 0 /* carefully! too many ARP */ + if (pucIpHdr[0] == 0x00) { /* ARP */ + UINT_8 *pucDstIp = (UINT_8 *) pucIpHdr; + + if (pucDstIp[7] == ARP_PRO_REQ) { + DBGLOG(RX, TRACE, " OS rx a arp req from %d.%d.%d.%d\n", + pucDstIp[14], pucDstIp[15], pucDstIp[16], pucDstIp[17]); + } else if (pucDstIp[7] == ARP_PRO_RSP) { + DBGLOG(RX, TRACE, " OS rx a arp rsp from %d.%d.%d.%d\n", + pucDstIp[24], pucDstIp[25], pucDstIp[26], pucDstIp[27]); + } + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display tx packet information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsTxPktCallBack(UINT_8 *pPkt, P_MSDU_INFO_T prMsduInfo) +{ + UINT_16 u2EtherTypeLen; + + u2EtherTypeLen = (pPkt[ETH_TYPE_LEN_OFFSET] << 8) | (pPkt[ETH_TYPE_LEN_OFFSET + 1]); + statsParsePktInfo(pPkt, 0, EVENT_TX, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to handle display tx packet tx done information. +* +* \param[in] pPkt Pointer to the packet +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID StatsTxPktDoneInfoDisplay(ADAPTER_T *prAdapter, UINT_8 *pucEvtBuf) +{ + EVENT_TX_DONE_STATUS_T *prTxDone; + + prTxDone = (EVENT_TX_DONE_STATUS_T *) pucEvtBuf; + /* + * Why 65 Bytes: + * 8B + wlanheader(40B) + hif_tx_header(16B) + 6B + 6B(LLC) - 12B + */ + statsParsePktInfo(&prTxDone->aucPktBuf[64], prTxDone->ucStatus, EVENT_TX_DONE, NULL); +} + +VOID StatsSetCfgTxDone(UINT_16 u2Cfg, BOOLEAN fgSet) +{ + if (fgSet) + su2TxDoneCfg |= u2Cfg; + else + su2TxDoneCfg &= ~u2Cfg; +} + +UINT_16 StatsGetCfgTxDone(VOID) +{ + return su2TxDoneCfg; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c new file mode 100644 index 0000000000000..67eccbda9fa8f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/swcr.c @@ -0,0 +1,1170 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/swcr.c#1 +*/ + +/*! \file "swcr.c" + \brief + +*/ + +/* +** Log: swcr.c + * + * 06 04 2012 tsaiyuan.hsu + * [WCXRP00001249] [ALPS.ICS] Daily build warning on "wlan/mgmt/swcr.c#1" + * resolve build waring for "WNM_UNIT_TEST not defined". + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 22 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * keep debug counter setting after wake up. + * + * 11 15 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * fix debug counters of rx in driver. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters, eCurPsProf, for PS. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 08 31 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * remove obsolete code. + * + * 08 15 2011 tsaiyuan.hsu + * [WCXRP00000931] [MT5931 Wi-Fi][DRV/FW] add swcr to disable roaming from driver + * add swcr in driver reg, 0x9fxx0000, to disable roaming . + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 03 28 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Fix Klockwork warning. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add swcr for test. + * +* +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_SWCR + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if 0 +SWCR_MOD_MAP_ENTRY_T g_arSwCrAllMaps[] = { + {SWCR_MAP_NUM(g_arRlmArSwCrMap), g_arRlmArSwCrMap}, /* 0x00nn */ + {0, NULL} +}; +#endif + +UINT_32 g_au4SwCr[SWCR_CR_NUM]; /*: 0: command other: data */ + +/* JB mDNS Filter*/ +UINT_32 g_u4mDNSRXFilter = 0; /* [31] 0: stop 1: start, [3] IPv6 [2] IPv4 */ + +static TIMER_T g_rSwcrDebugTimer; +static BOOLEAN g_fgSwcrDebugTimer = FALSE; +static UINT_32 g_u4SwcrDebugCheckTimeout; +static ENUM_SWCR_DBG_TYPE_T g_ucSwcrDebugCheckType; +static UINT_32 g_u4SwcrDebugFrameDumpType; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#define TEST_PS 1 + +static const PFN_CMD_RW_T g_arSwCtrlCmd[] = { + swCtrlCmdCategory0, + swCtrlCmdCategory1 +#if TEST_PS + , testPsCmdCategory0, testPsCmdCategory1 +#endif +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) + , testWNMCmdCategory0 +#endif +#endif +}; + +const PFN_SWCR_RW_T g_arSwCrModHandle[] = { + swCtrlSwCr, + NULL +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +enum { + SWCTRL_MAGIC, + SWCTRL_DEBUG, + SWCTRL_WIFI_VAR, + SWCTRL_ENABLE_INT, + SWCTRL_DISABLE_INT, + SWCTRL_TXM_INFO, + SWCTRL_RXM_INFO, + SWCTRL_DUMP_BSS, + SWCTRL_QM_INFO, + SWCTRL_DUMP_ALL_QUEUE_LEN, + SWCTRL_DUMP_MEM, + SWCTRL_TX_CTRL_INFO, + SWCTRL_DUMP_QUEUE, + SWCTRL_DUMP_QM_DBG_CNT, + SWCTRL_QM_DBG_CNT, + SWCTRL_RX_PKTS_DUMP, + SWCTRL_RX_MDNS_FILTER, + SWCTRL_CATA0_INDEX_NUM +}; + +enum { + SWCTRL_STA_INFO, + SWCTRL_DUMP_STA, + SWCTRL_STA_QUE_INFO, + SWCTRL_CATA1_INDEX_NUM +}; + +/* JB mDNS Filter*/ +#define RX_MDNS_FILTER_START (1<<31) +#define RX_MDNS_FILTER_IPV4 (1<<2) +#define RX_MDNS_FILTER_IPV6 (1<<3) +typedef enum _ENUM_SWCR_RX_MDNS_FILTER_CMD_T { + SWCR_RX_MDNS_FILTER_CMD_STOP = 0, + SWCR_RX_MDNS_FILTER_CMD_START, + SWCR_RX_MDNS_FILTER_CMD_ADD, + SWCR_RX_MDNS_FILTER_CMD_REMOVE, + SWCR_RX_MDNS_FILTER_NUM +} ENUM_SWCR_RX_MDNS_FILTER_CMD_T; + +#if TEST_PS +enum { + TEST_PS_MAGIC, + TEST_PS_SETUP_BSS, + TEST_PS_ENABLE_BEACON, + TEST_PS_TRIGGER_BMC, + TEST_PS_SEND_NULL, + TEST_PS_BUFFER_BMC, + TEST_PS_UPDATE_BEACON, + TEST_PS_CATA0_INDEX_NUM +}; + +enum { + TEST_PS_STA_PS, + TEST_PS_STA_ENTER_PS, + TEST_PS_STA_EXIT_PS, + TEST_PS_STA_TRIGGER_PSPOLL, + TEST_PS_STA_TRIGGER_FRAME, + TEST_PS_CATA1_INDEX_NUM +}; +#endif + +#if CFG_SUPPORT_802_11V +#if WNM_UNIT_TEST +enum { + TEST_WNM_TIMING_MEAS, + TEST_WNM_CATA0_INDEX_NUM +}; +#endif +#endif + +#define _SWCTRL_MAGIC 0x66201642 + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +void dumpQueue(P_ADAPTER_T prAdapter) +{ + + P_TX_CTRL_T prTxCtrl; + P_QUE_MGT_T prQM; + P_GLUE_INFO_T prGlueInfo; + UINT_32 i; + UINT_32 j; + + DEBUGFUNC("dumpQueue"); + + prTxCtrl = &prAdapter->rTxCtrl; + prQM = &prAdapter->rQM; + prGlueInfo = prAdapter->prGlueInfo; + + for (i = TC0_INDEX; i <= TC5_INDEX; i++) { + DBGLOG(SW4, INFO, "TC %u\n", i); + DBGLOG(SW4, INFO, "Max %u Free %u\n", + prTxCtrl->rTc.aucMaxNumOfBuffer[i], prTxCtrl->rTc.aucFreeBufferCount[i]); + + DBGLOG(SW4, INFO, "Average %u minReserved %u CurrentTcResource %u GuaranteedTcResource %u\n", + QM_GET_TX_QUEUE_LEN(prAdapter, i), + prQM->au4MinReservedTcResource[i], + prQM->au4CurrentTcResource[i], prQM->au4GuaranteedTcResource[i]); + + } + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + DBGLOG(SW4, INFO, + "TC %u HeadStaIdx %u ForwardCount %u\n", i, prQM->au4HeadStaRecIndex[i], + prQM->au4ForwardCount[i]); + } + + DBGLOG(SW4, INFO, "BMC or unknown TxQueue Len %u\n", prQM->arTxQueue[0].u4NumElem); + DBGLOG(SW4, INFO, "Pending %d\n", prGlueInfo->i4TxPendingFrameNum); + DBGLOG(SW4, INFO, "Pending Security %d\n", prGlueInfo->i4TxPendingSecurityFrameNum); +#if defined(LINUX) + for (i = 0; i < 4; i++) { + for (j = 0; j < CFG_MAX_TXQ_NUM; j++) { + DBGLOG(SW4, INFO, + "Pending Q[%u][%u] %d\n", i, j, prGlueInfo->ai4TxPendingFrameNumPerQueue[i][j]); + } + } +#endif + + DBGLOG(SW4, INFO, " rFreeSwRfbList %u\n", prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + DBGLOG(SW4, INFO, " rReceivedRfbList %u\n", prAdapter->rRxCtrl.rReceivedRfbList.u4NumElem); + DBGLOG(SW4, INFO, " rIndicatedRfbList %u\n", prAdapter->rRxCtrl.rIndicatedRfbList.u4NumElem); + DBGLOG(SW4, INFO, " ucNumIndPacket %u\n", prAdapter->rRxCtrl.ucNumIndPacket); + DBGLOG(SW4, INFO, " ucNumRetainedPacket %u\n", prAdapter->rRxCtrl.ucNumRetainedPacket); + +} + +void dumpSTA(P_ADAPTER_T prAdapter, P_STA_RECORD_T prStaRec) +{ + UINT_8 ucWTEntry; + UINT_32 i; + P_BSS_INFO_T prBssInfo; + + DEBUGFUNC("dumpSTA"); + + ASSERT(prStaRec); + ucWTEntry = prStaRec->ucWTEntry; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + DBGLOG(SW4, INFO, "Mac address: %pM Rcpi %u" "\n", prStaRec->aucMacAddr, prStaRec->ucRCPI); + + DBGLOG(SW4, INFO, "Idx %u Wtbl %u Used %u State %u Bss Phy 0x%x Sta DesiredPhy 0x%x\n", + prStaRec->ucIndex, ucWTEntry, + prStaRec->fgIsInUse, prStaRec->ucStaState, + prBssInfo->ucPhyTypeSet, prStaRec->ucDesiredPhyTypeSet); + + DBGLOG(SW4, INFO, "Sta Operation 0x%x DesiredNontHtRateSet 0x%x Mcs 0x%x u2HtCapInfo 0x%x\n", + prStaRec->u2OperationalRateSet, prStaRec->u2DesiredNonHTRateSet, prStaRec->ucMcsSet, + prStaRec->u2HtCapInfo); + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) + DBGLOG(SW4, INFO, "TC %u Queue Len %u\n", i, prStaRec->arTxQueue[i].u4NumElem); + + DBGLOG(SW4, INFO, "BmpDeliveryAC %x\n", prStaRec->ucBmpDeliveryAC); + DBGLOG(SW4, INFO, "BmpTriggerAC %x\n", prStaRec->ucBmpTriggerAC); + DBGLOG(SW4, INFO, "UapsdSpSupproted %u\n", prStaRec->fgIsUapsdSupported); + DBGLOG(SW4, INFO, "IsQoS %u\n", prStaRec->fgIsQoS); + DBGLOG(SW4, INFO, "AssocId %u\n", prStaRec->u2AssocId); + + DBGLOG(SW4, INFO, "fgIsInPS %u\n", prStaRec->fgIsInPS); + DBGLOG(SW4, INFO, "ucFreeQuota %u\n", prStaRec->ucFreeQuota); + DBGLOG(SW4, INFO, "ucFreeQuotaForDelivery %u\n", prStaRec->ucFreeQuotaForDelivery); + DBGLOG(SW4, INFO, "ucFreeQuotaForNonDelivery %u\n", prStaRec->ucFreeQuotaForNonDelivery); + +#if 0 + DBGLOG(SW4, INFO, "IsQmmSup %u\n", prStaRec->fgIsWmmSupported); + DBGLOG(SW4, INFO, "IsUapsdSup %u\n", prStaRec->fgIsUapsdSupported); + DBGLOG(SW4, INFO, "AvailabaleDeliverPkts %u\n", prStaRec->ucAvailableDeliverPkts); + DBGLOG(SW4, INFO, "BmpDeliverPktsAC %u\n", prStaRec->u4BmpDeliverPktsAC); + DBGLOG(SW4, INFO, "BmpBufferAC %u\n", prStaRec->u4BmpBufferAC); + DBGLOG(SW4, INFO, "BmpNonDeliverPktsAC %u\n", prStaRec->u4BmpNonDeliverPktsAC); +#endif + + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + if (prStaRec->aprRxReorderParamRefTbl[i]) { + DBGLOG(SW4, INFO, + "RxReorder fgIsValid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->fgIsValid); + DBGLOG(SW4, INFO, "RxReorder Tid: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->ucTid); + DBGLOG(SW4, INFO, + "RxReorder rReOrderQue Len: %u\n", + prStaRec->aprRxReorderParamRefTbl[i]->rReOrderQue.u4NumElem); + DBGLOG(SW4, INFO, + "RxReorder WinStart: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinStart); + DBGLOG(SW4, INFO, "RxReorder WinEnd: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinEnd); + DBGLOG(SW4, INFO, "RxReorder WinSize: %u\n", prStaRec->aprRxReorderParamRefTbl[i]->u2WinSize); + } + } + +} + +VOID dumpBss(P_ADAPTER_T prAdapter, P_BSS_INFO_T prBssInfo) +{ + + DBGLOG(SW4, INFO, "SSID %s\n", prBssInfo->aucSSID); + DBGLOG(SW4, INFO, "OWN %pM\n", prBssInfo->aucOwnMacAddr); + DBGLOG(SW4, INFO, "BSSID %pM\n", prBssInfo->aucBSSID); + DBGLOG(SW4, INFO, "ucNetTypeIndex %u\n", prBssInfo->ucNetTypeIndex); + DBGLOG(SW4, INFO, "eConnectionState %u\n", prBssInfo->eConnectionState); + DBGLOG(SW4, INFO, "eCurrentOPMode %u\n", prBssInfo->eCurrentOPMode); + DBGLOG(SW4, INFO, "fgIsQBSS %u\n", prBssInfo->fgIsQBSS); + DBGLOG(SW4, INFO, "fgIsShortPreambleAllowed %u\n", prBssInfo->fgIsShortPreambleAllowed); + DBGLOG(SW4, INFO, "fgUseShortPreamble %u\n", prBssInfo->fgUseShortPreamble); + DBGLOG(SW4, INFO, "fgUseShortSlotTime %u\n", prBssInfo->fgUseShortSlotTime); + DBGLOG(SW4, INFO, "ucNonHTBasicPhyType %x\n", prBssInfo->ucNonHTBasicPhyType); + DBGLOG(SW4, INFO, "u2OperationalRateSet %x\n", prBssInfo->u2OperationalRateSet); + DBGLOG(SW4, INFO, "u2BSSBasicRateSet %x\n", prBssInfo->u2BSSBasicRateSet); + DBGLOG(SW4, INFO, "ucPhyTypeSet %x\n", prBssInfo->ucPhyTypeSet); + DBGLOG(SW4, INFO, "rStaRecOfClientList %d\n", prBssInfo->rStaRecOfClientList.u4NumElem); + DBGLOG(SW4, INFO, "u2CapInfo %x\n", prBssInfo->u2CapInfo); + DBGLOG(SW4, INFO, "u2ATIMWindow %x\n", prBssInfo->u2ATIMWindow); + DBGLOG(SW4, INFO, "u2AssocId %x\n", prBssInfo->u2AssocId); + DBGLOG(SW4, INFO, "ucDTIMPeriod %x\n", prBssInfo->ucDTIMPeriod); + DBGLOG(SW4, INFO, "ucDTIMCount %x\n", prBssInfo->ucDTIMCount); + DBGLOG(SW4, INFO, "fgIsNetAbsent %x\n", prBssInfo->fgIsNetAbsent); + DBGLOG(SW4, INFO, "eBand %d\n", prBssInfo->eBand); + DBGLOG(SW4, INFO, "ucPrimaryChannel %d\n", prBssInfo->ucPrimaryChannel); + DBGLOG(SW4, INFO, "ucHtOpInfo1 %d\n", prBssInfo->ucHtOpInfo1); + DBGLOG(SW4, INFO, "ucHtOpInfo2 %d\n", prBssInfo->u2HtOpInfo2); + DBGLOG(SW4, INFO, "ucHtOpInfo3 %d\n", prBssInfo->u2HtOpInfo3); + DBGLOG(SW4, INFO, "fgErpProtectMode %d\n", prBssInfo->fgErpProtectMode); + DBGLOG(SW4, INFO, "eHtProtectMode %d\n", prBssInfo->eHtProtectMode); + DBGLOG(SW4, INFO, "eGfOperationMode %d\n", prBssInfo->eGfOperationMode); + DBGLOG(SW4, INFO, "eRifsOperationMode %d\n", prBssInfo->eRifsOperationMode); + DBGLOG(SW4, INFO, "fgObssErpProtectMode %d\n", prBssInfo->fgObssErpProtectMode); + DBGLOG(SW4, INFO, "eObssHtProtectMode %d\n", prBssInfo->eObssHtProtectMode); + DBGLOG(SW4, INFO, "eObssGfProtectMode %d\n", prBssInfo->eObssGfOperationMode); + DBGLOG(SW4, INFO, "fgObssRifsOperationMode %d\n", prBssInfo->fgObssRifsOperationMode); + DBGLOG(SW4, INFO, "fgAssoc40mBwAllowed %d\n", prBssInfo->fgAssoc40mBwAllowed); + DBGLOG(SW4, INFO, "fg40mBwAllowed %d\n", prBssInfo->fg40mBwAllowed); + DBGLOG(SW4, INFO, "eBssSCO %d\n", prBssInfo->eBssSCO); + +} + +VOID swCtrlCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_32 i; + + DEBUGFUNC("swCtrlCmdCategory0"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + i = 0; + + if (ucIndex >= SWCTRL_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case SWCTRL_DEBUG: +#if DBG + aucDebugModule[ucOpt0] = (UINT_8) g_au4SwCr[1]; +#endif + break; + case SWCTRL_WIFI_VAR: + break; + +#if QM_DEBUG_COUNTER + case SWCTRL_DUMP_QM_DBG_CNT: + for (i = 0; i < QM_DBG_CNT_NUM; i++) + prAdapter->rQM.au4QmDebugCounters[i] = 0; + break; + case SWCTRL_QM_DBG_CNT: + prAdapter->rQM.au4QmDebugCounters[ucOpt0] = g_au4SwCr[1]; + + break; +#endif +#if CFG_RX_PKTS_DUMP + case SWCTRL_RX_PKTS_DUMP: + /* DBGLOG(SW4, INFO,("SWCTRL_RX_PKTS_DUMP: mask %x\n", g_au4SwCr[1])); */ + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = g_au4SwCr[1]; + break; +#endif + case SWCTRL_RX_MDNS_FILTER: + { + UINT_32 u4rxfilter; + BOOLEAN fgUpdate = FALSE; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_STOP) { + g_u4mDNSRXFilter &= ~(RX_MDNS_FILTER_START); + + u4rxfilter = prAdapter->u4OsPacketFilter; + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_START) { + g_u4mDNSRXFilter |= (RX_MDNS_FILTER_START); + + u4rxfilter = prAdapter->u4OsPacketFilter; + if ((g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV4) || + (g_u4mDNSRXFilter & RX_MDNS_FILTER_IPV6)) { + u4rxfilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } + fgUpdate = TRUE; + } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_ADD) { + if (ucOpt1 < 31) + g_u4mDNSRXFilter |= (1 << ucOpt1); + } else if (ucOpt0 == SWCR_RX_MDNS_FILTER_CMD_REMOVE) { + if (ucOpt1 < 31) + g_u4mDNSRXFilter &= ~(1 << ucOpt1); + } + + if (fgUpdate == TRUE) { + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SET_RX_FILTER, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, /* pfCmdDoneHandler */ + NULL, /* pfCmdTimeoutHandler */ + sizeof(UINT_32), /* u4SetQueryInfoLen */ + (PUINT_8)&u4rxfilter, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* un4SetQueryBufferLen */ + ); + } +/* DBGLOG(SW4, INFO,("SWCTRL_RX_MDNS_FILTER: g_u4mDNSRXFilter %x ucOpt0 %x ucOpt1 %x fgUpdate %x u4rxfilter %x, */ +/* rStatus %x\n", g_u4mDNSRXFilter, ucOpt0, ucOpt1, fgUpdate, u4rxfilter, rStatus)); */ + } + break; + default: + break; + } + } else { + switch (ucIndex) { + case SWCTRL_DEBUG: +#if DBG + g_au4SwCr[1] = aucDebugModule[ucOpt0]; +#endif + break; + case SWCTRL_MAGIC: + g_au4SwCr[1] = _SWCTRL_MAGIC; + /* DBGLOG(SW4, INFO, "BUILD TIME: %s %s\n", __DATE__, __TIME__); */ + break; + case SWCTRL_QM_INFO: + { + P_QUE_MGT_T prQM = &prAdapter->rQM; + + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = (QM_GET_TX_QUEUE_LEN(prAdapter, ucOpt1)); + g_au4SwCr[2] = prQM->au4MinReservedTcResource[ucOpt1]; + g_au4SwCr[3] = prQM->au4CurrentTcResource[ucOpt1]; + g_au4SwCr[4] = prQM->au4GuaranteedTcResource[ucOpt1]; + break; + + case 1: + g_au4SwCr[1] = prQM->au4ForwardCount[ucOpt1]; + g_au4SwCr[2] = prQM->au4HeadStaRecIndex[ucOpt1]; + break; + + case 2: + g_au4SwCr[1] = prQM->arTxQueue[ucOpt1].u4NumElem; /* only one */ + + break; + } + + } + break; + case SWCTRL_TX_CTRL_INFO: + { + P_TX_CTRL_T prTxCtrl; + + prTxCtrl = &prAdapter->rTxCtrl; + switch (ucOpt0) { + case 0: + g_au4SwCr[1] = prAdapter->rTxCtrl.rTc.aucFreeBufferCount[ucOpt1]; + g_au4SwCr[2] = prAdapter->rTxCtrl.rTc.aucMaxNumOfBuffer[ucOpt1]; + break; + } + + } + break; + case SWCTRL_DUMP_QUEUE: + dumpQueue(prAdapter); + + break; +#if QM_DEBUG_COUNTER + case SWCTRL_DUMP_QM_DBG_CNT: + for (i = 0; i < QM_DBG_CNT_NUM; i++) + DBGLOG(SW4, INFO, "QM:DBG %u %u\n", i, prAdapter->rQM.au4QmDebugCounters[i]); + break; + + case SWCTRL_QM_DBG_CNT: + g_au4SwCr[1] = prAdapter->rQM.au4QmDebugCounters[ucOpt0]; + break; +#endif + case SWCTRL_DUMP_BSS: + { + dumpBss(prAdapter, &(prAdapter->rWifiVar.arBssInfo[ucOpt0])); + } + break; + + default: + break; + } + + } +} + +VOID swCtrlCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("swCtrlCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + /* prStaRec = cnmGetStaRecByIndex (prAdapter, ucOpt0); */ + prStaRec = &prAdapter->arStaRec[ucOpt0]; + ucWTEntry = prStaRec->ucWTEntry; + if (ucRead == SWCR_WRITE) { + /* Do nothing */ + } else { + /* Read */ + switch (ucIndex) { + case SWCTRL_STA_QUE_INFO: + { + g_au4SwCr[1] = prStaRec->arTxQueue[ucOpt1].u4NumElem; + } + break; + case SWCTRL_STA_INFO: + switch (ucOpt1) { + case 0: + g_au4SwCr[1] = prStaRec->fgIsInPS; + break; + } + + break; + + case SWCTRL_DUMP_STA: + { + dumpSTA(prAdapter, prStaRec); + } + break; + + default: + + break; + } + } + +} + +#if TEST_PS + +VOID +testPsSendQoSNullFrame(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, + IN UINT_8 ucUP, + IN UINT_8 ucNetTypeIndex, + IN BOOLEAN fgBMC, + IN BOOLEAN fgIsBurstEnd, IN BOOLEAN ucPacketType, IN BOOLEAN ucPsSessionID, IN BOOLEAN fgSetEOSP) +{ + P_MSDU_INFO_T prMsduInfo; + UINT_16 u2EstimatedFrameLen; + P_WLAN_MAC_HEADER_QOS_T prQoSNullFrame; + + DEBUGFUNC("testPsSendQoSNullFrame"); + DBGLOG(SW4, LOUD, "\n"); + + /* 4 <1> Allocate a PKT_INFO_T for Null Frame */ + /* Init with MGMT Header Length */ + u2EstimatedFrameLen = MAC_TX_RESERVED_FIELD + WLAN_MAC_HEADER_QOS_LEN; + + /* Allocate a MSDU_INFO_T */ + prMsduInfo = cnmMgtPktAlloc(prAdapter, u2EstimatedFrameLen); + if (prMsduInfo == NULL) { + DBGLOG(SW4, WARN, "No PKT_INFO_T for sending Null Frame.\n"); + return; + } + /* 4 <2> Compose Null frame in MSDU_INfO_T. */ + bssComposeQoSNullFrame(prAdapter, + (PUINT_8) ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD), + prStaRec, ucUP, fgSetEOSP); + + prMsduInfo->eSrc = TX_PACKET_MGMT; + /* prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_DATA; */ + prMsduInfo->ucPacketType = ucPacketType; + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_HEADER_QOS_LEN; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = NULL; + prMsduInfo->fgIsBasicRate = TRUE; + prMsduInfo->fgIsBurstEnd = fgIsBurstEnd; + prMsduInfo->ucUserPriority = ucUP; + prMsduInfo->ucPsSessionID = ucPsSessionID /* 0~7 Test 7 means NOACK */; + + prQoSNullFrame = (P_WLAN_MAC_HEADER_QOS_T) (((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD)); + + if (fgBMC) + prQoSNullFrame->aucAddr1[0] = 0xfd; + else + prQoSNullFrame->aucAddr1[5] = 0xdd; + + /* 4 <4> Inform TXM to send this Null frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + +} + +VOID testPsSetupBss(IN P_ADAPTER_T prAdapter, IN UINT_8 ucNetworkTypeIndex) +{ + P_BSS_INFO_T prBssInfo; + UINT_8 _aucZeroMacAddr[] = NULL_MAC_ADDR; + + DEBUGFUNC("testPsSetupBss()"); + DBGLOG(SW4, INFO, "index %d\n", ucNetworkTypeIndex); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetworkTypeIndex]); + + /* 4 <1.2> Initiate PWR STATE */ + /* SET_NET_PWR_STATE_IDLE(prAdapter, ucNetworkTypeIndex); */ + + /* 4 <2> Initiate BSS_INFO_T - common part */ + BSS_INFO_INIT(prAdapter, ucNetworkTypeIndex); + + prBssInfo->eConnectionState = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eConnectionStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prBssInfo->eCurrentOPMode = OP_MODE_ACCESS_POINT; + prBssInfo->fgIsNetActive = TRUE; + prBssInfo->ucNetTypeIndex = (ucNetworkTypeIndex); + prBssInfo->ucReasonOfDisconnect = DISCONNECT_REASON_CODE_RESERVED; + + prBssInfo->ucPhyTypeSet = PHY_TYPE_SET_802_11BG; /* Depend on eBand */ + prBssInfo->ucConfigAdHocAPMode = AP_MODE_MIXED_11BG; /* Depend on eCurrentOPMode and ucPhyTypeSet */ + prBssInfo->u2BSSBasicRateSet = RATE_SET_ERP; + prBssInfo->u2OperationalRateSet = RATE_SET_OFDM; + prBssInfo->fgErpProtectMode = FALSE; + prBssInfo->fgIsQBSS = TRUE; + + /* 4 <1.5> Setup MIB for current BSS */ + prBssInfo->u2BeaconInterval = 100; + prBssInfo->ucDTIMPeriod = DOT11_DTIM_PERIOD_DEFAULT; + prBssInfo->u2ATIMWindow = 0; + + prBssInfo->ucBeaconTimeoutCount = 0; + + bssInitForAP(prAdapter, prBssInfo, TRUE); + + COPY_MAC_ADDR(prBssInfo->aucBSSID, _aucZeroMacAddr); + LINK_INITIALIZE(&prBssInfo->rStaRecOfClientList); + prBssInfo->fgIsBeaconActivated = TRUE; + prBssInfo->ucHwDefaultFixedRateCode = RATE_CCK_1M_LONG; + + COPY_MAC_ADDR(prBssInfo->aucOwnMacAddr, prAdapter->rWifiVar.aucMacAddress); + + /* 4 <3> Initiate BSS_INFO_T - private part */ + /* TODO */ + prBssInfo->eBand = BAND_2G4; + prBssInfo->ucPrimaryChannel = 1; + prBssInfo->prStaRecOfAP = (P_STA_RECORD_T) NULL; + + /* prBssInfo->fgErpProtectMode = eErpProectMode; */ + /* prBssInfo->eHtProtectMode = eHtProtectMode; */ + /* prBssInfo->eGfOperationMode = eGfOperationMode; */ + + /* 4 <4> Allocate MSDU_INFO_T for Beacon */ + prBssInfo->prBeacon = cnmMgtPktAlloc(prAdapter, OFFSET_OF(WLAN_BEACON_FRAME_T, aucInfoElem[0]) + MAX_IE_LENGTH); + + if (prBssInfo->prBeacon) { + prBssInfo->prBeacon->eSrc = TX_PACKET_MGMT; + prBssInfo->prBeacon->ucNetworkType = ucNetworkTypeIndex; + } else { + DBGLOG(SW4, INFO, "prBeacon allocation fail\n"); + } + +#if 0 + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = PM_UAPSD_ALL; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = WMM_MAX_SP_LENGTH_2; +#else + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC = (UINT_8) prAdapter->u4UapsdAcBmp; + prBssInfo->rPmProfSetupInfo.ucUapsdSp = (UINT_8) prAdapter->u4MaxSpLen; +#endif + +#if 0 + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prBssInfo->arACQueParms[eAci].fgIsACMSet = FALSE; + prBssInfo->arACQueParms[eAci].u2Aifsn = (UINT_16) eAci; + prBssInfo->arACQueParms[eAci].u2CWmin = 7; + prBssInfo->arACQueParms[eAci].u2CWmax = 31; + prBssInfo->arACQueParms[eAci].u2TxopLimit = eAci + 1; + DBGLOG(SW4, INFO, "MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", + eAci, prBssInfo->arACQueParms[eAci].fgIsACMSet, + prBssInfo->arACQueParms[eAci].u2Aifsn, + prBssInfo->arACQueParms[eAci].u2CWmin, + prBssInfo->arACQueParms[eAci].u2CWmax, prBssInfo->arACQueParms[eAci].u2TxopLimit)); + + } +#endif + + DBGLOG(SW4, INFO, "[2] ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x, ucUapsdSp:0x%x", + prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC, + prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC, prBssInfo->rPmProfSetupInfo.ucUapsdSp); + +} + +VOID testPsCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + DBGLOG(SW4, LOUD, "Read %u Index %u\n", ucRead, ucIndex); + + prStaRec = cnmGetStaRecByIndex(prAdapter, 0); + + if (ucIndex >= TEST_PS_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case TEST_PS_SETUP_BSS: + testPsSetupBss(prAdapter, ucOpt0); + break; + + case TEST_PS_ENABLE_BEACON: + break; + + case TEST_PS_TRIGGER_BMC: + /* txmForwardQueuedBmcPkts (ucOpt0); */ + break; + case TEST_PS_SEND_NULL: + { + + testPsSendQoSNullFrame(prAdapter, prStaRec, (UINT_8) (g_au4SwCr[1] & 0xFF), /* UP */ + ucOpt0, (BOOLEAN) ((g_au4SwCr[1] >> 8) & 0xFF), /* BMC */ + (BOOLEAN) ((g_au4SwCr[1] >> 16) & 0xFF), /* BurstEnd */ + (BOOLEAN) ((g_au4SwCr[1] >> 24) & 0xFF), /* Packet type */ + (UINT_8) ((g_au4SwCr[2]) & 0xFF), /* PS sesson ID 7: NOACK */ + FALSE /* EOSP */ + ); + } + break; + case TEST_PS_BUFFER_BMC: + /* g_aprBssInfo[ucOpt0]->fgApToBufferBMC = (g_au4SwCr[1] & 0xFF); */ + break; + case TEST_PS_UPDATE_BEACON: + bssUpdateBeaconContent(prAdapter, ucOpt0 /*networktype */); + break; + + default: + break; + } + } else { + switch (ucIndex) { + + case TEST_PS_MAGIC: + g_au4SwCr[1] = 0x88660011; + break; + + } + } +} + +#endif /* TEST_PS */ + +#if TEST_PS + +VOID testPsCmdCategory1(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + UINT_8 ucWTEntry; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testPsCmdCategory1"); + + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + if (ucOpt0 >= CFG_STA_REC_NUM) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucOpt0); + if (!prStaRec) + return; + ucWTEntry = prStaRec->ucWTEntry; + if (ucRead == SWCR_WRITE) { + + switch (ucIndex) { + case TEST_PS_STA_PS: + prStaRec->fgIsInPS = (BOOLEAN) (g_au4SwCr[1] & 0x1); + prStaRec->fgIsQoS = (BOOLEAN) (g_au4SwCr[1] >> 8 & 0xFF); + prStaRec->fgIsUapsdSupported = (BOOLEAN) (g_au4SwCr[1] >> 16 & 0xFF); + prStaRec->ucBmpDeliveryAC = (BOOLEAN) (g_au4SwCr[1] >> 24 & 0xFF); + break; + + } + + } else { + /* Read */ + switch (ucIndex) { + default: + break; + } + } + +} + +#endif /* TEST_PS */ + +#if CFG_SUPPORT_802_11V +#if (CFG_SUPPORT_802_11V_TIMING_MEASUREMENT == 1) && (WNM_UNIT_TEST == 1) +VOID testWNMCmdCategory0(P_ADAPTER_T prAdapter, UINT_8 ucCate, UINT_8 ucAction, UINT_8 ucOpt0, UINT_8 ucOpt1) +{ + UINT_8 ucIndex, ucRead; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("testWNMCmdCategory0"); + SWCR_GET_RW_INDEX(ucAction, ucRead, ucIndex); + + DBGLOG(SW4, INFO, "Read %u Index %u\n", ucRead, ucIndex); + + if (ucIndex >= TEST_WNM_CATA0_INDEX_NUM) + return; + + if (ucRead == SWCR_WRITE) { + switch (ucIndex) { + case TEST_WNM_TIMING_MEAS: + wnmTimingMeasUnitTest1(prAdapter, ucOpt0); + break; + + default: + break; + } + } +} +#endif /* TEST_WNM */ +#endif /* CFG_SUPPORT_802_11V */ + +VOID swCtrlSwCr(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + /* According other register STAIDX */ + UINT_8 ucOffset; + + ucOffset = (u2Addr >> 2) & 0x3F; + + if (ucOffset >= SWCR_CR_NUM) + return; + + if (ucRead == SWCR_WRITE) { + g_au4SwCr[ucOffset] = *pu4Data; + if (ucOffset == 0x0) { + /* Commmand [31:24]: Category */ + /* Commmand [23:23]: 1(W) 0(R) */ + /* Commmand [22:16]: Index */ + /* Commmand [15:08]: Option0 */ + /* Commmand [07:00]: Option1 */ + UINT_8 ucCate; + UINT_32 u4Cmd; + + u4Cmd = g_au4SwCr[0]; + ucCate = (UINT_8) (u4Cmd >> 24); + if (ucCate < sizeof(g_arSwCtrlCmd) / sizeof(g_arSwCtrlCmd[0])) { + if (g_arSwCtrlCmd[ucCate] != NULL) { + g_arSwCtrlCmd[ucCate] (prAdapter, ucCate, (UINT_8) (u4Cmd >> 16 & 0xFF), + (UINT_8) ((u4Cmd >> 8) & 0xFF), (UINT_8) (u4Cmd & 0xFF)); + } + } + } + } else { + *pu4Data = g_au4SwCr[ucOffset]; + } +} + +VOID swCrReadWriteCmd(P_ADAPTER_T prAdapter, UINT_8 ucRead, UINT_16 u2Addr, UINT_32 *pu4Data) +{ + UINT_8 ucMod; + + ucMod = u2Addr >> 8; + /* Address [15:8] MOD ID */ + /* Address [7:0] OFFSET */ + + DEBUGFUNC("swCrReadWriteCmd"); + DBGLOG(SW4, TRACE, "%u addr 0x%x data 0x%x\n", ucRead, u2Addr, *pu4Data); + + if (ucMod < (sizeof(g_arSwCrModHandle) / sizeof(g_arSwCrModHandle[0]))) { + + if (g_arSwCrModHandle[ucMod] != NULL) + g_arSwCrModHandle[ucMod] (prAdapter, ucRead, u2Addr, pu4Data); + } /* ucMod */ +} + +/* Debug Support */ +VOID swCrFrameCheckEnable(P_ADAPTER_T prAdapter, UINT_32 u4DumpType) +{ + g_u4SwcrDebugFrameDumpType = u4DumpType; + prAdapter->rRxCtrl.u4RxPktsDumpTypeMask = u4DumpType; +} + +VOID swCrDebugInit(P_ADAPTER_T prAdapter) +{ + /* frame dump */ + if (g_u4SwcrDebugFrameDumpType) + swCrFrameCheckEnable(prAdapter, g_u4SwcrDebugFrameDumpType); + /* debug counter */ + g_fgSwcrDebugTimer = FALSE; + + cnmTimerInitTimer(prAdapter, &g_rSwcrDebugTimer, (PFN_MGMT_TIMEOUT_FUNC) swCrDebugCheckTimeout, (ULONG) NULL); + + if (g_u4SwcrDebugCheckTimeout) + swCrDebugCheckEnable(prAdapter, TRUE, g_ucSwcrDebugCheckType, g_u4SwcrDebugCheckTimeout); +} + +VOID swCrDebugUninit(P_ADAPTER_T prAdapter) +{ + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + + g_fgSwcrDebugTimer = FALSE; +} + +VOID swCrDebugCheckEnable(P_ADAPTER_T prAdapter, BOOLEAN fgIsEnable, UINT_8 ucType, UINT_32 u4Timeout) +{ + if (fgIsEnable) { + g_ucSwcrDebugCheckType = ucType; + g_u4SwcrDebugCheckTimeout = u4Timeout; + if (g_fgSwcrDebugTimer == FALSE) + swCrDebugCheckTimeout(prAdapter, 0); + } else { + cnmTimerStopTimer(prAdapter, &g_rSwcrDebugTimer); + g_u4SwcrDebugCheckTimeout = 0; + } + + g_fgSwcrDebugTimer = fgIsEnable; +} + +VOID swCrDebugCheck(P_ADAPTER_T prAdapter, P_CMD_SW_DBG_CTRL_T prCmdSwCtrl) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* dump counters */ + if (prCmdSwCtrl) { + if (prCmdSwCtrl->u4Data == SWCR_DBG_TYPE_ALL) { + + /* TX Counter from fw */ + DBGLOG(SW4, INFO, "TX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_BCN_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_FAILED_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_RETRY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_AGING_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_PS_OVERFLOW_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_MGNT_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_TX_ERROR_CNT]); +#if 1 + /* TX Counter from drv */ + DBGLOG(SW4, INFO, "TX1\n" + "%08x %08x %08x %08x\n", + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_BSS_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_INACTIVE_STA_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_FORWARD_OVERFLOW_DROP), + (UINT_32) TX_GET_CNT(prTxCtrl, TX_AP_BORADCAST_DROP)); +#endif + + /* RX Counter */ + DBGLOG(SW4, INFO, "RX0\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_DUP_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TYPE_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_CLASS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_AMPDU_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_STATUS_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FORMAT_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_ICV_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_KEY_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_TKIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_MIC_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_BIP_ERROR_DROP_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_FIFOFULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_RX_PFDROP_CNT]); + + DBGLOG(SW4, INFO, "RX1\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + (UINT_32) RX_GET_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETURNED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT), + (UINT_32) RX_GET_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT)); + + DBGLOG(SW4, INFO, "PWR\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PS_POLL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_TRIGGER_NULL_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_IND_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_BCN_TIMEOUT_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_PM_STATE1], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF0], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_PWR_CUR_PS_PROF1]); + + DBGLOG(SW4, INFO, "ARM\n" + "%08x %08x %08x %08x\n" + "%08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RATE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_BWGI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_AR_STA0_RX_RATE_RCPI], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ENABLE], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_ROAM_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_ROAMING_INT_CNT]); + + DBGLOG(SW4, INFO, "BB\n" + "%08x %08x %08x %08x\n" + "%08x %08x %08x %08x\n", + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_MDRDY_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_RX_FCSERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_PD_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SFDERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_CCK_SIGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_TAGERR_CNT], + prCmdSwCtrl->u4DebugCnt[SWCR_DBG_ALL_BB_OFDM_SIGERR_CNT]); + + } + } + /* start the next check */ + if (g_u4SwcrDebugCheckTimeout) + cnmTimerStartTimer(prAdapter, &g_rSwcrDebugTimer, g_u4SwcrDebugCheckTimeout * MSEC_PER_SEC); +} + +VOID swCrDebugCheckTimeout(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + WLAN_STATUS rStatus; + + rCmdSwCtrl.u4Id = (0xb000 << 16) + g_ucSwcrDebugCheckType; + rCmdSwCtrl.u4Data = 0; + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_SW_DBG_CTRL, /* ucCID */ + FALSE, /* fgSetQuery */ + TRUE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + swCrDebugQuery, /* pfCmdDoneHandler */ + swCrDebugQueryTimeout, /* pfCmdTimeoutHandler */ + sizeof(CMD_SW_DBG_CTRL_T), /* u4SetQueryInfoLen */ + (PUINT_8)&rCmdSwCtrl, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + ASSERT(rStatus == WLAN_STATUS_PENDING); + +} + +VOID swCrDebugQuery(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, (P_CMD_SW_DBG_CTRL_T) (pucEventBuf)); +} + +VOID swCrDebugQueryTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + swCrDebugCheck(prAdapter, NULL); +} + +#endif /* CFG_SUPPORT_SWCR */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c new file mode 100644 index 0000000000000..96293c57e2b03 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls.c @@ -0,0 +1,5199 @@ +/* +** Id: tdls.c#1 +*/ + +/*! \file tdls.c + \brief This file includes IEEE802.11z TDLS support. +*/ + +/* +** Log: tdls.c + * + * 11 13 2013 vend_samp.lin + * NULL + * Initial version. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ +#include "precomp.h" + +#if (CFG_SUPPORT_TDLS == 1) +#include "gl_wext.h" +#include "tdls.h" +#include "gl_cfg80211.h" +#include +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb); + +#if TDLS_CFG_CMD_TEST +static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static TDLS_STATUS +TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd); + +static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param); + +static TDLS_STATUS +TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); + +static TDLS_STATUS +TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static VOID +TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, + UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers); + +static VOID +TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, + UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo); + +static TDLS_STATUS +TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static TDLS_STATUS +TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen); + +static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen); + +#endif /* TDLS_CFG_CMD_TEST */ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static BOOLEAN fgIsPtiTimeoutSkip = FALSE; + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to indicate packets to upper layer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prSkb A pointer to the received packet +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static VOID TdlsCmdTestRxIndicatePkts(GLUE_INFO_T *prGlueInfo, struct sk_buff *prSkb) +{ + struct net_device *prNetDev; + + /* init */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + /* pass to upper layer */ + //prNetDev->last_rx = jiffies; + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); +} + +#if TDLS_CFG_CMD_TEST + +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +do { \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} while (0) + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to add a TDLS peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_2_[Responder MAC] + + iwpriv wlan0 set_str_cmd 0_2_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestAddPeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + struct wireless_dev *prWdev; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + /* init */ + rCmd.rPeerInfo.supported_rates = NULL; + rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; + rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); + + /* send command to wifi task to handle */ + prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; + mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_16_[Enable/Disable]_[Set/Clear] + + iwpriv wlan0 set_str_cmd 0_16_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + TDLS_CMD_CORE_T rCmd; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); + + /* command to do this */ + flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; + + aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; + aucTdlsTestExtCapElm[1] = 5; + aucTdlsTestExtCapElm[2] = 0; + aucTdlsTestExtCapElm[3] = 0; + aucTdlsTestExtCapElm[4] = 0; + aucTdlsTestExtCapElm[5] = 0; + aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 7); /* bit39 */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a channel switch request from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_5_[TDLS Peer MAC]_[Chan]_[RegulatoryClass]_ + [SecondaryChannelOffset]_[SwitchTime]_[SwitchTimeout] + + iwpriv wlan0 set_str_cmd 0_1_5_00:11:22:33:44:01_1_255_0_15000_30000 + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChStReqRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4RegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s:[%pM]u4Chan=%u u4RegClass=%u u4SecChanOff=%u u4SwitchTime=%u u4SwitchTimeout=%u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4Chan, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4RegClass, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SecChanOff, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTime, + (UINT32) rCmd.Content.rCmdChStReqRcv.u4SwitchTimeout); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestChStReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a channel switch response from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_6_[TDLS Peer MAC]_[Chan]_ + [SwitchTime]_[SwitchTimeout]_[StatusCode] + + iwpriv wlan0 set_str_cmd 0_1_6_00:11:22:33:44:01_11_15000_30000_0 + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChStRspRcv.u4Chan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4SwitchTime = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChStRspRcv.u4StatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [ %pM ] u4Chan=%u u4SwitchTime=%u u4SwitchTimeout=%u u4StatusCode=%u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4Chan, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTime, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4SwitchTimeout, + (UINT32) rCmd.Content.rCmdChStRspRcv.u4StatusCode); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestChStRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip channel switch timeout function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_11_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestChSwTimeoutSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestChSwTimeoutSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer periodically. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static TIMER_T rTdlsTimerTestDataSend; +static UINT_8 aucTdlsTestDataSPeerMac[6]; +static UINT_16 u2TdlsTestDataSInterval; + +static void TdlsCmdTestDataContSend(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + BOOLEAN fgIsEnabled; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucTdlsTestDataSPeerMac); + u2TdlsTestDataSInterval = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + fgIsEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); + + if (fgIsEnabled == FALSE) { + /* stop test timer */ + return; + } + + /* re-init test timer */ + cnmTimerInitTimer(prAdapter, + &rTdlsTimerTestDataSend, (PFN_MGMT_TIMEOUT_FUNC) TdlsTimerTestDataContSend, (ULONG) NULL); + + cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a data frame from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_0_x80_[TDLS Peer MAC]_[PM]_[UP]_[EOSP]_[IsNull] + + iwpriv wlan0 set_str_cmd 0_1_x80_00:11:22:33:44:01_0_0_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDataRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.Content.rCmdDatRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4UP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4EOSP = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdDatRcv.u4IsNull = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, + " %s: [%pM] PM(%u) UP(%u) EOSP(%u) NULL(%u)\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdDatRcv.u4PM, + (UINT32) rCmd.Content.rCmdDatRcv.u4UP, + (UINT32) rCmd.Content.rCmdDatRcv.u4EOSP, (UINT32) rCmd.Content.rCmdDatRcv.u4IsNull); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestDataRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_4_[Responder MAC]_[tx status] + + iwpriv wlan0 set_str_cmd 0_4_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDataSend(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + P_ADAPTER_T prAdapter; + struct sk_buff *prMsduInfo; + UINT_8 *prPkt; + UINT_8 MAC[6]; + UINT_8 ucTxStatus; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, MAC); + ucTxStatus = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + /* allocate a data frame */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); + return; + } + + /* init dev */ + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* init packet */ + prMsduInfo->len = 1000; + kalMemZero(prMsduInfo->data, 100); /* for QoS field */ + kalMemCopy(prMsduInfo->data, MAC, 6); + kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); + *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; + + /* simulate OS to send the packet */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_16_[mili seconds] + + iwpriv wlan0 set_str_cmd 0_19_1000 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDelay(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT32 u4Delay; + + u4Delay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, "%s: Delay = %d\n", __func__, u4Delay); + + kalMdelay(u4Delay); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test discovery request frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_10_[DialogToken]_[Peer MAC]_[BSSID] + + iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01 + iwpriv wlan0 set_str_cmd 0_1_10_1_00:11:22:33:44:01_00:22:33:44:11:22 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestDiscoveryReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6]; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + kalMemZero(aucBSSID, sizeof(aucBSSID)); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_DISCOVERY_REQ; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + else + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip keep alive function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_10_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_10_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestKeepAliveSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdKeepAliveSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdKeepAliveSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestKeepAliveSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to simulate to set the TDLS Prohibited bit. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_11_[Enable/Disable]_[Set/Clear] + + iwpriv wlan0 set_str_cmd 0_13_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestProhibitedBitSet(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + TDLS_CMD_CORE_T rCmd; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdProhibit.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdProhibit.fgIsSet = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdProhibit.fgIsEnable); + + /* command to do this */ + flgTdlsTestExtCapElm = rCmd.Content.rCmdProhibit.fgIsEnable; + + aucTdlsTestExtCapElm[0] = ELEM_ID_EXTENDED_CAP; + aucTdlsTestExtCapElm[1] = 5; + aucTdlsTestExtCapElm[2] = 0; + aucTdlsTestExtCapElm[3] = 0; + aucTdlsTestExtCapElm[4] = 0; + aucTdlsTestExtCapElm[5] = 0; + aucTdlsTestExtCapElm[6] = (rCmd.Content.rCmdProhibit.fgIsSet << 6); /* bit38 */ +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI request from the AP. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_4_[TDLS Peer MAC]_[Dialog Token] + + iwpriv wlan0 set_str_cmd 0_1_4_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiReqRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [ %pM ] u4DialogToken = %u\n", + __func__, rCmd.aucPeerMac, (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiReqRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI response from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_9_[TDLS Peer MAC]_[Dialog Token]_[PM] + + iwpriv wlan0 set_str_cmd 0_1_9_00:11:22:33:44:01_0_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiRspRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdPtiRspRcv.u4DialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdPtiRspRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [%pM] u4DialogToken = %u %u\n", + __func__, rCmd.aucPeerMac, + (UINT32) rCmd.Content.rCmdPtiRspRcv.u4DialogToken, + (UINT32) rCmd.Content.rCmdPtiRspRcv.u4PM); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiRspRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to simulate PTI tx done fail case. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_21_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_21_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestPtiTxDoneFail(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdPtiTxFail.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdPtiTxFail.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestPtiTxFail, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test frame. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestRvFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ +/* PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; */ +/* TDLS_STATUS u4Status; */ + UINT_32 u4Subcmd; +/* UINT_32 u4BufLen; */ + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test rv frame sub command = %u\n", (UINT32) u4Subcmd); + + /* parse command arguments */ + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + /* simulate to receive a setup request frame */ + TdlsCmdTestSetupReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + /* simulate to receive a setup response frame */ + TdlsCmdTestSetupRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CONFIRM: + /* simulate to receive a setup confirm frame */ + TdlsCmdTestSetupConfirmRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_TEARDOWN: + /* simulate to receive a tear down frame */ + TdlsCmdTestTearDownRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_PTI: + /* simulate to receive a PTI request frame */ + TdlsCmdTestPtiReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_PTI_RSP: + /* simulate to receive a PTI response frame */ + TdlsCmdTestPtiRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_DATA_TEST_DATA: + /* simulate to receive a DATA frame */ + TdlsCmdTestDataRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CHAN_SWITCH_REQ: + /* simulate to receive a channel switch request frame */ + TdlsCmdTestChSwReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_CHAN_SWITCH_RSP: + /* simulate to receive a channel switch response frame */ + TdlsCmdTestChSwRspRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + case TDLS_FRM_ACTION_DISCOVERY_REQ: + /* simulate to receive a discovery request frame */ + TdlsCmdTestDiscoveryReqRecv(prGlueInfo, prInBuf, u4InBufLen); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test rv frame sub command\n"); + return; + } + +/* if (u4Status != TDLS_STATUS_SUCCESS) */ + { +/* DBGLOG(TDLS, ERROR, (" command parse fail\n")); */ +/* return; */ + } + + /* send command to wifi task to handle */ +#if 0 + kalIoctl(prGlueInfo, + TdlsTestFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup confirm frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_2_[DialogToken]_[StatusCode]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_1_2_1_0_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupConfirmRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6]; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d StatusCode=%d from %pM\n", + __func__, ucDialogToken, ucStatusCode, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_CONFIRM; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Status Code */ + *pPkt = ucStatusCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (4) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (17) WMM Information element */ + if (prAdapter->rWifiVar.fgSupportQoS) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup request frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_0_[DialogToken]_[Peer MAC]_[BSSID] + + iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01 + iwpriv wlan0 set_str_cmd 0_1_0_1_00:11:22:33:44:01_00:22:33:44:11:22 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupReqRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, aucPeerMac[6], aucBSSID[6], aucZeroMac[6]; + UINT_16 u2CapInfo; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + kalMemZero(aucBSSID, sizeof(aucBSSID)); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucBSSID); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d from %pM\n", __func__, ucDialogToken, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_SETUP_REQ; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (4) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = 18; + + if (kalMemCmp(aucBSSID, aucZeroMac, 6) == 0) + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + else + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, aucBSSID, 6); + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test setup response frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_1_[DialogToken]_[StatusCode]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_1_1_1_0_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestSetupRspRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + UINT_8 ucDialogToken, ucStatusCode, aucPeerMac[6]; + UINT_16 u2CapInfo; + + /* parse arguments */ + ucDialogToken = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucStatusCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + + DBGLOG(TDLS, INFO, + " %s: DialogToken=%d StatusCode=%d from %pM\n", + __func__, ucDialogToken, ucStatusCode, aucPeerMac); + + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_SETUP_RSP; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Status Code */ + *pPkt = ucStatusCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (4) Dialog token */ + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (5) Capability */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, NULL); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* TDLS_EX_CAP_PEER_UAPSD */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* TDLS_EX_CAP_CHAN_SWITCH */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* TDLS_EX_CAP_TDLS */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip channel switch timeout function. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_14_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_14_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestScanCtrl(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdScanSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdScanSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestScanSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a test tear down frame command. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_1_3_[IsInitiator]_[ReasonCode]_[Peer MAC]_[Where] + + Where 0 (From driver) or 1 (From FW) + + iwpriv wlan0 set_str_cmd 0_1_3_1_26_00:11:22:33:44:01_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTearDownRecv(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + ADAPTER_T *prAdapter; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + BOOLEAN fgIsInitiator; + UINT_8 ucReasonCode, aucPeerMac[6]; + BOOLEAN fgIsFromWhich; + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + fgIsInitiator = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + ucReasonCode = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, aucPeerMac); + fgIsFromWhich = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, + " %s: ReasonCode=%d from %pM %d\n", + __func__, ucReasonCode, aucPeerMac, fgIsFromWhich); + + if (fgIsFromWhich == 0) { + /* allocate/init packet */ + prAdapter = prGlueInfo->prAdapter; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, aucPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = TDLS_FRM_ACTION_TEARDOWN; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Reason Code */ + *pPkt = ucReasonCode; + *(pPkt + 1) = 0x00; + LR_TDLS_FME_FIELD_FILL(2); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + if (fgIsInitiator == 1) { + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, aucPeerMac, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prAdapter->rMyMacAddr, 6); + } else { + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, aucPeerMac, 6); + } + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* pass to OS */ + TdlsCmdTestRxIndicatePkts(prGlueInfo, prMsduInfo); + } else { + kalMemZero(&rCmd, sizeof(rCmd)); + kalMemCopy(rCmd.aucPeerMac, aucPeerMac, 6); + rCmd.Content.rCmdTearDownRcv.u4ReasonCode = (UINT32) ucReasonCode; + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, + TdlsTestTearDownRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to inform firmware to skip tx fail case. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_7_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_7_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxFailSkip(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + rCmd.Content.rCmdTxFailSkip.fgIsEnable = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: fgIsEnable = %d\n", __func__, rCmd.Content.rCmdTxFailSkip.fgIsEnable); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestTxFailSkip, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a test frame command to wifi task. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 +* +* EX: iwpriv wlan0 set_str_cmd 0_12_2_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_2_0_1_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxTdlsFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + UINT32 u4Subcmd; + UINT_32 u4BufLen; + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test tx tdls frame sub command = %u\n", u4Subcmd); + + /* parse command arguments */ + rCmd.ucFmeType = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); + + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + rCmd.ucToken = CmdStringDecParse(prInBuf, &prInBuf, &u4BufLen); + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + DBGLOG(TDLS, INFO, " setup FmeType=%d Token=%d to [%pM]\n", + rCmd.ucFmeType, rCmd.ucToken, rCmd.arRspAddr); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); + return; + } + + /* send command to wifi task to handle */ + kalIoctl(prGlueInfo, + TdlsTestTdlsFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a test frame command to wifi task. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ + [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ + [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ + [Timeout]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestTxFrame(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + TDLS_STATUS u4Status; + UINT_32 u4Subcmd; + UINT_32 u4BufLen; + + /* parse sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " test tx frame sub command = %u\n", (UINT32) u4Subcmd); + + /* parse command arguments */ + switch (u4Subcmd) { + case TDLS_FRM_ACTION_SETUP_REQ: + u4Status = TdlsCmdTestTxFmeSetupReqBufTranslate(prInBuf, u4InBufLen, &rCmd); + break; + + default: + DBGLOG(TDLS, ERROR, " wrong test tx frame sub command\n"); + return; + } + + if (u4Status != TDLS_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, " command parse fail\n"); + return; + } + + /* send command to wifi task to handle */ + kalIoctl(prGlueInfo, + TdlsTestFrameSend, + (PVOID)&rCmd, sizeof(PARAM_CUSTOM_TDLS_CMD_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse the TDLS test frame command, setup request +* +* @param CmdBuf Pointer to the buffer. +* @param BufLen Record buffer length. +* @param CmdTspec Pointer to the structure. +* +* @retval WLAN_STATUS_SUCCESS: Translate OK. +* @retval WLAN_STATUS_FAILURE: Translate fail. +* @usage iwpriv wlan0 set_str_cmd [tdls]_[command] +* +* EX: iwpriv wlan0 set_str_cmd 0_0_0_[FrameType]_[DialogToken]_[Cap]_[ExCap]_ + [SupRate0]_[SupRate1]_[SupRate2]_[SupRate3]_ + [SupChan0]_[SupChan1]_[SupChan2]_[SupChan3]_ + [Timeout]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_0_0_0_1_1_7_0_0_0_0_0_0_0_0_300_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsCmdTestTxFmeSetupReqBufTranslate(UINT_8 *pCmdBuf, UINT_32 u4BufLen, PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd) +{ +/* dumpMemory8(ANDROID_LOG_INFO, pCmdBuf, u4BufLen); */ + + prCmd->ucFmeType = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->ucToken = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->u2Cap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->ucExCap = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupRate[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[0] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[1] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[2] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->arSupChan[3] = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + prCmd->u4Timeout = CmdStringDecParse(pCmdBuf, &pCmdBuf, &u4BufLen); + CmdStringMacParse(pCmdBuf, &pCmdBuf, &u4BufLen, prCmd->arRspAddr); + + DBGLOG(TDLS, INFO, " command content =\n"); + DBGLOG(TDLS, INFO, "\tPeer MAC = %pM\n", (prCmd->arRspAddr)); + DBGLOG(TDLS, INFO, "\tToken = %u, Cap = 0x%x, ExCap = 0x%x, Timeout = %us FrameType = %u\n", + (UINT32) prCmd->ucToken, prCmd->u2Cap, prCmd->ucExCap, + (UINT32) prCmd->u4Timeout, (UINT32) prCmd->ucFmeType); + DBGLOG(TDLS, INFO, "\tSupRate = 0x%x %x %x %x\n", + prCmd->arSupRate[0], prCmd->arSupRate[1], prCmd->arSupRate[2], prCmd->arSupRate[3]); + DBGLOG(TDLS, INFO, "\tSupChan = %d %d %d %d\n", + prCmd->arSupChan[0], prCmd->arSupChan[1], prCmd->arSupChan[2], prCmd->arSupChan[3]); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update a TDLS peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_3_[Responder MAC] + + iwpriv wlan0 set_str_cmd 0_3_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestUpdatePeer(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + PARAM_CUSTOM_TDLS_CMD_STRUCT_T rCmd; + struct wireless_dev *prWdev; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.arRspAddr); + + /* init */ + rCmd.rPeerInfo.supported_rates = rCmd.arSupRate; + rCmd.rPeerInfo.ht_capa = &rCmd.rHtCapa; + rCmd.rPeerInfo.vht_capa = &rCmd.rVhtCapa; /* LINUX_KERNEL_VERSION >= 3.10.0 */ + rCmd.rPeerInfo.sta_flags_set = BIT(NL80211_STA_FLAG_TDLS_PEER); + rCmd.rPeerInfo.uapsd_queues = 0xf; /* all AC */ + rCmd.rPeerInfo.max_sp = 0; /* delivery all packets */ + + /* send command to wifi task to handle */ + prWdev = prGlueInfo->prDevHandler->ieee80211_ptr; + mtk_cfg80211_add_station(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, &rCmd.rPeerInfo); + + /* update */ + TdlsexCfg80211TdlsOper(prWdev->wiphy, (void *)0x1, rCmd.arRspAddr, NL80211_TDLS_ENABLE_LINK); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Null frame from the peer. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* EX: iwpriv wlan0 set_str_cmd 0_5_[Responder MAC]_[PM bit] + + iwpriv wlan0 set_str_cmd 0_5_00:11:22:33:44:01_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdTestNullRecv(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.Content.rCmdNullRcv.u4PM = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: [%pM] u4PM = %u\n", + __func__, (rCmd.aucPeerMac), (UINT32) rCmd.Content.rCmdNullRcv.u4PM); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsTestNullRecv, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a data frame to the peer periodically. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] u4Param no use +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_15_[Responder MAC]_[Interval: ms]_[Enable/Disable] + + iwpriv wlan0 set_str_cmd 0_15_00:11:22:33:44:01_5000_1 +*/ +/*----------------------------------------------------------------------------*/ +static VOID TdlsTimerTestDataContSend(ADAPTER_T *prAdapter, UINT_32 u4Param) +{ + GLUE_INFO_T *prGlueInfo; + struct sk_buff *prMsduInfo; + UINT_8 *prPkt; + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + + /* allocate a data frame */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1000, &prPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s allocate pkt fail!\n", __func__); + return; + } + + /* init dev */ + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s prMsduInfo->dev == NULL!\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return; + } + + /* init packet */ + prMsduInfo->len = 1000; + kalMemCopy(prMsduInfo->data, aucTdlsTestDataSPeerMac, 6); + kalMemCopy(prMsduInfo->data + 6, prAdapter->rMyMacAddr, 6); + *(UINT_16 *) (prMsduInfo->data + 12) = 0x0800; + + DBGLOG(TDLS, INFO, " %s try to send a data frame to %pM\n", + __func__, aucTdlsTestDataSPeerMac); + + /* simulate OS to send the packet */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + + /* restart test timer */ + cnmTimerStartTimer(prAdapter, &rTdlsTimerTestDataSend, u2TdlsTestDataSInterval); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Channel Switch Request frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChStReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_REQ; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Channel Switch Response frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChStRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_RSP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a test frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; + P_BSS_INFO_T prBssInfo; + struct sk_buff *prMsduInfo; + UINT_8 *pPkt; + UINT_32 u4PktLen, u4IeLen; + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if (u4SetBufferLen == 0) + return TDLS_STATUS_INVALID_LENGTH; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + *pu4SetInfoLen = u4SetBufferLen; + u4PktLen = 0; + + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAILURE; + } + + /* make up frame content */ + /* 1. 802.3 header */ + kalMemCopy(pPkt, prCmd->arRspAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prAdapter->rMyMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (2) Action */ + *pPkt = prCmd->ucFmeType; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (3) Dialog token */ + *pPkt = prCmd->ucToken; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (4) Capability */ + WLAN_SET_FIELD_16(pPkt, prCmd->u2Cap); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, NULL, 0, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (10) Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (12) Timeout interval element (TPK Key Lifetime) */ + TIMEOUT_INTERVAL_IE(pPkt)->ucId = ELEM_ID_TIMEOUT_INTERVAL; + TIMEOUT_INTERVAL_IE(pPkt)->ucLength = 5; + + TIMEOUT_INTERVAL_IE(pPkt)->ucType = IE_TIMEOUT_INTERVAL_TYPE_KEY_LIFETIME; + TIMEOUT_INTERVAL_IE(pPkt)->u4Value = htonl(prCmd->u4Timeout); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 3. Frame Formation - (16) Link identifier element */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, prAdapter->rMyMacAddr, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, prCmd->arRspAddr, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 4. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + /* 5. send the data frame */ + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a NULL frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestNullRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_NULL_RCV; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiReqRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_REQ; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a PTI response frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiRspRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_RSP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a Tear Down frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTearDownRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TEAR_DOWN; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to receive a data frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestDataRecv(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_DATA_RCV; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip PTI tx fail status. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestPtiTxFail(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_PTI_TX_FAIL; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a TDLS action frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* EX: iwpriv wlan0 set_str_cmd 0_12_0_[FrameType]_[DialogToken]_[Peer MAC] + + iwpriv wlan0 set_str_cmd 0_12_0_0_1_00:11:22:33:44:01 +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTdlsFrameSend(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + PARAM_CUSTOM_TDLS_CMD_STRUCT_T *prCmd; + struct wireless_dev *prWdev; + + /* sanity check */ + ASSERT(prAdapter); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if (u4SetBufferLen == 0) + return TDLS_STATUS_INVALID_LENGTH; + + /* allocate/init packet */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prCmd = (PARAM_CUSTOM_TDLS_CMD_STRUCT_T *) pvSetBuffer; + prWdev = (struct wireless_dev *)prGlueInfo->prDevHandler->ieee80211_ptr; + + TdlsexCfg80211TdlsMgmt(prWdev->wiphy, NULL, + prCmd->arRspAddr, prCmd->ucFmeType, 1, + 0, 0, /* open/none */ + FALSE, NULL, 0); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip tx fail status. So always success in tx done in firmware. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestTxFailSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_TX_FAIL_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip to do keep alive function in firmware. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestKeepAliveSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_KEEP_ALIVE_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip channel switch timeout. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestChSwTimeoutSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_CHSW_TIMEOUT_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to skip scan request. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsTestScanSkip(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_TEST_SCAN_SKIP; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +#endif /* TDLS_CFG_CMD_TEST */ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure channel switch parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsChSwConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_CHSW_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update channel switch parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_9_[TDLS Peer MAC]_ + [NetworkTypeIndex]_[1 (Enable) or (0) Disable]_[1 (Start) or 0 (Stop)]_ + [RegClass]_[Chan]_[SecChanOff]_[1 (Reqular) or (0) One Shot] + + RegulatoryClass: TODO (reference to Annex I of 802.11n spec.) + Secondary Channel Offset: 0 (SCN - no secondary channel) + 1 (SCA - secondary channel above) + 2 (SCB - secondary channel below) + SwitchTime: units of microseconds + + iwpriv wlan0 set_str_cmd 0_9_00:11:22:33:44:01_0_1_0_0_1_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdChSwConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + + rCmd.Content.rCmdChSwConf.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwStarted = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucRegClass = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucTargetChan = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.ucSecChanOff = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdChSwConf.fgIsChSwRegular = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: %pM ucNetTypeIndex=%d, fgIsChSwEnabled=%d, fgIsChSwStarted=%d", + __func__, (rCmd.aucPeerMac), + rCmd.Content.rCmdChSwConf.ucNetTypeIndex, + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled, + rCmd.Content.rCmdChSwConf.fgIsChSwStarted); + DBGLOG(TDLS, INFO, " RegClass=%d, TargetChan=%d, SecChanOff=%d, Regular=%d\n", + rCmd.Content.rCmdChSwConf.ucRegClass, + rCmd.Content.rCmdChSwConf.ucTargetChan, + rCmd.Content.rCmdChSwConf.ucSecChanOff, rCmd.Content.rCmdChSwConf.fgIsChSwRegular); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsChSwConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display TDLS related information. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_18_[Peer MAC]_[Network Interface ID]_[IsClear] + + Network Interface ID: reference to ENUM_NETWORK_TYPE_INDEX_T + + typedef enum _ENUM_NETWORK_TYPE_INDEX_T { + NETWORK_TYPE_AIS_INDEX = 0, + NETWORK_TYPE_P2P_INDEX, + NETWORK_TYPE_BOW_INDEX, + NETWORK_TYPE_INDEX_NUM + } ENUM_NETWORK_TYPE_INDEX_T; + + iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(&rCmd, sizeof(rCmd)); + + CmdStringMacParse(prInBuf, &prInBuf, &u4InBufLen, rCmd.aucPeerMac); + rCmd.ucNetTypeIndex = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdInfoDisplay.fgIsToClearAllHistory = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, " %s: Command PeerMac=%pM in BSS%u\n", + __func__, (rCmd.aucPeerMac), rCmd.ucNetTypeIndex); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display key related information. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_20 + + iwpriv wlan0 set_str_cmd 0_20 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdKeyInfoDisplay(GLUE_INFO_T *prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(&rCmd, sizeof(rCmd)); + + DBGLOG(TDLS, INFO, " %s\n", __func__); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsKeyInfoDisplay, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update MIB parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_6_[TdlsEn]_[UapsdEn]_[PsmEn]_[PtiWin]_[CWCap]_ + [AckMisRetry]_[RspTimeout]_[CWPbDelay]_[DRWin]_[LowestAcInt] + + iwpriv wlan0 set_str_cmd 0_6_1_1_0_1_1_3_5_1000_2_1 + + reference to TDLS_CMD_CORE_MIB_PARAM_UPDATE_T +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdMibParamUpdate(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* reset */ + kalMemZero(&rCmd, sizeof(rCmd)); + + /* parse arguments */ + rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval = + CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, " MIB param = %d %d %d %d %d %d %d %d %d %d\n", + rCmd.Content.rCmdMibUpdate.Tdlsdot11TunneledDirectLinkSetupImplemented, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDBufferSTAActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerPSMActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerUAPSDIndicationWindow, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSChannelSwitchingActivated, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSPeerSTAMissingAckRetryLimit, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSResponseTimeout, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSProbeDelay, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSDiscoveryRequestWindow, + rCmd.Content.rCmdMibUpdate.Tdlsdot11TDLSACDeterminationInterval); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsMibParamUpdate, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update setup parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_17_[20/40 Support] + + iwpriv wlan0 set_str_cmd 0_17_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdSetupConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + + rCmd.Content.rCmdSetupConf.fgIs2040Supported = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + + DBGLOG(TDLS, INFO, "%s: rCmdSetupConf=%d\n", __func__, rCmd.Content.rCmdSetupConf.fgIs2040Supported); + + /* command to do this */ + prGlueInfo->rTdlsLink.fgIs2040Sup = rCmd.Content.rCmdSetupConf.fgIs2040Supported; + + rStatus = kalIoctl(prGlueInfo, TdlsSetupConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update UAPSD parameters. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +* EX: iwpriv wlan0 set_str_cmd 0_8_[SP timeout skip]_[PTI timeout skip] + + iwpriv wlan0 set_str_cmd 0_8_1_1 +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsCmdUapsdConf(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + WLAN_STATUS rStatus; + TDLS_CMD_CORE_T rCmd; + UINT_32 u4BufLen; + + /* parse arguments */ + kalMemZero(rCmd.aucPeerMac, sizeof(rCmd.aucPeerMac)); + + /* UAPSD Service Period */ + rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + /* PTI Service Period */ + fgIsPtiTimeoutSkip = rCmd.Content.rCmdUapsdConf.fgIsPtiTimeoutSkip; + + DBGLOG(TDLS, INFO, "%s: fgIsSpTimeoutSkip=%d, fgIsPtiTimeoutSkip=%d\n", + __func__, rCmd.Content.rCmdUapsdConf.fgIsSpTimeoutSkip, fgIsPtiTimeoutSkip); + + /* command to do this */ + rStatus = kalIoctl(prGlueInfo, TdlsUapsdConf, &rCmd, sizeof(rCmd), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s kalIoctl fail:%x\n", __func__, rStatus); + return; + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display TDLS all information. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +* iwpriv wlan0 set_str_cmd 0_18_00:00:00:00:00:00_0_0 +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_CORE_T *prCmdContent; + STA_RECORD_T *prStaRec; + TDLS_INFO_LINK_T *prLink; + UINT32 u4StartIdx; + UINT32 u4PeerNum; + BOOLEAN fgIsListAll; + UINT8 ucMacZero[6]; + UINT32 u4HisIdx; + UINT8 ucNetTypeIndex; + + /* init */ + prGlueInfo = prAdapter->prGlueInfo; + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + u4StartIdx = 0; + u4PeerNum = 1; + fgIsListAll = TRUE; + kalMemZero(ucMacZero, sizeof(ucMacZero)); + ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + /* display common information */ + DBGLOG(TDLS, TRACE, "TDLS common:\n"); + DBGLOG(TDLS, TRACE, "\t\trFreeSwRfbList=%u\n", (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + DBGLOG(TDLS, TRACE, "\t\tjiffies=%u %ums (HZ=%d)\n", (UINT32) jiffies, (UINT32) kalGetTimeTick(), HZ); + + /* display disconnection history information */ + DBGLOG(TDLS, TRACE, "TDLS link history: %d\n", prGlueInfo->rTdlsLink.u4LinkIdx); + + for (u4HisIdx = prGlueInfo->rTdlsLink.u4LinkIdx + 1; u4HisIdx < TDLS_LINK_HISTORY_MAX; u4HisIdx++) { + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; + + if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) + continue; /* skip all zero */ + + DBGLOG(TDLS, TRACE, + "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", + u4HisIdx, prLink->aucPeerMac, + prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), + prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), + prLink->ucReasonCode, + prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); + + if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { + DBGLOG(TDLS, TRACE, + "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", + prLink->ucHtBa[0], prLink->ucHtBa[1], + prLink->ucHtBa[2], prLink->ucHtBa[3], + prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); + } + } + for (u4HisIdx = 0; u4HisIdx <= prGlueInfo->rTdlsLink.u4LinkIdx; u4HisIdx++) { + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4HisIdx]; + + if (kalMemCmp(prLink->aucPeerMac, ucMacZero, 6) == 0) + continue; /* skip all zero, use continue, not break */ + + DBGLOG(TDLS, TRACE, + "\t\t%d. %pM jiffies start(%lu %ums)end(%lu %ums)Reason(%u)fromUs(%u)Dup(%u)HT(%u)\n", + u4HisIdx, (prLink->aucPeerMac), + prLink->jiffies_start, jiffies_to_msecs(prLink->jiffies_start), + prLink->jiffies_end, jiffies_to_msecs(prLink->jiffies_end), + prLink->ucReasonCode, + prLink->fgIsFromUs, prLink->ucDupCount, (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP)); + + if (prLink->ucHtCap & TDLS_INFO_LINK_HT_CAP_SUP) { + DBGLOG(TDLS, TRACE, + "\t\t\tBA (0x%x %x %x %x %x %x %x %x)\n", + prLink->ucHtBa[0], prLink->ucHtBa[1], + prLink->ucHtBa[2], prLink->ucHtBa[3], + prLink->ucHtBa[4], prLink->ucHtBa[5], prLink->ucHtBa[6], prLink->ucHtBa[7]); + } + } + DBGLOG(TDLS, TRACE, "\n"); + + /* display link information */ + if (prCmdContent != NULL) { + if (kalMemCmp(prCmdContent->aucPeerMac, ucMacZero, 6) != 0) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + prCmdContent->ucNetTypeIndex, prCmdContent->aucPeerMac); + if (prStaRec == NULL) + fgIsListAll = TRUE; + } + + ucNetTypeIndex = prCmdContent->ucNetTypeIndex; + } + + while (1) { + if (fgIsListAll == TRUE) { + /* list all TDLS peers */ + prStaRec = cnmStaTheTypeGet(prAdapter, ucNetTypeIndex, STA_TYPE_TDLS_PEER, &u4StartIdx); + if (prStaRec == NULL) + break; + } + + DBGLOG(TDLS, TRACE, "-------- TDLS %d: 0x %pM\n", u4PeerNum, (prStaRec->aucMacAddr)); + DBGLOG(TDLS, TRACE, "\t\t\t State %d, PM %d, Cap 0x%x\n", + prStaRec->ucStaState, prStaRec->fgIsInPS, prStaRec->u2CapInfo); + DBGLOG(TDLS, TRACE, "\t\t\t SetupDisable %d, ChSwDisable %d\n", + prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); + + if (fgIsListAll == FALSE) + break; /* only list one */ + } + + /* check if we need to clear all histories */ + if ((prCmdContent != NULL) && (prCmdContent->Content.rCmdInfoDisplay.fgIsToClearAllHistory == TRUE)) { + kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); + prGlueInfo->rTdlsLink.u4LinkIdx = TDLS_LINK_HISTORY_MAX - 1; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to display key information. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsKeyInfoDisplay(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_KEY_INFO; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to record a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] fgIsTearDown TRUE: the link is torn down +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] fgIsFromUs TRUE: tear down is from us +* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +TdlsLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, + UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode, VOID *prOthers) +{ + TDLS_INFO_LINK_T *prLink; + + DBGLOG(TDLS, INFO, + " %s: record history for %pM %d %d %d %d\n", + __func__, pucPeerMac, prGlueInfo->rTdlsLink.u4LinkIdx, + fgIsTearDown, fgIsFromUs, u2ReasonCode); + + /* check duplicate one */ + if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) { + DBGLOG(TDLS, ERROR, " %s: u4LinkIdx >= TDLS_LINK_HISTORY_MAX\n", __func__); + + /* reset to 0 */ + prGlueInfo->rTdlsLink.u4LinkIdx = 0; + } + + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; + + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) == 0) { + if ((prLink->ucReasonCode == u2ReasonCode) && (prLink->fgIsFromUs == fgIsFromUs)) { + /* same Peer MAC, Reason Code, Trigger source */ + if (fgIsTearDown == TRUE) { + if (prLink->jiffies_end != 0) { + /* already torn down */ + prLink->ucDupCount++; + return; + } + } else { + /* already built */ + prLink->ucDupCount++; + return; + } + } + } + + /* search old entry */ + if (fgIsTearDown == TRUE) { + /* TODO: need to search all entries to find it if we support multiple TDLS link design */ + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { + /* error! can not find the link entry */ + DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); + return; + } + + prLink->jiffies_end = jiffies; + prLink->ucReasonCode = (UINT8) u2ReasonCode; + prLink->fgIsFromUs = fgIsFromUs; + } else { + /* record new one */ + prGlueInfo->rTdlsLink.u4LinkIdx++; + if (prGlueInfo->rTdlsLink.u4LinkIdx >= TDLS_LINK_HISTORY_MAX) + prGlueInfo->rTdlsLink.u4LinkIdx = 0; + + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[prGlueInfo->rTdlsLink.u4LinkIdx]; + + prLink->jiffies_start = jiffies; + prLink->jiffies_end = 0; + kalMemCopy(&prLink->aucPeerMac, pucPeerMac, 6); + prLink->ucReasonCode = 0; + prLink->fgIsFromUs = (UINT8) fgIsFromUs; + prLink->ucDupCount = 0; + + if (prOthers != NULL) { + /* record other parameters */ + TDLS_LINK_HIS_OTHERS_T *prHisOthers; + + prHisOthers = (TDLS_LINK_HIS_OTHERS_T *) prOthers; + if (prHisOthers->fgIsHt == TRUE) + prLink->ucHtCap |= TDLS_INFO_LINK_HT_CAP_SUP; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] eFmeStatus TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME +* \param[in] pInfo other information +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +static VOID +TdlsLinkHistoryRecordUpdate(GLUE_INFO_T *prGlueInfo, + UINT8 *pucPeerMac, TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus, VOID *pInfo) +{ + TDLS_INFO_LINK_T *prLink; + UINT32 u4LinkIdx; + UINT32 u4Tid; + + /* sanity check */ + if ((eFmeStatus < TDLS_HOST_EVENT_SF_BA) || (eFmeStatus > TDLS_HOST_EVENT_SF_BA_RSP_DECLINE)) { + /* do not care these frames */ + return; + } + + DBGLOG(TDLS, INFO, + " %s: update history for %pM %d %d\n", + __func__, (pucPeerMac), prGlueInfo->rTdlsLink.u4LinkIdx, eFmeStatus); + + /* init */ + u4LinkIdx = prGlueInfo->rTdlsLink.u4LinkIdx; + prLink = &prGlueInfo->rTdlsLink.rLinkHistory[u4LinkIdx]; + + /* TODO: need to search all entries to find it if we support multiple TDLS link design */ + if (kalMemCmp(&prLink->aucPeerMac, pucPeerMac, 6) != 0) { + /* error! can not find the link entry */ + DBGLOG(TDLS, INFO, " %s: cannot find the same entry!!!\n", __func__); + return; + } + + /* update */ + u4Tid = *(UINT32 *) pInfo; + switch (eFmeStatus) { + case TDLS_HOST_EVENT_SF_BA: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP; + break; + + case TDLS_HOST_EVENT_SF_BA_OK: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_OK; + break; + + case TDLS_HOST_EVENT_SF_BA_DECLINE: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_SETUP_DECLINE; + break; + + case TDLS_HOST_EVENT_SF_BA_PEER: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_PEER; + break; + + case TDLS_HOST_EVENT_SF_BA_RSP_OK: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_OK; + break; + + case TDLS_HOST_EVENT_SF_BA_RSP_DECLINE: + prLink->ucHtBa[u4Tid] |= TDLS_INFO_LINK_HT_BA_RSP_DECLINE; + break; + } + + /* display TDLS link history */ + TdlsInfoDisplay(prGlueInfo->prAdapter, NULL, 0, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure TDLS MIB parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsMibParamUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_MIB_UPDATE; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure TDLS SETUP parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsSetupConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_SETUP_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to configure UAPSD parameters. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +* +*/ +/*----------------------------------------------------------------------------*/ +static TDLS_STATUS +TdlsUapsdConf(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + TDLS_CMD_CORE_T *prCmdContent; + WLAN_STATUS rStatus; + + /* init command buffer */ + prCmdContent = (TDLS_CMD_CORE_T *) pvSetBuffer; + prCmdContent->u4Command = TDLS_CORE_CMD_UAPSD_CONF; + + /* send the command */ + rStatus = wlanSendSetQueryCmd(prAdapter, /* prAdapter */ + CMD_ID_TDLS_CORE, /* ucCID */ + TRUE, /* fgSetQuery */ + FALSE, /* fgNeedResp */ + FALSE, /* fgIsOid */ + NULL, NULL, /* pfCmdTimeoutHandler */ + sizeof(TDLS_CMD_CORE_T), /* u4SetQueryInfoLen */ + (PUINT_8) prCmdContent, /* pucInfoBuffer */ + NULL, /* pvSetQueryBuffer */ + 0 /* u4SetQueryBufferLen */ + ); + + if (rStatus != WLAN_STATUS_PENDING) { + DBGLOG(TDLS, ERROR, "%s wlanSendSetQueryCmd allocation fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + DBGLOG(TDLS, INFO, "%s cmd ok.\n", __func__); + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to update frame status. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventFmeStatus(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + TDLS_EVENT_HOST_SUBID_SPECIFIC_FRAME eFmeStatus; + STA_RECORD_T *prStaRec; + UINT32 u4Tid; + + /* init */ + u4Tid = *(UINT32 *) prInBuf; + prInBuf += 4; /* skip u4EventSubId */ + + /* sanity check */ + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); + if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) + return; + prInBuf++; + + /* update status */ + eFmeStatus = *prInBuf; + TdlsLinkHistoryRecordUpdate(prGlueInfo, prStaRec->aucMacAddr, eFmeStatus, &u4Tid); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to collect TDLS statistics from firmware. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventStatistics(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + STA_RECORD_T *prStaRec; + STAT_CNT_INFO_FW_T *prStat; + UINT32 u4RateId; + + /* init */ + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *prInBuf); + if ((prStaRec == NULL) || (!IS_TDLS_STA(prStaRec))) + return; + + prInBuf += 4; /* skip prStaRec->ucIndex */ + + /* update statistics */ + kalMemCopy(&prStaRec->rTdlsStatistics.rFw, prInBuf, sizeof(prStaRec->rTdlsStatistics.rFw)); + + /* display statistics */ + prStat = &prStaRec->rTdlsStatistics.rFw; + + DBGLOG(TDLS, TRACE, " peer [%pM] statistics:\n", (prStaRec->aucMacAddr)); + DBGLOG(TDLS, TRACE, "\t\tT%d %d %d (P%d %d) (%dus) - E%d 0x%x - R%d (P%d)\n", + prStat->u4NumOfTx, prStat->u4NumOfTxOK, prStat->u4NumOfTxRetry, + prStat->u4NumOfPtiRspTxOk, prStat->u4NumOfPtiRspTxErr, + prStat->u4TxDoneAirTimeMax, + prStat->u4NumOfTxErr, prStat->u4TxErrBitmap, prStat->u4NumOfRx, prStat->u4NumOfPtiRspRx); + + DBGLOG(TDLS, TRACE, "\t\t"); + + for (u4RateId = prStat->u4TxRateOkHisId; u4RateId < STAT_CNT_INFO_MAX_TX_RATE_OK_HIS_NUM; u4RateId++) + DBGLOG(TDLS, TRACE, + "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); + for (u4RateId = 0; u4RateId < prStat->u4TxRateOkHisId; u4RateId++) + DBGLOG(TDLS, TRACE, + "%d(%d) ", prStat->aucTxRateOkHis[u4RateId][0], prStat->aucTxRateOkHis[u4RateId][1]); + + DBGLOG(TDLS, TRACE, "\n\n"); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tear down. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventTearDown(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + STA_RECORD_T *prStaRec; + UINT16 u2ReasonCode; + UINT32 u4TearDownSubId; + UINT8 *pMac, aucZeroMac[6]; + + /* init */ + u4TearDownSubId = *(UINT32 *) prInBuf; + kalMemZero(aucZeroMac, sizeof(aucZeroMac)); + pMac = aucZeroMac; + + prStaRec = cnmGetStaRecByIndex(prGlueInfo->prAdapter, *(prInBuf + 4)); + if (prStaRec != NULL) + pMac = prStaRec->aucMacAddr; + + /* handle */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=PTI timeout\n", + __func__, pMac); + } else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=AGE timeout\n", + __func__, pMac); + } else { + DBGLOG(TDLS, WARN, " %s: peer [%pM] Reason=%d\n", + __func__, pMac, u4TearDownSubId); + } + + /* sanity check */ + if (prStaRec == NULL) + return; + + if (fgIsPtiTimeoutSkip == TRUE) { + /* skip PTI timeout event */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) { + DBGLOG(TDLS, WARN, " %s: skip PTI timeout\n", __func__); + return; + } + } + + /* record history */ + if (u4TearDownSubId == TDLS_HOST_EVENT_TD_AGE_TIMEOUT) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_TIMEOUT) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_FAIL) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_FAIL; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_PTI_SEND_MAX_FAIL) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_SEND_MAX_FAIL; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_WRONG_NETWORK_IDX) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_WRONG_NETWORK_IDX; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_NON_STATE3) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_NON_STATE3; + else if (u4TearDownSubId == TDLS_HOST_EVENT_TD_LOST_TEAR_DOWN) + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_LOST_TEAR_DOWN; + else { + /* shall not be here */ + u2ReasonCode = TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_UNKNOWN; + } + + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, TRUE, u2ReasonCode, NULL); + + /* correct correct reason code for PTI or AGE timeout to supplicant */ + if ((u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_AGE_TIMEOUT) || + (u2ReasonCode == TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_PTI_TIMEOUT)) { + u2ReasonCode = TDLS_REASON_CODE_UNREACHABLE; + } + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, NL80211_TDLS_TEARDOWN, u2ReasonCode, GFP_ATOMIC); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to do tx down. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer, from u4EventSubId +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +static void TdlsEventTxDone(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + /* UINT32 u4FmeIdx; */ + UINT8 *pucFmeHdr; + UINT8 ucErrStatus; + + ucErrStatus = *(UINT32 *) prInBuf; + + pucFmeHdr = prInBuf + 4; /* skip ucErrStatus */ + + if (ucErrStatus == 0) + DBGLOG(TDLS, TRACE, " %s: OK to tx a TDLS action:", __func__); + else + DBGLOG(TDLS, TRACE, " %s: fail to tx a TDLS action (err=0x%x):", __func__, ucErrStatus); + #if 0 + /* dump TX packet content from wlan header */ + for (u4FmeIdx = 0; u4FmeIdx < (u4InBufLen - 4); u4FmeIdx++) { + if ((u4FmeIdx % 16) == 0) + DBGLOG(TDLS, TRACE, "\n"); + + DBGLOG(TDLS, TRACE, "%02x ", *pucFmeHdr++); + } + DBGLOG(TDLS, TRACE, "\n\n"); + #endif +} + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to parse TDLS Extended Capabilities element. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexBssExtCapParse(STA_RECORD_T *prStaRec, UINT_8 *pucIE) +{ + UINT_8 *pucIeExtCap; + + /* sanity check */ + if ((prStaRec == NULL) || (pucIE == NULL)) + return; + + if (IE_ID(pucIE) != ELEM_ID_EXTENDED_CAP) + return; + + /* + from bit0 ~ + + bit 38: TDLS Prohibited + The TDLS Prohibited subfield indicates whether the use of TDLS is prohibited. The + field is set to 1 to indicate that TDLS is prohibited and to 0 to indicate that TDLS is + allowed. + */ + if (IE_LEN(pucIE) < 5) + return; /* we need 39/8 = 5 bytes */ + + /* init */ + prStaRec->fgTdlsIsProhibited = FALSE; + prStaRec->fgTdlsIsChSwProhibited = FALSE; + + /* parse */ + pucIeExtCap = pucIE + 2; + pucIeExtCap += 4; /* shift to the byte we care about */ + + if ((*pucIeExtCap) & BIT(38 - 32)) + prStaRec->fgTdlsIsProhibited = TRUE; + if ((*pucIeExtCap) & BIT(39 - 32)) + prStaRec->fgTdlsIsChSwProhibited = TRUE; + + DBGLOG(TDLS, TRACE, + " %s: AP [%pM] tdls prohibit bit=%d %d\n", + __func__, + prStaRec->aucMacAddr, prStaRec->fgTdlsIsProhibited, prStaRec->fgTdlsIsChSwProhibited); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame from nl80211. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int +TdlsexCfg80211TdlsMgmt(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capability, + bool initiator, const u8 *buf, size_t len) +{ + ADAPTER_T *prAdapter; + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prAisBssInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + TDLS_MGMT_TX_INFO *prMgmtTxInfo; + + /* + Have correct behavior for STAUT receiving TDLS Setup Request after sending TDLS + Set Request and before receiving TDLS Setup Response: + -- Source Address of received Request is higher than own MAC address + -- Source Address of received Request is lower than own MAC address + + ==> STA with larger MAC address will send the response frame. + + Supplicant will do this in wpa_tdls_process_tpk_m1(). + */ + + /* sanity check */ + if ((wiphy == NULL) || (peer == NULL)) { + DBGLOG(TDLS, ERROR, " %s: wrong 0x%p 0x%p!\n", __func__, wiphy, peer); + return -EINVAL; + } + + DBGLOG(TDLS, INFO, " %s: [%pM] %d %d %d 0x%p %u\n", + __func__, peer, action_code, dialog_token, status_code, buf, (UINT32) len); + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); + return -EINVAL; + } + + prAdapter = prGlueInfo->prAdapter; + if (prAdapter->fgTdlsIsSup == FALSE) { + DBGLOG(TDLS, ERROR, " %s: firmware TDLS is not supported!\n", __func__); + return -EBUSY; + } + + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prAisBssInfo->fgTdlsIsProhibited == TRUE) { + /* do not send anything if TDLS is prohibited in the BSS */ + return 0; + } + + prMgmtTxInfo = kalMemAlloc(sizeof(TDLS_MGMT_TX_INFO), VIR_MEM_TYPE); + if (prMgmtTxInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate fail!\n", __func__); + return -ENOMEM; + } + + kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); + + if (peer != NULL) + kalMemCopy(prMgmtTxInfo->aucPeer, peer, 6); + prMgmtTxInfo->ucActionCode = action_code; + prMgmtTxInfo->ucDialogToken = dialog_token; + prMgmtTxInfo->u2StatusCode = status_code; + + if (buf != NULL) { + if (len > sizeof(prMgmtTxInfo->aucSecBuf)) { + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return -EINVAL; + } + prMgmtTxInfo->u4SecBufLen = len; + kalMemCopy(prMgmtTxInfo->aucSecBuf, buf, len); + } + + /* send the TDLS action data frame */ + rStatus = kalIoctl(prGlueInfo, + TdlsexMgmtCtrl, + prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + /* + clear all content to avoid any bug if we dont yet execute TdlsexMgmtCtrl() + then kalIoctl finishes + */ + kalMemZero(prMgmtTxInfo, sizeof(TDLS_MGMT_TX_INFO)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return -EINVAL; + } + + kalMemFree(prMgmtTxInfo, VIR_MEM_TYPE, sizeof(TDLS_MGMT_TX_INFO)); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable or disable TDLS link from upper layer. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] +* \param[in] +* \param[in] buf includes RSN IE + FT IE + Lifetimeout IE +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +int TdlsexCfg80211TdlsOper(struct wiphy *wiphy, struct net_device *dev, + const u8 *peer, enum nl80211_tdls_operation oper) +{ + ADAPTER_T *prAdapter; + GLUE_INFO_T *prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + TDLS_CMD_LINK_T rCmdLink; + + /* sanity check */ + if (peer == NULL) { + DBGLOG(TDLS, ERROR, " %s: peer == NULL!\n", __func__); + return -EINVAL; + } + + DBGLOG(TDLS, INFO, " %s: [%pM] %d %d\n", + __func__, peer, oper, (wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)); + + if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) + return -ENOTSUPP; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) wiphy_priv(wiphy); + if (prGlueInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: wrong prGlueInfo 0x%p!\n", __func__, prGlueInfo); + return -EINVAL; + } + prAdapter = prGlueInfo->prAdapter; + kalMemCopy(rCmdLink.aucPeerMac, peer, sizeof(rCmdLink.aucPeerMac)); + rCmdLink.fgIsEnabled = FALSE; + + /* + enum nl80211_tdls_operation { + NL80211_TDLS_DISCOVERY_REQ, + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, + }; + */ + + switch (oper) { + case NL80211_TDLS_ENABLE_LINK: + rCmdLink.fgIsEnabled = TRUE; + break; + + case NL80211_TDLS_DISABLE_LINK: + rCmdLink.fgIsEnabled = FALSE; + break; + + case NL80211_TDLS_TEARDOWN: + case NL80211_TDLS_SETUP: + case NL80211_TDLS_DISCOVERY_REQ: + /* we do not support setup/teardown/discovery from driver */ + return -ENOTSUPP; + + default: + return -ENOTSUPP; + } + + /* enable or disable TDLS link */ + rStatus = kalIoctl(prGlueInfo, + TdlsexLinkCtrl, &rCmdLink, sizeof(TDLS_CMD_LINK_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s enable or disable link fail:%x\n", __func__, rStatus); + return -EINVAL; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen) +{ + UINT_32 u4Subcmd; + static void (*TdlsCmdTestFunc)(P_GLUE_INFO_T, UINT_8 *, UINT_32); + + /* parse TDLS sub-command */ + u4Subcmd = CmdStringDecParse(prInBuf, &prInBuf, &u4InBufLen); + DBGLOG(TDLS, INFO, " sub command = %u\n", (UINT32) u4Subcmd); + TdlsCmdTestFunc = NULL; + + /* handle different sub-command */ + switch (u4Subcmd) { +#if TDLS_CFG_CMD_TEST /* only for unit test */ + case TDLS_CMD_TEST_TX_FRAME: + /* simulate to send a TDLS frame */ + /* TdlsCmdTestTxFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxFrame; + break; + + case TDLS_CMD_TEST_TX_TDLS_FRAME: + /* simulate to send a TDLS frame from supplicant */ + /* TdlsCmdTestTxTdlsFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxTdlsFrame; + break; + + case TDLS_CMD_TEST_RCV_FRAME: + /* simulate to receive a TDLS frame */ + /* TdlsCmdTestRvFrame(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestRvFrame; + break; + + case TDLS_CMD_TEST_PEER_ADD: + /* simulate to add a TDLS peer */ + /* TdlsCmdTestAddPeer(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestAddPeer; + break; + + case TDLS_CMD_TEST_PEER_UPDATE: + /* simulate to update a TDLS peer */ + /* TdlsCmdTestUpdatePeer(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestUpdatePeer; + break; + + case TDLS_CMD_TEST_DATA_FRAME: + /* simulate to send a data frame to the peer */ + /* TdlsCmdTestDataSend(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDataSend; + break; + + case TDLS_CMD_TEST_RCV_NULL: + /* simulate to receive a QoS null frame from the peer */ + /* TdlsCmdTestNullRecv(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestNullRecv; + break; + + case TDLS_CMD_TEST_SKIP_TX_FAIL: + /* command firmware to skip tx fail case */ + /* TdlsCmdTestTxFailSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestTxFailSkip; + break; + + case TDLS_CMD_TEST_SKIP_KEEP_ALIVE: + /* command firmware to skip keep alive function */ + /* TdlsCmdTestKeepAliveSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestKeepAliveSkip; + break; + + case TDLS_CMD_TEST_SKIP_CHSW_TIMEOUT: + /* command firmware to skip channel switch timeout function */ + /* TdlsCmdTestChSwTimeoutSkip(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestChSwTimeoutSkip; + break; + + case TDLS_CMD_TEST_PROHIBIT_SET_IN_AP: + /* simulate to set Prohibited Bit in AP */ + /* TdlsCmdTestProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestProhibitedBitSet; + break; + + case TDLS_CMD_TEST_SCAN_DISABLE: + /* command to disable scan request to do channel switch */ + /* TdlsCmdTestScanCtrl(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestScanCtrl; + break; + + case TDLS_CMD_TEST_DATA_FRAME_CONT: + /* simulate to send a data frame to the peer periodically */ + /* TdlsCmdTestDataContSend(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDataContSend; + break; + + case TDLS_CMD_TEST_CH_SW_PROHIBIT_SET_IN_AP: + /* simulate to set channel switch Prohibited Bit in AP */ + /* TdlsCmdTestChSwProhibitedBitSet(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestChSwProhibitedBitSet; + break; + + case TDLS_CMD_TEST_DELAY: + /* delay a where */ + /* TdlsCmdTestDelay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestDelay; + break; + + case TDLS_CMD_TEST_PTI_TX_FAIL: + /* simulate the tx done fail for PTI */ + /* TdlsCmdTestPtiTxDoneFail(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdTestPtiTxDoneFail; + break; +#endif /* TDLS_CFG_CMD_TEST */ + + case TDLS_CMD_MIB_UPDATE: + /* update MIB parameters */ + /* TdlsCmdMibParamUpdate(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdMibParamUpdate; + break; + + case TDLS_CMD_UAPSD_CONF: + /* config UAPSD parameters */ + /* TdlsCmdUapsdConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdUapsdConf; + break; + + case TDLS_CMD_CH_SW_CONF: + /* enable or disable or start or stop channel switch function */ + /* TdlsCmdChSwConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdChSwConf; + break; + + case TDLS_CMD_SETUP_CONF: + /* config setup parameters */ + /* TdlsCmdSetupConf(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdSetupConf; + break; + + case TDLS_CMD_INFO: + /* display all TDLS information */ + /* TdlsCmdInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdInfoDisplay; + break; + + case TDLS_CMD_KEY_INFO: + /* display key information */ + /* TdlsCmdKeyInfoDisplay(prGlueInfo, prInBuf, u4InBufLen); */ + TdlsCmdTestFunc = TdlsCmdKeyInfoDisplay; + break; + + default: + break; + } + + if (TdlsCmdTestFunc != NULL) + TdlsCmdTestFunc(prGlueInfo, prInBuf, u4InBufLen); + +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to record a disconnection event. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure +* \param[in] fgIsTearDown TRUE: tear down +* \param[in] pucPeerMac Pointer to the MAC of the TDLS peer +* \param[in] fgIsFromUs TRUE: tear down is from us +* \param[in] u2ReasonCode Disconnection reason (TDLS_REASON_CODE) +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +TdlsexLinkHistoryRecord(GLUE_INFO_T *prGlueInfo, + BOOLEAN fgIsTearDown, UINT8 *pucPeerMac, BOOLEAN fgIsFromUs, UINT16 u2ReasonCode) +{ + /* sanity check */ + if ((prGlueInfo == NULL) || (pucPeerMac == NULL)) + return; + + DBGLOG(TDLS, INFO, + " %s: Rcv a inform from %pM %d %d\n", + __func__, pucPeerMac, fgIsFromUs, u2ReasonCode); + + /* record */ + TdlsLinkHistoryRecord(prGlueInfo, fgIsTearDown, pucPeerMac, fgIsFromUs, u2ReasonCode, NULL); +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to send a command to TDLS module. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexEventHandle(GLUE_INFO_T *prGlueInfo, UINT8 *prInBuf, UINT32 u4InBufLen) +{ + UINT32 u4EventId; + + /* sanity check */ + if ((prGlueInfo == NULL) || (prInBuf == NULL)) + return; /* shall not be here */ + + /* handle */ + u4EventId = *(UINT32 *) prInBuf; + u4InBufLen -= 4; + + DBGLOG(TDLS, INFO, " %s: Rcv a event: %d\n", __func__, u4EventId); + + switch (u4EventId) { + case TDLS_HOST_EVENT_TEAR_DOWN: + TdlsEventTearDown(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_TX_DONE: + TdlsEventTxDone(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_FME_STATUS: + TdlsEventFmeStatus(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + + case TDLS_HOST_EVENT_STATISTICS: + TdlsEventStatistics(prGlueInfo, prInBuf + 4, u4InBufLen); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return TDLS_STATUS_SUCCESS: do not set key and key infor. is queued + TDLS_STATUS_FAILURE: set key +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexKeyHandle(ADAPTER_T *prAdapter, PARAM_KEY_T *prNewKey) +{ + STA_RECORD_T *prStaRec; + + /* sanity check */ + if ((prAdapter == NULL) || (prNewKey == NULL)) + return TDLS_STATUS_FAILURE; + + /* + supplicant will set key before updating station & enabling the link so we need to + backup the key information and set key when link is enabled + */ + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prNewKey->arBSSID); + if ((prStaRec != NULL) && IS_TDLS_STA(prStaRec)) { + DBGLOG(TDLS, TRACE, " %s: [%pM] queue key (len=%d) until link is enabled\n", + __func__, prNewKey->arBSSID, (UINT32) prNewKey->u4KeyLength); + + if (prStaRec->ucStaState == STA_STATE_3) { + DBGLOG(TDLS, TRACE, " %s: [%pM] tear down the link due to STA_STATE_3\n", + __func__, prNewKey->arBSSID); + + /* re-key */ + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, + prStaRec->aucMacAddr, TRUE, + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, + TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); + return TDLS_STATUS_SUCCESS; + } + + /* backup the key */ + kalMemCopy(&prStaRec->rTdlsKeyTemp, prNewKey, sizeof(prStaRec->rTdlsKeyTemp)); + return TDLS_STATUS_SUCCESS; + } + + return TDLS_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexInit(ADAPTER_T *prAdapter) +{ + GLUE_INFO_T *prGlueInfo; + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + /* reset */ + kalMemZero(&prGlueInfo->rTdlsLink, sizeof(prGlueInfo->rTdlsLink)); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to get any peer is in power save. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \retval TRUE (at least one peer is in power save) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN TdlsexIsAnyPeerInPowerSave(ADAPTER_T *prAdapter) +{ + STA_RECORD_T *prStaRec; + UINT32 u4StaId, u4StartIdx; + + for (u4StaId = 0, u4StartIdx = 0; u4StaId < CFG_STA_REC_NUM; u4StaId++) { + /* list all TDLS peers */ + prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx); + if (prStaRec == NULL) + break; + + if (prStaRec->fgIsInPS == TRUE) { + DBGLOG(TDLS, TRACE, " yes, at least one peer is in ps\n"); + return TRUE; + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to enable or disable a TDLS link. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexLinkCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_LINK_T *prCmd; + BSS_INFO_T *prBssInfo; + STA_RECORD_T *prStaRec; + TDLS_LINK_HIS_OTHERS_T rHisOthers; + + /* sanity check */ + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_LINK_T); + prCmd = (TDLS_CMD_LINK_T *) pvSetBuffer; + + /* search old entry */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); + if (prStaRec == NULL) { + DBGLOG(TDLS, ERROR, " %s: cannot find the peer! %pM\n", + __func__, prCmd->aucPeerMac); + return TDLS_STATUS_FAILURE; + } + + if (prCmd->fgIsEnabled == TRUE) { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); + DBGLOG(TDLS, TRACE, " %s: NL80211_TDLS_ENABLE_LINK\n", __func__); + + /* update key information after cnmStaRecChangeState(STA_STATE_3) */ + prStaRec->fgTdlsInSecurityMode = FALSE; + + if (prStaRec->rTdlsKeyTemp.u4Length > 0) { + UINT_32 u4BufLen; /* no use */ + + DBGLOG(TDLS, INFO, " %s: key len=%d\n", + __func__, (UINT32) prStaRec->rTdlsKeyTemp.u4Length); + + /* + reminder the function that we are CIPHER_SUITE_CCMP, + do not change cipher type to CIPHER_SUITE_WEP128 + */ + _wlanoidSetAddKey(prAdapter, &prStaRec->rTdlsKeyTemp, + prStaRec->rTdlsKeyTemp.u4Length, FALSE, CIPHER_SUITE_CCMP, &u4BufLen); + + /* clear the temp key */ + prStaRec->fgTdlsInSecurityMode = TRUE; + kalMemZero(&prStaRec->rTdlsKeyTemp, sizeof(prStaRec->rTdlsKeyTemp)); + } + + /* check if we need to disable channel switch function */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + if (prBssInfo->fgTdlsIsChSwProhibited == TRUE) { + TDLS_CMD_CORE_T rCmd; + + kalMemZero(&rCmd, sizeof(TDLS_CMD_CORE_T)); + rCmd.Content.rCmdChSwConf.ucNetTypeIndex = prStaRec->ucNetTypeIndex; + rCmd.Content.rCmdChSwConf.fgIsChSwEnabled = FALSE; + kalMemCopy(rCmd.aucPeerMac, prStaRec->aucMacAddr, 6); + TdlsChSwConf(prAdapter, &rCmd, 0, 0); + + DBGLOG(TDLS, INFO, " %s: disable channel switch\n", __func__); + } + + TDLS_LINK_INCREASE(prGlueInfo); + + /* record link */ + if (prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11N) + rHisOthers.fgIsHt = TRUE; + else + rHisOthers.fgIsHt = FALSE; + + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, FALSE, + prStaRec->aucMacAddr, !prStaRec->flgTdlsIsInitiator, 0, &rHisOthers); + } else { + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + cnmStaRecFree(prAdapter, prStaRec, TRUE); /* release to other TDLS peers */ + DBGLOG(TDLS, TRACE, " %s: NL80211_TDLS_DISABLE_LINK\n", __func__); + + TDLS_LINK_DECREASE(prGlueInfo); +/* while(1); //sample debug */ + } + + /* work-around link count */ + if ((TDLS_LINK_COUNT(prGlueInfo) < 0) || (TDLS_LINK_COUNT(prGlueInfo) > 1)) { + /* ERROR case: work-around to recount by searching all station records */ + UINT32 u4Idx; + + TDLS_LINK_COUNT_RESET(prGlueInfo); + + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { + prStaRec = &prAdapter->arStaRec[u4Idx]; + + if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) + TDLS_LINK_INCREASE(prGlueInfo); + } + + if (TDLS_LINK_COUNT(prGlueInfo) > 1) { + /* number of links is still > 1 */ + DBGLOG(TDLS, INFO, " %s: cTdlsLinkCnt %d > 1?\n", + __func__, TDLS_LINK_COUNT(prGlueInfo)); + + TDLS_LINK_COUNT_RESET(prGlueInfo); + + /* free all TDLS links */ + for (u4Idx = 0; u4Idx < CFG_STA_REC_NUM; u4Idx++) { + prStaRec = &prAdapter->arStaRec[u4Idx]; + + if (prStaRec->fgIsInUse && IS_TDLS_STA(prStaRec)) + cnmStaRecFree(prAdapter, prStaRec, TRUE); + } + + /* maybe inform supplicant ? */ + } + } + + /* display TDLS link history */ + TdlsInfoDisplay(prAdapter, NULL, 0, NULL); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to send a TDLS action data frame. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexMgmtCtrl(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_MGMT_TX_INFO *prMgmtTxInfo; + STA_RECORD_T *prStaRec; + + /* sanity check */ + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_MGMT_TX_INFO); + prMgmtTxInfo = (TDLS_MGMT_TX_INFO *) pvSetBuffer; + + switch (prMgmtTxInfo->ucActionCode) { + case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: + prStaRec = NULL; + break; + + case TDLS_FRM_ACTION_SETUP_REQ: + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer); + if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3)) { + /* rekey? we reject re-setup link currently */ + /* TODO: Still can setup link during rekey */ + + /* + return success to avoid supplicant clear TDLS entry; + Or we cannot send out any TDLS tear down frame to the peer + */ + DBGLOG(TDLS, TRACE, " %s: skip new setup on the exist link!\n", __func__); + return TDLS_STATUS_SUCCESS; + } + + prStaRec = NULL; + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_TEARDOWN: + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMgmtTxInfo->aucPeer); +#if 0 /* in some cases, the prStaRec is still NULL */ + /* + EX: if a peer sends us a TDLS setup request with wrong BSSID, + supplicant will not call TdlsexPeerAdd() to create prStaRec and + supplicant will send a TDLS setup response with status code 7. + + So in the case, prStaRec will be NULL. + */ + if (prStaRec == NULL) { + DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); + return -EINVAL; + } +#endif + break; + + /* + TODO: Discovery response frame + Note that the TDLS Discovery Response frame is not a TDLS frame but a 11 + Public Action frame. + In WiFi TDLS Tech Minutes June 8 2010.doc, + a public action frame (i.e. it is no longer an encapsulated data frame) + */ + + default: + DBGLOG(TDLS, ERROR, + " %s: wrong action_code %d!\n", __func__, prMgmtTxInfo->ucActionCode); + return TDLS_STATUS_FAILURE; + } + + /* send the TDLS data frame */ + if (prStaRec != NULL) { + DBGLOG(TDLS, INFO, " %s: [%pM] ps=%d status=%d\n", + __func__, prStaRec->aucMacAddr, + prStaRec->fgIsInPS, prMgmtTxInfo->u2StatusCode); + + if (prMgmtTxInfo->ucActionCode == TDLS_FRM_ACTION_TEARDOWN) { + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prMgmtTxInfo->aucPeer, + TRUE, prMgmtTxInfo->u2StatusCode, NULL); + } + } + + return TdlsDataFrameSend(prAdapter, + prStaRec, + prMgmtTxInfo->aucPeer, + prMgmtTxInfo->ucActionCode, + prMgmtTxInfo->ucDialogToken, + prMgmtTxInfo->u2StatusCode, + (UINT_8 *) prMgmtTxInfo->aucSecBuf, prMgmtTxInfo->u4SecBufLen); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to add a peer record. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexPeerAdd(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_PEER_ADD_T *prCmd; + BSS_INFO_T *prAisBssInfo; + STA_RECORD_T *prStaRec; + UINT_8 ucNonHTPhyTypeSet; + UINT32 u4StartIdx; + OS_SYSTIME rCurTime; + + /* sanity check */ + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); + prCmd = (TDLS_CMD_PEER_ADD_T *) pvSetBuffer; + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + u4StartIdx = 0; + + /* search old entry */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); + + /* check if any TDLS link exists because we only support one TDLS link currently */ + if (prStaRec == NULL) { + /* the MAC is new peer */ + prStaRec = cnmStaTheTypeGet(prAdapter, NETWORK_TYPE_AIS_INDEX, STA_TYPE_TDLS_PEER, &u4StartIdx); + + if (prStaRec != NULL) { + /* a building TDLS link exists */ + DBGLOG(TDLS, ERROR, + " %s: one TDLS link setup [%pM] is going...\n", + __func__, prStaRec->aucMacAddr); + + if (prStaRec->ucStaState != STA_STATE_3) { + /* check timeout */ + GET_CURRENT_SYSTIME(&rCurTime); + + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsSetupStartTime, + SEC_TO_SYSTIME(TDLS_SETUP_TIMEOUT_SEC))) { + /* free the StaRec */ + cnmStaRecFree(prAdapter, prStaRec, TRUE); + + DBGLOG(TDLS, ERROR, + " %s: free going TDLS link setup [%pM]\n", + __func__, (prStaRec->aucMacAddr)); + + /* handle new setup */ + prStaRec = NULL; + } else + return TDLS_STATUS_FAILURE; + } else { + /* the TDLS is built and works fine, reject new one */ + return TDLS_STATUS_FAILURE; + } + } + } else { + if (prStaRec->ucStaState == STA_STATE_3) { + /* the peer exists, maybe TPK lifetime expired, supplicant wants to renew key */ + TdlsLinkHistoryRecord(prAdapter->prGlueInfo, TRUE, + prStaRec->aucMacAddr, TRUE, + TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_REKEY, NULL); + + /* 16 Nov 21:49 2012 http://permalink.gmane.org/gmane.linux.kernel.wireless.general/99712 */ + cfg80211_tdls_oper_request(prAdapter->prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, + TDLS_REASON_CODE_UNSPECIFIED, GFP_ATOMIC); + + DBGLOG(TDLS, TRACE, + " %s: re-setup link for [%pM] maybe re-key?\n", + __func__, (prStaRec->aucMacAddr)); + return TDLS_STATUS_FAILURE; + } + } + + /* + create new entry if not exist + + 1. we are initiator + (1) send TDLS setup request + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + create a station record with STA_STATE_1. + (2) got TDLS setup response and send TDLS setup confirm + wpa_tdls_enable_link() + update a station record with STA_STATE_3. + + 2. we are responder + (1) got TDLS setup request + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + create a station record with STA_STATE_1. + (2) send TDLS setup response + (3) got TDLS setup confirm + wpa_tdls_enable_link() + update a station record with STA_STATE_3. + */ + if (prStaRec == NULL) { + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX); + + if (prStaRec == NULL) { + /* shall not be here */ + DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, prCmd->aucPeerMac); + +/* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); */ + } else { +#if 0 + if ((prStaRec->ucStaState > STA_STATE_1) && (IS_TDLS_STA(prStaRec))) { + /* + test plan: The STAUT should locally tear down existing TDLS direct link and + respond with Set up Response frame. + */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } +#endif + } + + /* reference to bssCreateStaRecFromBssDesc() and use our best capability */ + /* reference to assocBuildReAssocReqFrameCommonIEs() to fill elements */ + + /* prStaRec->u2CapInfo */ + /* TODO: Need to parse elements from setup request frame */ + prStaRec->u2OperationalRateSet = prAisBssInfo->u2OperationalRateSet; + prStaRec->u2BSSBasicRateSet = prAisBssInfo->u2BSSBasicRateSet; + prStaRec->u2DesiredNonHTRateSet = prAdapter->rWifiVar.ucAvailablePhyTypeSet; + prStaRec->ucPhyTypeSet = prAisBssInfo->ucPhyTypeSet; + prStaRec->eStaType = STA_TYPE_TDLS_PEER; + + prStaRec->ucDesiredPhyTypeSet = /*prStaRec->ucPhyTypeSet & */ + prAdapter->rWifiVar.ucAvailablePhyTypeSet; + ucNonHTPhyTypeSet = prStaRec->ucDesiredPhyTypeSet & PHY_TYPE_SET_802_11ABG; + + /* check for Target BSS's non HT Phy Types */ + if (ucNonHTPhyTypeSet) { + if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_ERP) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_ERP_INDEX; + } else if (ucNonHTPhyTypeSet & PHY_TYPE_BIT_OFDM) { + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_OFDM_INDEX; + } else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + } + + prStaRec->fgHasBasicPhyType = TRUE; + } else { + /* use mandatory for 11N only BSS */ +/* ASSERT(prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N); */ + + prStaRec->ucNonHTBasicPhyType = PHY_TYPE_HR_DSSS_INDEX; + prStaRec->fgHasBasicPhyType = FALSE; + } + + /* update non HT Desired Rate Set */ + { + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prStaRec->u2DesiredNonHTRateSet = + (prStaRec->u2OperationalRateSet & prConnSettings->u2DesiredNonHTRateSet); + } + +#if 0 /* TdlsexPeerAdd() will be called before we receive setup rsp in TdlsexRxFrameHandle() */ + /* check if the add is from the same peer in the 1st unhandled setup request frame */ + DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", + __func__, prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac); + + if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { + /* copy the HT capability from its setup request */ + kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); + + prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); + + /* reset backup */ + kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); + kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); + + DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); + } +#endif + + /* update WMM: must support due to UAPSD in TDLS link */ + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = TRUE; + + /* update station record to firmware */ + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + + /* update time */ + GET_CURRENT_SYSTIME(&prStaRec->rTdlsSetupStartTime); + + DBGLOG(TDLS, INFO, " %s: create a peer [%pM]\n", + __func__, (prStaRec->aucMacAddr)); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update a peer record. +* +* \param[in] prAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexPeerUpdate(ADAPTER_T *prAdapter, VOID *pvSetBuffer, UINT_32 u4SetBufferLen, UINT_32 *pu4SetInfoLen) +{ + GLUE_INFO_T *prGlueInfo; + TDLS_CMD_PEER_UPDATE_T *prCmd; + BSS_INFO_T *prAisBssInfo; + STA_RECORD_T *prStaRec; + IE_HT_CAP_T *prHtCap; + + /* sanity check */ + DBGLOG(TDLS, INFO, " %s\n", __func__); + + if ((prAdapter == NULL) || (pvSetBuffer == NULL) || (pu4SetInfoLen == NULL)) { + DBGLOG(TDLS, ERROR, " %s: sanity fail!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + *pu4SetInfoLen = sizeof(TDLS_CMD_PEER_ADD_T); + prCmd = (TDLS_CMD_PEER_UPDATE_T *) pvSetBuffer; + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + /* search old entry */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prCmd->aucPeerMac); + + /* + create new entry if not exist + + 1. we are initiator + (1) send TDLS setup request + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + create a station record with STA_STATE_1. + (2) got TDLS setup response and send TDLS setup confirm + wpa_tdls_enable_link() + update a station record with STA_STATE_3. + + 2. we are responder + (1) got TDLS setup request + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, NULL, 0); + create a station record with STA_STATE_1. + (2) send TDLS setup response + (3) got TDLS setup confirm + wpa_tdls_enable_link() + update a station record with STA_STATE_3. + */ + if ((prStaRec == NULL) || (prStaRec->fgIsInUse == 0)) { + DBGLOG(TDLS, ERROR, " %s: cannot find the peer!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + DBGLOG(TDLS, INFO, " %s: update a peer [%pM] %d -> %d, 0x%x\n", + __func__, (prStaRec->aucMacAddr), + prStaRec->ucStaState, STA_STATE_3, prStaRec->eStaType); + + if (!IS_TDLS_STA(prStaRec)) { + DBGLOG(TDLS, ERROR, " %s: peer is not TDLS one!\n", __func__); + return TDLS_STATUS_FAILURE; + } + + /* check if the add is from the same peer in the 1st unhandled setup request frame */ + DBGLOG(TDLS, INFO, " %s: [%pM] [%pM]\n", + __func__, (prGlueInfo->aucTdlsHtPeerMac), (prCmd->aucPeerMac)); + + if (kalMemCmp(prGlueInfo->aucTdlsHtPeerMac, prCmd->aucPeerMac, 6) == 0) { + /* copy the HT capability from its setup request */ + kalMemCopy(&prStaRec->rTdlsHtCap, &prGlueInfo->rTdlsHtCap, sizeof(IE_HT_CAP_T)); + + prStaRec->ucPhyTypeSet |= PHY_TYPE_SET_802_11N; + prStaRec->u2DesiredNonHTRateSet |= BIT(RATE_HT_PHY_INDEX); + + /* reset backup */ + kalMemZero(&prGlueInfo->rTdlsHtCap, sizeof(prStaRec->rTdlsHtCap)); + kalMemZero(prGlueInfo->aucTdlsHtPeerMac, sizeof(prGlueInfo->aucTdlsHtPeerMac)); + + DBGLOG(TDLS, INFO, " %s: peer is a HT device\n", __func__); + } + + /* update the record join time. */ + GET_CURRENT_SYSTIME(&prStaRec->rUpdateTime); + + /* update Station Record - Status/Reason Code */ + prStaRec->u2StatusCode = prCmd->u2StatusCode; + + /* prStaRec->ucStaState shall be STA_STATE_1 */ + + prStaRec->u2CapInfo = prCmd->u2Capability; +/* prStaRec->u2OperationalRateSet */ + prStaRec->u2AssocId = 0; /* no use */ + prStaRec->u2ListenInterval = 0; /* unknown */ +/* prStaRec->ucDesiredPhyTypeSet */ +/* prStaRec->u2DesiredNonHTRateSet */ +/* prStaRec->u2BSSBasicRateSet */ +/* prStaRec->ucMcsSet */ +/* prStaRec->fgSupMcs32 */ +/* prStaRec->u2HtCapInfo */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsUapsdSupported = (prCmd->UapsdBitmap == 0) ? FALSE : TRUE; +/* prStaRec->ucAmpduParam */ +/* prStaRec->u2HtExtendedCap */ + prStaRec->u4TxBeamformingCap = 0; /* no use */ + prStaRec->ucAselCap = 0; /* no use */ + prStaRec->ucRCPI = 0; + prStaRec->ucBmpTriggerAC = prCmd->UapsdBitmap; + prStaRec->ucBmpDeliveryAC = prCmd->UapsdBitmap; + prStaRec->ucUapsdSp = prCmd->UapsdMaxSp; + + /* update HT */ +#if (TDLS_CFG_HT_SUP == 1) + if (prCmd->fgIsSupHt == FALSE) { + /* no HT IE is from supplicant so we use the backup */ + prHtCap = (IE_HT_CAP_T *) &prStaRec->rTdlsHtCap; + + DBGLOG(TDLS, INFO, " %s: [%pM] update ht ie 0x%x\n", + __func__, (prStaRec->aucMacAddr), prHtCap->ucId); + + if (prHtCap->ucId == ELEM_ID_HT_CAP) { + prStaRec->ucMcsSet = prHtCap->rSupMcsSet.aucRxMcsBitmask[0]; + prStaRec->fgSupMcs32 = (prHtCap->rSupMcsSet.aucRxMcsBitmask[32 / 8] & BIT(0)) ? TRUE : FALSE; + + prStaRec->u2HtCapInfo = prHtCap->u2HtCapInfo; + prStaRec->ucAmpduParam = prHtCap->ucAmpduParam; + prStaRec->u2HtExtendedCap = prHtCap->u2HtExtendedCap; + prStaRec->u4TxBeamformingCap = prHtCap->u4TxBeamformingCap; + prStaRec->ucAselCap = prHtCap->ucAselCap; + prStaRec->ucDesiredPhyTypeSet |= PHY_TYPE_SET_802_11N; + } + } else { + /* TODO: use the HT IE from supplicant */ + } +#endif /* TDLS_CFG_HT_SUP */ + + DBGLOG(TDLS, INFO, " %s: UAPSD 0x%x %d MCS=0x%x\n", + __func__, prCmd->UapsdBitmap, prCmd->UapsdMaxSp, prStaRec->ucMcsSet); + +/* cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_3); */ + + DBGLOG(TDLS, INFO, " %s: update a peer [%pM]\n", + __func__, (prStaRec->aucMacAddr)); + + return TDLS_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to check if we need to drop a TDLS action frame. +* +* \param[in] *pPkt Pointer to the struct sk_buff->data. +* \param[in] +* \param[in] +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN TdlsexRxFrameDrop(GLUE_INFO_T *prGlueInfo, UINT_8 *pPkt) +{ + ADAPTER_T *prAdapter; + UINT8 ucActionId; + + /* sanity check */ + if ((pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) + return FALSE; /* not TDLS data frame htons(0x890d) */ + +#if 0 /* supplicant handles this check */ + if (prStaRec == NULL) + return FALSE; /* shall not be here */ + + DBGLOG(TDLS, INFO, + " %s: Rcv a TDLS action frame (id=%d) %d %d\n", + __func__, *(pPkt + 13 + 4), prStaRec->fgTdlsIsProhibited, fgIsPtiTimeoutSkip); + + /* check if TDLS Prohibited bit is set in AP's beacon */ + if (prStaRec->fgTdlsIsProhibited == TRUE) + return TRUE; +#endif + + ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ + + if (fgIsPtiTimeoutSkip == TRUE) { + /* also skip any tear down frame from the peer */ + if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) + return TRUE; + } + + prAdapter = prGlueInfo->prAdapter; + DBGLOG(TDLS, INFO, + " %s: Rcv a TDLS action frame %d (%u)\n", + __func__, ucActionId, (UINT32) prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem); + + if (ucActionId == TDLS_FRM_ACTION_TEARDOWN) { + DBGLOG(TDLS, WARN, " %s: Rcv a TDLS tear down frame %d, will DISABLE link\n", + __func__, *(pPkt + 13 + 4)); /* reason code */ + + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, pPkt + 6, FALSE, *(pPkt + 13 + 4), NULL); + + /* inform tear down to supplicant only in OPEN/NONE mode */ + /* + we need to tear down the link manually; or supplicant will display + "No FTIE in TDLS Teardown" and it will not tear down the link + */ + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + pPkt + 6, TDLS_FRM_ACTION_TEARDOWN, *(pPkt + 13 + 4), GFP_ATOMIC); + } +#if 0 /* pass all to supplicant except same thing is handled in supplicant */ + if (((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI) || + ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_REQ) || + ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_CHAN_SWITCH_RSP) || + ((*(pPkt + 13 + 3)) == TDLS_FRM_ACTION_PTI_RSP)) { + return TRUE; + } +#endif + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to parse some IEs in the setup frame from the peer. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] pPkt Pointer to the ethernet packet +* +* \retval None +* +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexRxFrameHandle(GLUE_INFO_T *prGlueInfo, UINT8 *pPkt, UINT16 u2PktLen) +{ + ADAPTER_T *prAdapter; + STA_RECORD_T *prStaRec; + UINT8 ucActionId; + UINT8 *pucPeerMac, ucElmId, ucElmLen; + INT16 s2FmeLen; + + /* sanity check */ + if ((prGlueInfo == NULL) || (pPkt == NULL) || (*(pPkt + 12) != 0x89) || (*(pPkt + 13) != 0x0d)) + return; + + ucActionId = *(pPkt + 12 + 2 + 2); /* skip dst, src MAC, type, payload type, category */ + + if ((ucActionId != TDLS_FRM_ACTION_SETUP_REQ) && (ucActionId != TDLS_FRM_ACTION_SETUP_RSP)) + return; + + /* init */ + prAdapter = prGlueInfo->prAdapter; + pucPeerMac = pPkt + 6; + s2FmeLen = (INT16) u2PktLen; + + DBGLOG(TDLS, TRACE, + " %s: get a setup frame %d from %pM\n", + __func__, ucActionId, (pucPeerMac)); + + if (ucActionId == TDLS_FRM_ACTION_SETUP_REQ) + pPkt += 12 + 2 + 2 + 1 + 1 + 2; /* skip action, dialog token, capability */ + else + pPkt += 12 + 2 + 2 + 1 + 2 + 1 + 2; /* skip action, status code, dialog token, capability */ + + /* check station record */ + prStaRec = cnmGetStaRecByAddress(prGlueInfo->prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, pucPeerMac); + + if (prStaRec == NULL) { + prStaRec = cnmStaRecAlloc(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX); + + if (prStaRec == NULL) { + /* TODO: only one TDLS entry, need to free old one if timeout */ + DBGLOG(TDLS, ERROR, " %s: alloc prStaRec fail!\n", __func__); + return; + } + + /* init the prStaRec */ + /* prStaRec will be zero first in cnmStaRecAlloc() */ + COPY_MAC_ADDR(prStaRec->aucMacAddr, pucPeerMac); + + cnmStaRecChangeState(prAdapter, prStaRec, STA_STATE_1); + } + + /* backup HT IE to station record */ + /* TODO: Maybe our TDLS only supports non-11n */ + while (s2FmeLen > 0) { + ucElmId = *pPkt++; + ucElmLen = *pPkt++; + + switch (ucElmId) { + case ELEM_ID_HT_CAP: /* 0x2d */ + /* backup the HT IE of 1st unhandled setup request frame */ + if (prGlueInfo->rTdlsHtCap.ucId == 0x00) { + kalMemCopy(prGlueInfo->aucTdlsHtPeerMac, pucPeerMac, 6); + kalMemCopy(&prGlueInfo->rTdlsHtCap, pPkt - 2, ucElmLen + 2); + + /* + cannot backup in prStaRec; or + + 1. we build a TDLS link + 2. peer re-sends setup req + 3. we backup HT cap element + 4. supplicant disables the link + 5. we clear the prStaRec + */ + + DBGLOG(TDLS, TRACE, + " %s: %pM: find a HT IE\n", + __func__, (pucPeerMac)); + } + return; + + case ELEM_ID_EXTENDED_CAP: + /* TODO: backup the extended capability IE */ + break; + } + + pPkt += ucElmLen; + s2FmeLen -= (2 + ucElmLen); + } +} + +/*----------------------------------------------------------------------------*/ +/*! \brief This routine is called to get the TDLS station record. +* +* \param[in] prGlueInfo Pointer to the Adapter structure +* \param[in] prInBuf A pointer to the command string buffer +* \param[in] u4InBufLen The length of the buffer +* \param[out] None +* +* \retval TDLS_STATUS_SUCCESS: this is TDLS packet +* TDLS_STATUS_FAILURE: this is not TDLS packet +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS TdlsexStaRecIdxGet(ADAPTER_T *prAdapter, MSDU_INFO_T *prMsduInfo) +{ + BSS_INFO_T *prBssInfo; + STA_RECORD_T *prStaRec; + TDLS_STATUS Status; + + /* sanity check */ + if ((prAdapter == NULL) || (prMsduInfo == NULL)) + return TDLS_STATUS_FAILURE; + + if (prAdapter->prGlueInfo == NULL) + return TDLS_STATUS_FAILURE; + if (TDLS_IS_NO_LINK_GOING(prAdapter->prGlueInfo)) + return TDLS_STATUS_FAILURE; + + /* init */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + Status = TDLS_STATUS_SUCCESS; + + /* get record by ether dest */ + prStaRec = cnmGetStaRecByAddress(prAdapter, (UINT_8) NETWORK_TYPE_AIS_INDEX, prMsduInfo->aucEthDestAddr); + + /* + TDLS Setup Request frames, TDLS Setup Response frames and TDLS Setup Confirm + frames shall be transmitted through the AP and shall not be transmitted to a group + address. + + 1. In first time, prStaRec == NULL or prStaRec->ucStaState != STA_STATE_3, + we will send them to AP; + 2. When link is still on, if you command to send TDLS setup from supplicant, + supplicant will DISABLE LINK first, prStaRec will be NULL then send TDLS + setup frame to the peer. + */ + + do { + if ((prStaRec != NULL) && (prStaRec->ucStaState == STA_STATE_3) && (IS_TDLS_STA(prStaRec))) { + /* + TDLS Test Case 5.3 Tear Down + Automatically sends TDLS Teardown frame to STA 2 via AP + + 11.21.5 TDLS Direct Link Teardown + The TDLS Teardown frame shall be sent over the direct path and the reason + code shall be set to "TDLS 40 direct link teardown for unspecified reason", + except when the TDLS peer STA is unreachable via the TDLS direct link, + in which case, the TDLS Teardown frame shall be sent through the AP and + the reason code shall be set to "TDLS direct link teardown due to TDLS peer + STA unreachable via the TDLS direct link". + */ + /* if (prStaRec->fgIsInPS == TRUE) */ + /* + check if the packet is tear down: + we do not want to use PTI to indicate the tear down and + we want to send the tear down to AP then AP help us to send it + */ + struct sk_buff *prSkb; + UINT8 *pEth; + UINT_16 u2EtherTypeLen; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + if (prSkb != NULL) { + UINT8 ucActionCode, ucReasonCode; + + /* init */ + pEth = prSkb->data; + u2EtherTypeLen = (pEth[ETH_TYPE_LEN_OFFSET] << 8) | + (pEth[ETH_TYPE_LEN_OFFSET + 1]); + ucActionCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 3]; + ucReasonCode = pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] | + (pEth[ETH_TYPE_LEN_OFFSET + 1 + 5] << 8); + + /* TDLS_REASON_CODE_UNREACHABLE: keep alive fail or PTI timeout */ + if ((u2EtherTypeLen == TDLS_FRM_PROT_TYPE) && + (ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && + (ucReasonCode == TDLS_REASON_CODE_UNREACHABLE)) { + /* + when we cannot reach the peer, + we need AP's help to send the tear down frame + */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prStaRec = prBssInfo->prStaRecOfAP; + if (prStaRec == NULL) { + Status = TDLS_STATUS_FAILURE; + break; + } +#if 0 + /* change status code */ + pEth[ETH_TYPE_LEN_OFFSET + 1 + 4] = TDLS_REASON_CODE_UNREACHABLE; +#endif + } + } + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + } + } while (FALSE); + + DBGLOG(TDLS, INFO, " %s: (Status=%x) [%pM] ucStaRecIndex = %d!\n", + __func__, (INT32) Status, (prMsduInfo->aucEthDestAddr), + prMsduInfo->ucStaRecIndex); + return Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to check if we suffer timeout for TX quota empty case. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexTxQuotaCheck(GLUE_INFO_T *prGlueInfo, STA_RECORD_T *prStaRec, UINT8 FreeQuota) +{ + OS_SYSTIME rCurTime; + + /* sanity check */ + if (!IS_TDLS_STA(prStaRec)) + return; + + if (FreeQuota != 0) { + /* reset timeout */ + prStaRec->rTdlsTxQuotaEmptyTime = 0; + return; + } + + /* work-around: check if the no free quota case is too long */ + GET_CURRENT_SYSTIME(&rCurTime); + + if (prStaRec->rTdlsTxQuotaEmptyTime == 0) { + prStaRec->rTdlsTxQuotaEmptyTime = rCurTime; + } else { + if (CHECK_FOR_TIMEOUT(rCurTime, prStaRec->rTdlsTxQuotaEmptyTime, + SEC_TO_SYSTIME(TDLS_TX_QUOTA_EMPTY_TIMEOUT))) { + /* tear down the link */ + DBGLOG(TDLS, WARN, + " %s: [%pM] TX quota empty timeout!\n", + __func__, (prStaRec->aucMacAddr)); + + /* record disconnect history */ + TdlsLinkHistoryRecord(prGlueInfo, TRUE, prStaRec->aucMacAddr, + TRUE, TDLS_REASON_CODE_MTK_DIS_BY_US_DUE_TO_TX_QUOTA_EMPTY, NULL); + + /* inform tear down to supplicant only in OPEN/NONE mode */ + /* + we need to tear down the link manually; or supplicant will display + "No FTIE in TDLS Teardown" and it will not tear down the link + */ + cfg80211_tdls_oper_request(prGlueInfo->prDevHandler, + prStaRec->aucMacAddr, TDLS_FRM_ACTION_TEARDOWN, + TDLS_REASON_CODE_UNREACHABLE, GFP_ATOMIC); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to un-initialize variables in TDLS. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID TdlsexUninit(ADAPTER_T *prAdapter) +{ +#if TDLS_CFG_CMD_TEST + cnmTimerStopTimer(prAdapter, &rTdlsTimerTestDataSend); +#endif /* TDLS_CFG_CMD_TEST */ +} + +#endif /* CFG_SUPPORT_TDLS */ + +/* End of tdls.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c new file mode 100644 index 0000000000000..5450cbb651837 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/tdls_com.c @@ -0,0 +1,741 @@ +/* +** Id: tdls_com.c#1 +*/ + +/*! \file tdls_com.c + \brief This file includes IEEE802.11z TDLS main support. +*/ + +/* +** Log: tdls_com.c + * + * 11 13 2013 vend_samp.lin + * NULL + * Initial version. + */ + +/******************************************************************************* + * C O M P I L E R F L A G S + ******************************************************************************** + */ + +/******************************************************************************* + * E X T E R N A L R E F E R E N C E S + ******************************************************************************** + */ + +#include "precomp.h" + +#if (CFG_SUPPORT_TDLS == 1) +#include "tdls.h" + + /******************************************************************************* + * C O N S T A N T S + ******************************************************************************** + */ + + /******************************************************************************* + * F U N C T I O N D E C L A R A T I O N S + ******************************************************************************** + */ + + /******************************************************************************* + * P R I V A T E D A T A + ******************************************************************************** + */ + + /******************************************************************************* + * P R I V A T E F U N C T I O N S + ******************************************************************************** + */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to append general IEs. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] prStaRec Pointer to the STA_RECORD_T structure. +* \param[in] u2StatusCode Status code. +* \param[in] pPkt Pointer to the frame body +* +* \retval append length +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 TdlsFrameGeneralIeAppend(ADAPTER_T *prAdapter, STA_RECORD_T *prStaRec, UINT_16 u2StatusCode, UINT_8 *pPkt) +{ + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + UINT_32 u4NonHTPhyType; + UINT_16 u2SupportedRateSet; + UINT_8 aucAllSupportedRates[RATE_NUM] = { 0 }; + UINT_8 ucAllSupportedRatesLen; + UINT_8 ucSupRatesLen; + UINT_8 ucExtSupRatesLen; + UINT_32 u4PktLen, u4IeLen; + BOOLEAN fg40mAllowed; + + /* reference to assocBuildReAssocReqFrameCommonIEs() */ + + /* init */ + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + + /* 3. Frame Formation - (5) Supported Rates element */ + /* use all sup rate we can support */ + if (prStaRec != NULL) + u4NonHTPhyType = prStaRec->ucNonHTBasicPhyType; + else + u4NonHTPhyType = PHY_TYPE_ERP_INDEX; /* default */ + + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + + if (prStaRec != NULL) { + u2SupportedRateSet &= prStaRec->u2OperationalRateSet; + + if (u2SupportedRateSet == 0) + u2SupportedRateSet = rNonHTPhyAttributes[u4NonHTPhyType].u2SupportedRateSet; + } + + rateGetDataRatesFromRateSet(u2SupportedRateSet, + prBssInfo->u2BSSBasicRateSet, aucAllSupportedRates, &ucAllSupportedRatesLen); + + ucSupRatesLen = ((ucAllSupportedRatesLen > ELEM_MAX_LEN_SUP_RATES) ? + ELEM_MAX_LEN_SUP_RATES : ucAllSupportedRatesLen); + + ucExtSupRatesLen = ucAllSupportedRatesLen - ucSupRatesLen; + + if (ucSupRatesLen) { + SUP_RATES_IE(pPkt)->ucId = ELEM_ID_SUP_RATES; + SUP_RATES_IE(pPkt)->ucLength = ucSupRatesLen; + kalMemCopy(SUP_RATES_IE(pPkt)->aucSupportedRates, aucAllSupportedRates, ucSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (7) Extended sup rates element */ + if (ucExtSupRatesLen) { + + EXT_SUP_RATES_IE(pPkt)->ucId = ELEM_ID_EXTENDED_SUP_RATES; + EXT_SUP_RATES_IE(pPkt)->ucLength = ucExtSupRatesLen; + + kalMemCopy(EXT_SUP_RATES_IE(pPkt)->aucExtSupportedRates, + &aucAllSupportedRates[ucSupRatesLen], ucExtSupRatesLen); + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (8) Supported channels element */ + /* + The Supported channels element is included in Request frame and also in Response + frame if Status Code 0 (successful). + */ + if (u2StatusCode == 0) { + SUPPORTED_CHANNELS_IE(pPkt)->ucId = ELEM_ID_SUP_CHS; + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 2; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[0] = 1; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[1] = 11; + +#if CFG_SUPPORT_DFS + if (prAdapter->fgEnable5GBand == TRUE) { + /* 5G support */ + SUPPORTED_CHANNELS_IE(pPkt)->ucLength = 10; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[2] = 36; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[3] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[4] = 52; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[5] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[6] = 149; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[7] = 4; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[8] = 165; + SUPPORTED_CHANNELS_IE(pPkt)->ucChannelNum[9] = 4; + } +#endif /* CFG_SUPPORT_DFS */ + + u4IeLen = IE_SIZE(pPkt); + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (14) HT capabilities element */ + + /* no need to check AP capability */ +/* if ((prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_SET_802_11N) && */ + + /* + after we set ucPhyTypeSet to PHY_TYPE_SET_802_11N in TdlsexRxFrameHandle(), + supplicant will disable link if exists and we will clear prStaRec. + + finally, prStaRec->ucPhyTypeSet will also be 0 + + so we have a fix in TdlsexPeerAdd(). + */ + if (!prStaRec || (prStaRec->ucPhyTypeSet & PHY_TYPE_SET_802_11N)) { + /* TODO: prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode */ +#if 0 /* always support */ + if (prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode == CONFIG_BW_20M) + fg40mAllowed = FALSE; + else +#endif + fg40mAllowed = TRUE; + + u4IeLen = rlmFillHtCapIEByParams(fg40mAllowed, + prAdapter->rWifiVar.rConnSettings.fgRxShortGIDisabled, + prAdapter->rWifiVar.u8SupportRxSgi20, + prAdapter->rWifiVar.u8SupportRxSgi40, + prAdapter->rWifiVar.u8SupportRxGf, + prAdapter->rWifiVar.u8SupportRxSTBC, prBssInfo->eCurrentOPMode, pPkt); + + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + /* 3. Frame Formation - (17) WMM Information element */ + + /* always support */ +/* if (prAdapter->rWifiVar.fgSupportQoS) */ + + { + /* force to support all UAPSD in TDLS link */ + u4IeLen = mqmGenerateWmmInfoIEByParam(TRUE /*prAdapter->rWifiVar.fgSupportUAPSD */ , + 0xf /*prPmProfSetupInfo->ucBmpDeliveryAC */ , + 0xf /*prPmProfSetupInfo->ucBmpTriggerAC */ , + WMM_MAX_SP_LENGTH_ALL /*prPmProfSetupInfo->ucUapsdSp */ , + pPkt); + + pPkt += u4IeLen; + u4PktLen += u4IeLen; + } + + return u4PktLen; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to transmit a TDLS data frame (setup req/rsp/confirm and tear down). +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* \param[in] prStaRec Pointer to the STA_RECORD_T structure. +* \param[in] pPeerMac Pointer to the MAC of the TDLS peer +* \param[in] ucActionCode TDLS Action +* \param[in] ucDialogToken Dialog token +* \param[in] u2StatusCode Status code +* \param[in] pAppendIe Others IEs (here are security IEs from supplicant) +* \param[in] AppendIeLen IE length of others IEs +* +* \retval TDLS_STATUS_xx +*/ +/*----------------------------------------------------------------------------*/ +TDLS_STATUS +TdlsDataFrameSend(ADAPTER_T *prAdapter, + STA_RECORD_T *prStaRec, + UINT_8 *pPeerMac, + UINT_8 ucActionCode, + UINT_8 ucDialogToken, UINT_16 u2StatusCode, UINT_8 *pAppendIe, UINT_32 AppendIeLen) +{ +#define LR_TDLS_FME_FIELD_FILL(__Len) \ +do { \ + pPkt += __Len; \ + u4PktLen += __Len; \ +} while (0) + + GLUE_INFO_T *prGlueInfo; + BSS_INFO_T *prBssInfo; + PM_PROFILE_SETUP_INFO_T *prPmProfSetupInfo; + struct sk_buff *prMsduInfo; + MSDU_INFO_T *prMsduInfoMgmt; + UINT8 *pPkt, *pucInitiator, *pucResponder; + UINT32 u4PktLen, u4IeLen; + UINT16 u2CapInfo; +/* UINT8 *pPktTemp; */ + + prGlueInfo = (GLUE_INFO_T *) prAdapter->prGlueInfo; + + DBGLOG(TDLS, INFO, " %s: 2040=%d\n", __func__, prGlueInfo->rTdlsLink.fgIs2040Sup); + + /* sanity check */ + if (prStaRec != NULL) { + if (prStaRec->ucNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + DBGLOG(TDLS, ERROR, + " %s: net index %d fail\n", __func__, prStaRec->ucNetTypeIndex); + return TDLS_STATUS_FAILURE; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + } else { + /* prStaRec maybe NULL in setup request */ + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + } + + /* allocate/init packet */ + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + u4PktLen = 0; + prMsduInfo = NULL; + prMsduInfoMgmt = NULL; + + /* make up frame content */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { + /* + The STAUT will not respond to a TDLS Discovery Request Frame with different BSSID. + Supplicant will check this in wpa_tdls_process_discovery_request(). + */ + + /* TODO: reduce 1600 to correct size */ + prMsduInfo = kalPacketAlloc(prGlueInfo, 1600, &pPkt); + if (prMsduInfo == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + prMsduInfo->dev = prGlueInfo->prDevHandler; + if (prMsduInfo->dev == NULL) { + DBGLOG(TDLS, ERROR, " %s: MsduInfo->dev == NULL\n", __func__); + kalPacketFree(prGlueInfo, prMsduInfo); + return TDLS_STATUS_FAILURE; + } + + /* 1. 802.3 header */ +/* pPktTemp = pPkt; */ + kalMemCopy(pPkt, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(pPkt, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + LR_TDLS_FME_FIELD_FILL(TDLS_FME_MAC_ADDR_LEN); + *(UINT_16 *) pPkt = htons(TDLS_FRM_PROT_TYPE); + LR_TDLS_FME_FIELD_FILL(2); + + /* 2. payload type */ + *pPkt = TDLS_FRM_PAYLOAD_TYPE; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - (1) Category */ + *pPkt = TDLS_FRM_CATEGORY; + LR_TDLS_FME_FIELD_FILL(1); + } else { + /* discovery response */ + WLAN_MAC_HEADER_T *prHdr; + + prMsduInfoMgmt = (MSDU_INFO_T *) + cnmMgtPktAlloc(prAdapter, PUBLIC_ACTION_MAX_LEN); + if (prMsduInfoMgmt == NULL) { + DBGLOG(TDLS, ERROR, " %s: allocate mgmt pkt fail\n", __func__); + return TDLS_STATUS_RESOURCES; + } + + pPkt = (UINT8 *) prMsduInfoMgmt->prPacket; + prHdr = (WLAN_MAC_HEADER_T *) pPkt; + + /* 1. 802.11 header */ + prHdr->u2FrameCtrl = MAC_FRAME_ACTION; + prHdr->u2DurationID = 0; + kalMemCopy(prHdr->aucAddr1, pPeerMac, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr2, prBssInfo->aucOwnMacAddr, TDLS_FME_MAC_ADDR_LEN); + kalMemCopy(prHdr->aucAddr3, prBssInfo->aucBSSID, TDLS_FME_MAC_ADDR_LEN); + prHdr->u2SeqCtrl = 0; + LR_TDLS_FME_FIELD_FILL(sizeof(WLAN_MAC_HEADER_T)); + + /* Frame Formation - (1) Category */ + *pPkt = CATEGORY_PUBLIC_ACTION; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* 3. Frame Formation - (2) Action */ + *pPkt = ucActionCode; + LR_TDLS_FME_FIELD_FILL(1); + + /* 3. Frame Formation - Status Code */ + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_CONFIRM: + case TDLS_FRM_ACTION_TEARDOWN: + WLAN_SET_FIELD_16(pPkt, u2StatusCode); + LR_TDLS_FME_FIELD_FILL(2); + break; + } + + /* 3. Frame Formation - (3) Dialog token */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + *pPkt = ucDialogToken; + LR_TDLS_FME_FIELD_FILL(1); + } + + /* Fill elements */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + Capability + + Support Rates + Extended Support Rates + Supported Channels + HT Capabilities + WMM Information Element + + Extended Capabilities + Link Identifier + + RSNIE + FTIE + Timeout Interval + */ + if (ucActionCode != TDLS_FRM_ACTION_CONFIRM) { + /* 3. Frame Formation - (4) Capability: 0x31 0x04, privacy bit will be set */ + u2CapInfo = assocBuildCapabilityInfo(prAdapter, prStaRec); + WLAN_SET_FIELD_16(pPkt, u2CapInfo); + LR_TDLS_FME_FIELD_FILL(2); + + /* 4. Append general IEs */ + /* + TODO check HT: prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode + must be CONFIG_BW_20_40M. + + TODO check HT: HT_CAP_INFO_40M_INTOLERANT must be clear if + Tdls 20/40 is enabled. + */ + u4IeLen = TdlsFrameGeneralIeAppend(prAdapter, prStaRec, u2StatusCode, pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 5. Frame Formation - Extended capabilities element */ + EXT_CAP_IE(pPkt)->ucId = ELEM_ID_EXTENDED_CAP; + EXT_CAP_IE(pPkt)->ucLength = 5; + + EXT_CAP_IE(pPkt)->aucCapabilities[0] = 0x00; /* bit0 ~ bit7 */ + EXT_CAP_IE(pPkt)->aucCapabilities[1] = 0x00; /* bit8 ~ bit15 */ + EXT_CAP_IE(pPkt)->aucCapabilities[2] = 0x00; /* bit16 ~ bit23 */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] = 0x00; /* bit24 ~ bit31 */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] = 0x00; /* bit32 ~ bit39 */ + + /* if (prCmd->ucExCap & TDLS_EX_CAP_PEER_UAPSD) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((28 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_CHAN_SWITCH) */ + EXT_CAP_IE(pPkt)->aucCapabilities[3] |= BIT((30 - 24)); + /* if (prCmd->ucExCap & TDLS_EX_CAP_TDLS) */ + EXT_CAP_IE(pPkt)->aucCapabilities[4] |= BIT((37 - 32)); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } else { + /* 5. Frame Formation - WMM Parameter element */ + if (prAdapter->rWifiVar.fgSupportQoS) { + u4IeLen = mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, pPkt, OP_MODE_INFRASTRUCTURE); + + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + } + } + + /* 6. Frame Formation - 20/40 BSS Coexistence */ + /* + Follow WiFi test plan, add 20/40 element to request/response/confirm. + */ +/* if (prGlueInfo->rTdlsLink.fgIs2040Sup == TRUE) */ /* force to enable */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* + bit0 = 1: The Information Request field is used to indicate that a + transmitting STA is requesting the recipient to transmit a 20/40 BSS + Coexistence Management frame with the transmitting STA as the + recipient. + + bit1 = 0: The Forty MHz Intolerant field is set to 1 to prohibit an AP + that receives this information or reports of this information from + operating a 20/40 MHz BSS. + + bit2 = 0: The 20 MHz BSS Width Request field is set to 1 to prohibit + a receiving AP from operating its BSS as a 20/40 MHz BSS. + */ + BSS_20_40_COEXIST_IE(pPkt)->ucId = ELEM_ID_20_40_BSS_COEXISTENCE; + BSS_20_40_COEXIST_IE(pPkt)->ucLength = 1; + BSS_20_40_COEXIST_IE(pPkt)->ucData = 0x01; + LR_TDLS_FME_FIELD_FILL(3); + } + + /* 6. Frame Formation - HT Operation element */ +/* u4IeLen = rlmFillHtOpIeBody(prBssInfo, pPkt); */ +/* LR_TDLS_FME_FIELD_FILL(u4IeLen); */ + + /* 7. Frame Formation - Link identifier element */ + /* Note1: Link ID sequence must be correct; Or the calculated MIC will be error */ + /* + Note2: When we receive a setup request with link ID, Marvell will send setup response + to the peer in link ID, not the SA in the WLAN header. + */ + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucId = ELEM_ID_LINK_IDENTIFIER; + TDLS_LINK_IDENTIFIER_IE(pPkt)->ucLength = ELEM_LEN_LINK_IDENTIFIER; + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aBSSID, prBssInfo->aucBSSID, 6); + + switch (ucActionCode) { + case TDLS_FRM_ACTION_SETUP_REQ: + case TDLS_FRM_ACTION_CONFIRM: + default: + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = TRUE; + break; + + case TDLS_FRM_ACTION_SETUP_RSP: + case TDLS_FRM_ACTION_DISCOVERY_RESPONSE: + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + + if (prStaRec != NULL) + prStaRec->flgTdlsIsInitiator = FALSE; + break; + + case TDLS_FRM_ACTION_TEARDOWN: + if (prStaRec != NULL) { + if (prStaRec->flgTdlsIsInitiator == TRUE) { + /* we are initiator */ + pucInitiator = prBssInfo->aucOwnMacAddr; + pucResponder = pPeerMac; + } else { + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + } + } else { + /* peer is initiator */ + pucInitiator = pPeerMac; + pucResponder = prBssInfo->aucOwnMacAddr; + } + break; + } + + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aInitiator, pucInitiator, 6); + kalMemCopy(TDLS_LINK_IDENTIFIER_IE(pPkt)->aResponder, pucResponder, 6); + + u4IeLen = IE_SIZE(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + + /* 8. Append security IEs */ + /* + 11.21.5 TDLS Direct Link Teardown + If the STA has security enabled on the link 37 with the AP, then the FTIE shall be + included in the TDLS Teardown frame. + + For ralink station, it can accept our tear down without FTIE but marvell station. + */ +/* if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) && (pAppendIe != NULL)) */ + if (pAppendIe != NULL) { + if ((ucActionCode != TDLS_FRM_ACTION_TEARDOWN) || + ((ucActionCode == TDLS_FRM_ACTION_TEARDOWN) && + (prStaRec != NULL) && (prStaRec->fgTdlsInSecurityMode == TRUE))) { + kalMemCopy(pPkt, pAppendIe, AppendIeLen); + LR_TDLS_FME_FIELD_FILL(AppendIeLen); + } + } + + /* 7. Append Supported Operating Classes IE */ + if (ucActionCode != TDLS_FRM_ACTION_TEARDOWN) { + /* Note: if we do not put the IE, Marvell STA will decline our TDLS setup request */ + u4IeLen = rlmDomainSupOperatingClassIeFill(pPkt); + LR_TDLS_FME_FIELD_FILL(u4IeLen); + } + + /* 11. send the data or management frame */ + if (ucActionCode != TDLS_FRM_ACTION_DISCOVERY_RESPONSE) { +#if 0 + /* + Note1: remember to modify our MAC & AP MAC & peer MAC in LINK ID + Note2: dialog token in rsp & confirm must be same as sender. + */ + +#if 1 + /* example for Ralink's and Broadcom's TDLS setup request frame in open/none */ + if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { +#if 0 + /* mediatek */ + char buffer[] = { 0x31, 0x04, + 0x01, 0x08, 0x02, 0x04, 0x0b, 0x16, 0xc, 0x12, 0x18, 0x24, + 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, + 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, + 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e + }; +#endif + +#if 1 + /* ralink *//* from capability */ + char buffer[] = { 0x21, 0x04, + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, + 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, + 0x32, 0x04, 0x0c, 0x18, 0x30, 0x60, + 0x24, 0x06, 0x01, 0x0b, 0x24, 0x08, 0x95, 0x04, + 0x7f, 0x05, 0x01, 0x00, 0x00, 0x50, 0x20, + 0x3b, 0x10, 0x20, 0x01, 0x02, 0x03, 0x04, 0x0c, 0x16, 0x17, 0x18, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f + }; +#endif +#if 0 + /* 6630 */ + char buffer[] = { 0x01, 0x01, + 0x01, 0x04, 0x02, 0x04, 0x0b, 0x16, + 0x24, 0x02, 0x01, 0x0d, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0xff, + 0x2d, 0x1a, 0x61, 0x01, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00, + 0xbf, 0x0c, 0x30, 0x01, 0x80, 0x03, 0xfe, 0xff, 0x00, 0x00, 0xfe, 0xff, + 0x00, 0x00 + }; +#endif + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif + +#if 1 + if (ucActionCode == TDLS_FRM_ACTION_CONFIRM) { + /* Note: dialog token must be same as request */ +#if 1 + /* ralink */ + char buffer[] = { 0x00, + 0x01, 0x2d, 0x1a, 0x6e, 0x00, 0x17, 0xff, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x00, 0x03, + 0xa4, 0x00, 0x00, 0x27, 0xa4, 0x00, 0x00, 0x42, 0x43, 0x5e, 0x00, + 0x62, 0x32, 0x2f, 0x00 + }; +#endif + +#if 0 + /* 6630 */ + char buffer[] = { 0x00, + 0x01, + 0x38, 0x05, 0x02, 0xc0, 0xa8, 0x00, 0x00, + 0x48, 0x01, 0x01, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1d, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x80, 0x3f, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00 + }; +#endif + +#if 0 + /* A/D die */ + char buffer[] = { 0x00, + 0x01, + 0xdd, 0x18, 0x00, 0x50, 0xf2, 0x02, 0x01, 0x01, 0x0f, 0x6b, 0x00, 0x00, + 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x60, + 0x00, 0x00, 0x00 0x65, 0x12, 0x00, 0x0c, 0x43, 0x31, 0x35, 0x97, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x38, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, 0x1b, + 0x1c, 0x1e, 0x20, 0x21, + 0x07, 0x06, 0x55, 0x53, 0x20, 0x01, 0x0b, 0x1e + }; +#endif + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif + +#else + +#if 0 + /* for test in open/none */ + if (ucActionCode == TDLS_FRM_ACTION_SETUP_REQ) { + char buffer[] = { 0x01, 0x04, + 0x01, 0x08, 0x82, 0x84, 0x8b, 0x96, 0x12, 0x24, 0x48, 0x6c, + 0x07, 0x06, 0x55, 0x53, 0x20, 0xdd, 0x20, 0x00, + 0x32, 0x04, 0x30, 0x48, 0x60, 0x6c, + 0x24, 0x0a, 0x01, 0x0b, 0x24, 0x04, 0x34, 0x04, 0x95, 0x04, 0xa5, 0x01, + 0x2d, 0x1a, 0x72, 0x11, 0x03, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xdd, 0x07, 0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x0f, + 0x7f, 0x05, 0x00, 0x00, 0x00, 0x50, 0x20, + 0x48, 0x01, 0x01, + 0x65, 0x12, 0x00, 0x0c, 0x43, 0x44, 0x0b, 0x1a, 0x00, 0x11, 0x22, 0x33, + 0x44, 0x05, 0x00, 0x22, 0x58, 0x00, 0xcc, 0x0f, + 0x3b, 0x0d, 0x0c, 0x01, 0x02, 0x03, 0x05, 0x16, 0x17, 0x19, + 0x1b, 0x1c, 0x1e, 0x20, 0x21 + }; + + pPktTemp += 18; + memcpy(pPktTemp, buffer, sizeof(buffer)); + u4PktLen = 18 + sizeof(buffer); + } +#endif +#endif /* 0 */ + + /* 9. Update packet length */ + prMsduInfo->len = u4PktLen; + dumpMemory8(prMsduInfo->data, u4PktLen); + + wlanHardStartXmit(prMsduInfo, prMsduInfo->dev); + } else { + /* + A TDLS capable STA that receives a TDLS Discovery Request frame is required to + send the response "to the requesting STA, via the direct path." + However, prior to establishment of the direct link, the responding STA may not + know the rate capabilities of the requesting STA. In this case, the responding + STA shall send the TDLS Discovery Response frame using a rate from the + BSSBasicRateSet of the BSS to which the STA is currently associated. + */ + prMsduInfoMgmt->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; + prMsduInfoMgmt->ucStaRecIndex = prBssInfo->prStaRecOfAP->ucIndex; + prMsduInfoMgmt->ucNetworkType = prBssInfo->ucNetTypeIndex; + prMsduInfoMgmt->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfoMgmt->fgIs802_1x = FALSE; + prMsduInfoMgmt->fgIs802_11 = TRUE; + prMsduInfoMgmt->u2FrameLength = u4PktLen; + prMsduInfoMgmt->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfoMgmt->pfTxDoneHandler = NULL; + prMsduInfoMgmt->fgIsBasicRate = TRUE; /* use basic rate */ + + /* Send them to HW queue */ + nicTxEnqueueMsdu(prAdapter, prMsduInfoMgmt); + } + + return TDLS_STATUS_SUCCESS; +} + +#endif /* CFG_SUPPORT_TDLS */ + + /* End of tdls_com.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c new file mode 100644 index 0000000000000..af66ef95d17cf --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wapi.c @@ -0,0 +1,491 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/mgmt/wapi.c#1 +*/ + +/*! \file "wapi.c" + \brief This file including the WAPI related function. + + This file provided the macros and functions library support the wapi ie parsing, + cipher and AKM check to help the AP seleced deciding. +*/ + +/* +** Log: wapi.c +** +** 10 24 2012 wh.su +** [ALPS00376392] [klocwork 9.1] in wapi.c, line 344 +** Use MAX_NUM_SUPPORTED_WAPI_AKM_SUITESfor avoid Klocwork warning. +** +** 10 24 2012 wh.su +** [ALPS00376391] [klocwork 9.1] in wapi.c, line 311 +** Use the MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES for avoid Klccwork waring. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the debug module level. + * + * 10 20 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * fixed the network type + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 07 20 2010 wh.su + * + * . + * + * 04 06 2010 wh.su + * [BORA00000680][MT6620] Support the statistic for Micxxsoft os query + * fixed the firmware return the broadcast frame at wrong tc. + * + * 03 03 2010 wh.su + * [BORA00000637][MT6620 Wi-Fi] [Bug] WPA2 pre-authentication timer not correctly initialize + * move the AIS specific variable for security to AIS specific structure. + * + * 12 18 2009 cm.chang + * [BORA00000018]Integrate WIFI part into BORA for the 1st time + * . + * + * Dec 8 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the function to check and update the default wapi tx + * + * Dec 7 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * adding the generate wapi ie function, and replace the tabe by space + * + * Nov 23 2009 mtk01088 + * [BORA00000476] [Wi-Fi][firmware] Add the security module initialize code + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" +#if CFG_SUPPORT_WAPI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to generate WPA IE for +* associate request frame. +* +* \param[in] prCurrentBss The Selected BSS description +* +* \retval The append WPA IE length +* +* \note +* Called by: AIS module, Associate request +*/ +/*----------------------------------------------------------------------------*/ +VOID wapiGenerateWAPIIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + PUINT_8 pucBuffer; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + if (prMsduInfo->ucNetworkType != NETWORK_TYPE_AIS_INDEX) + return; + + pucBuffer = (PUINT_8) ((ULONG) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + + /* ASSOC INFO IE ID: 68 :0x44 */ + if (/* prWlanInfo->fgWapiMode && */ prAdapter->prGlueInfo->u2WapiAssocInfoIESz) { + kalMemCopy(pucBuffer, &prAdapter->prGlueInfo->aucWapiAssocInfoIEs, + prAdapter->prGlueInfo->u2WapiAssocInfoIESz); + prMsduInfo->u2FrameLength += prAdapter->prGlueInfo->u2WapiAssocInfoIESz; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to parse WAPI IE. +* +* \param[in] prInfoElem Pointer to the RSN IE +* \param[out] prRsnInfo Pointer to the BSSDescription structure to store the +** WAPI information from the given WAPI IE +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiParseWapiIE(IN P_WAPI_INFO_ELEM_T prInfoElem, OUT P_WAPI_INFO_T prWapiInfo) +{ + UINT_32 i; + INT_32 u4RemainWapiIeLen; + UINT_16 u2Version; + UINT_16 u2Cap = 0; + UINT_32 u4GroupSuite = WAPI_CIPHER_SUITE_WPI; + UINT_16 u2PairSuiteCount = 0; + UINT_16 u2AuthSuiteCount = 0; + PUCHAR pucPairSuite = NULL; + PUCHAR pucAuthSuite = NULL; + PUCHAR cp; + + DEBUGFUNC("wapiParseWapiIE"); + + ASSERT(prInfoElem); + ASSERT(prWapiInfo); + + /* Verify the length of the WAPI IE. */ + if (prInfoElem->ucLength < 6) { + DBGLOG(SEC, TRACE, "WAPI IE length too short (length=%d)\n", prInfoElem->ucLength); + return FALSE; + } + + /* Check WAPI version: currently, we only support version 1. */ + WLAN_GET_FIELD_16(&prInfoElem->u2Version, &u2Version); + if (u2Version != 1) { + DBGLOG(SEC, TRACE, "Unsupported WAPI IE version: %d\n", u2Version); + return FALSE; + } + + cp = (PUCHAR) &prInfoElem->u2AuthKeyMgtSuiteCount; + u4RemainWapiIeLen = (INT_32) prInfoElem->ucLength - 2; + + do { + if (u4RemainWapiIeLen == 0) + break; + + /* + AuthCount : 2 + AuthSuite : 4 * authSuiteCount + PairwiseCount: 2 + PairwiseSuite: 4 * pairSuiteCount + GroupSuite : 4 + Cap : 2 */ + + /* Parse the Authentication and Key Management Cipher Suite Count + field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2AuthSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Authentication and Key Management Cipher Suite List + field. */ + i = (UINT_32) u2AuthSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in auth & key mgt suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucAuthSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + if (u4RemainWapiIeLen == 0) + break; + + /* Parse the Pairwise Key Cipher Suite Count field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite count (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2PairSuiteCount); + cp += 2; + u4RemainWapiIeLen -= 2; + + /* Parse the Pairwise Key Cipher Suite List field. */ + i = (UINT_32) u2PairSuiteCount * 4; + if (u4RemainWapiIeLen < (INT_32) i) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in pairwise cipher suite list (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + pucPairSuite = cp; + + cp += i; + u4RemainWapiIeLen -= (INT_32) i; + + /* Parse the Group Key Cipher Suite field. */ + if (u4RemainWapiIeLen < 4) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in group cipher suite (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_32(cp, &u4GroupSuite); + cp += 4; + u4RemainWapiIeLen -= 4; + + /* Parse the WAPI u2Capabilities field. */ + if (u4RemainWapiIeLen < 2) { + DBGLOG(SEC, TRACE, "Fail to parse WAPI IE in WAPI capabilities (IE len: %d)\n", + prInfoElem->ucLength); + return FALSE; + } + + WLAN_GET_FIELD_16(cp, &u2Cap); + u4RemainWapiIeLen -= 2; + + /* Todo:: BKID support */ + } while (FALSE); + + /* Save the WAPI information for the BSS. */ + + prWapiInfo->ucElemId = ELEM_ID_WAPI; + + prWapiInfo->u2Version = u2Version; + + prWapiInfo->u4GroupKeyCipherSuite = u4GroupSuite; + + DBGLOG(SEC, LOUD, "WAPI: version %d, group key cipher suite %02x-%02x-%02x-%02x\n", + u2Version, (UCHAR) (u4GroupSuite & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 8) & 0x000000FF), + (UCHAR) ((u4GroupSuite >> 16) & 0x000000FF), (UCHAR) ((u4GroupSuite >> 24) & 0x000000FF)); + + if (pucPairSuite) { + /* The information about the pairwise key cipher suites is present. */ + if (u2PairSuiteCount > MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES) + u2PairSuiteCount = MAX_NUM_SUPPORTED_WAPI_CIPHER_SUITES; + + prWapiInfo->u4PairwiseKeyCipherSuiteCount = (UINT_32) u2PairSuiteCount; + + for (i = 0; i < (UINT_32) u2PairSuiteCount; i++) { + WLAN_GET_FIELD_32(pucPairSuite, &prWapiInfo->au4PairwiseKeyCipherSuite[i]); + pucPairSuite += 4; + + DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the pairwise key cipher suites is not present. + Use the default chipher suite for WAPI: WPI. */ + prWapiInfo->u4PairwiseKeyCipherSuiteCount = 1; + prWapiInfo->au4PairwiseKeyCipherSuite[0] = WAPI_CIPHER_SUITE_WPI; + + DBGLOG(SEC, LOUD, "WAPI: pairwise key cipher suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4PairwiseKeyCipherSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4PairwiseKeyCipherSuite[0] >> 24) & 0x000000FF)); + } + + if (pucAuthSuite) { + /* The information about the authentication and key management suites + is present. */ + if (u2AuthSuiteCount > MAX_NUM_SUPPORTED_WAPI_AKM_SUITES) + u2AuthSuiteCount = MAX_NUM_SUPPORTED_WAPI_AKM_SUITES; + + prWapiInfo->u4AuthKeyMgtSuiteCount = (UINT_32) u2AuthSuiteCount; + + for (i = 0; i < (UINT_32) u2AuthSuiteCount; i++) { + WLAN_GET_FIELD_32(pucAuthSuite, &prWapiInfo->au4AuthKeyMgtSuite[i]); + pucAuthSuite += 4; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite [%d]: %02x-%02x-%02x-%02x\n", + (UINT_8) i, (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[i] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[i] >> 24) & 0x000000FF)); + } + } else { + /* The information about the authentication and key management suites + is not present. Use the default AKM suite for WAPI. */ + prWapiInfo->u4AuthKeyMgtSuiteCount = 1; + prWapiInfo->au4AuthKeyMgtSuite[0] = WAPI_AKM_SUITE_802_1X; + + DBGLOG(SEC, LOUD, "WAPI: AKM suite: %02x-%02x-%02x-%02x (default)\n", + (UCHAR) (prWapiInfo->au4AuthKeyMgtSuite[0] & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 8) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 16) & 0x000000FF), + (UCHAR) ((prWapiInfo->au4AuthKeyMgtSuite[0] >> 24) & 0x000000FF)); + } + + prWapiInfo->u2WapiCap = u2Cap; + DBGLOG(SEC, LOUD, "WAPI: cap: 0x%04x\n", prWapiInfo->u2WapiCap); + + return TRUE; +} /* wapiParseWapiIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to perform WAPI policy selection for a given BSS. +* +* \param[in] prAdapter Pointer to the adapter object data area. +* \param[in] prBss Pointer to the BSS description +* +* \retval TRUE - The WAPI policy selection for the given BSS is +* successful. The selected pairwise and group cipher suites +* are returned in the BSS description. +* \retval FALSE - The WAPI policy selection for the given BSS is failed. +* The driver shall not attempt to join the given BSS. +* +* \note The Encrypt status matched score will save to bss for final ap select. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiPerformPolicySelection(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prBss) +{ + UINT_32 i; + UINT_32 u4PairwiseCipher = 0; + UINT_32 u4GroupCipher = 0; + UINT_32 u4AkmSuite = 0; + P_WAPI_INFO_T prBssWapiInfo; + P_WLAN_INFO_T prWlanInfo; + + DEBUGFUNC("wapiPerformPolicySelection"); + + ASSERT(prBss); + + /* Notice!!!! WAPI AP not set the privacy bit for WAI and WAI-PSK at WZC configuration mode */ + prWlanInfo = &prAdapter->rWlanInfo; + + if (prBss->fgIEWAPI) { + prBssWapiInfo = &prBss->rIEWAPI; + } else { + if (prAdapter->rWifiVar.rConnSettings.fgWapiMode == FALSE) { + DBGLOG(SEC, TRACE, "-- No Protected BSS\n"); + return TRUE; + } + DBGLOG(SEC, TRACE, "WAPI Information Element does not exist.\n"); + return FALSE; + } + + /* Select pairwise/group ciphers */ + for (i = 0; i < prBssWapiInfo->u4PairwiseKeyCipherSuiteCount; i++) { + if (prBssWapiInfo->au4PairwiseKeyCipherSuite[i] == + prAdapter->rWifiVar.rConnSettings.u4WapiSelectedPairwiseCipher) { + u4PairwiseCipher = prBssWapiInfo->au4PairwiseKeyCipherSuite[i]; + } + } + if (prBssWapiInfo->u4GroupKeyCipherSuite == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedGroupCipher) + u4GroupCipher = prBssWapiInfo->u4GroupKeyCipherSuite; + + /* Exception handler */ + /* If we cannot find proper pairwise and group cipher suites to join the + BSS, do not check the supported AKM suites. */ + if (u4PairwiseCipher == 0 || u4GroupCipher == 0) { + DBGLOG(SEC, TRACE, "Failed to select pairwise/group cipher (0x%08x/0x%08x)\n", + u4PairwiseCipher, u4GroupCipher); + return FALSE; + } + + /* Select AKM */ + /* If the driver cannot support any authentication suites advertised in + the given BSS, we fail to perform RSNA policy selection. */ + /* Attempt to find any overlapping supported AKM suite. */ + for (i = 0; i < prBssWapiInfo->u4AuthKeyMgtSuiteCount; i++) { + if (prBssWapiInfo->au4AuthKeyMgtSuite[i] == prAdapter->rWifiVar.rConnSettings.u4WapiSelectedAKMSuite) { + u4AkmSuite = prBssWapiInfo->au4AuthKeyMgtSuite[i]; + break; + } + } + + if (u4AkmSuite == 0) { + DBGLOG(SEC, TRACE, "Cannot support any AKM suites\n"); + return FALSE; + } + + DBGLOG(SEC, TRACE, "Selected pairwise/group cipher: %02x-%02x-%02x-%02x/%02x-%02x-%02x-%02x\n", + (UINT_8) (u4PairwiseCipher & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 8) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 16) & 0x000000FF), + (UINT_8) ((u4PairwiseCipher >> 24) & 0x000000FF), + (UINT_8) (u4GroupCipher & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 8) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 16) & 0x000000FF), + (UINT_8) ((u4GroupCipher >> 24) & 0x000000FF)); + + DBGLOG(SEC, TRACE, "Selected AKM suite: %02x-%02x-%02x-%02x\n", + (UINT_8) (u4AkmSuite & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 8) & 0x000000FF), + (UINT_8) ((u4AkmSuite >> 16) & 0x000000FF), (UINT_8) ((u4AkmSuite >> 24) & 0x000000FF)); + + return TRUE; +} /* wapiPerformPolicySelection */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is use for wapi mode, to update the current wpi tx idx ? 0 :1 . +* +* \param[in] prStaRec Pointer to the Sta record +* \param[out] ucWlanIdx The Rx status->wlanidx field +* +* \retval TRUE - Succeeded +* \retval FALSE - Failed +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wapiUpdateTxKeyIdx(IN P_STA_RECORD_T prStaRec, IN UINT_8 ucWlanIdx) +{ + UINT_8 ucKeyId; + + if ((ucWlanIdx & BITS(0, 3)) == CIPHER_SUITE_WPI) { + + ucKeyId = ((ucWlanIdx & BITS(4, 5)) >> 4); + + if (ucKeyId != g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey) { + DBGLOG(RSN, STATE, + "Change wapi key index from %d->%d\n", + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey, ucKeyId); + g_prWifiVar->rAisSpecificBssInfo.ucWpiActivedPWKey = ucKeyId; + + prStaRec->ucWTEntry = + (ucKeyId == + WTBL_AIS_BSSID_WAPI_IDX_0) ? WTBL_AIS_BSSID_WAPI_IDX_0 : WTBL_AIS_BSSID_WAPI_IDX_1; + } + } +} +#endif +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c new file mode 100644 index 0000000000000..f54d229411485 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/mgmt/wnm.c @@ -0,0 +1,301 @@ +/* +** Id: //Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/mgmt/wnm.c#1 +*/ + +/*! \file "wnm.c" + \brief This file includes the 802.11v default vale and functions. +*/ + +/* +** Log: wnm.c + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#if CFG_SUPPORT_802_11V + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define WNM_MAX_TOD_ERROR 0 +#define WNM_MAX_TOA_ERROR 0 +#define MICRO_TO_10NANO(x) ((x)*100) +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +static UINT_8 ucTimingMeasToken; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v wnm category action frame. +* +* +* \note +* Called by: Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmWNMAction(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prRxFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + if (prRxFrame->ucAction == ACTION_WNM_TIMING_MEASUREMENT_REQUEST) { + wnmTimingMeasRequest(prAdapter, prSwRfb); + return; + } +#endif + + DBGLOG(WNM, TRACE, "Unsupport WNM action frame: %d\n", prRxFrame->ucAction); +} + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to report timing measurement data. +* +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmReportTimingMeas(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIndex, IN UINT_32 u4ToD, IN UINT_32 u4ToA) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "wnmReportTimingMeas: u4ToD %x u4ToA %x", u4ToD, u4ToA); + + if (!prStaRec->rWNMTimingMsmt.ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.u4ToD = MICRO_TO_10NANO(u4ToD); + prStaRec->rWNMTimingMsmt.u4ToA = MICRO_TO_10NANO(u4ToA); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will handle TxDone(TimingMeasurement) Event. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prMsduInfo Pointer to the MSDU_INFO_T. +* @param[in] rTxDoneStatus Return TX status of the Timing Measurement frame. +* +* @retval WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +wnmRunEventTimgingMeasTxDone(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN ENUM_TX_RESULT_CODE_T rTxDoneStatus) +{ + P_STA_RECORD_T prStaRec; + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + DBGLOG(WNM, LOUD, "EVENT-TX DONE: Current Time = %u\n", kalGetTimeTick()); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return WLAN_STATUS_SUCCESS; /* For the case of replying ERROR STATUS CODE */ + + DBGLOG(WNM, TRACE, "wnmRunEventTimgingMeasTxDone: ucDialog %d ucFollowUp %d u4ToD %x u4ToA %x", + prStaRec->rWNMTimingMsmt.ucDialogToken, + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken, + prStaRec->rWNMTimingMsmt.u4ToD, prStaRec->rWNMTimingMsmt.u4ToA); + + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, NULL); + + return WLAN_STATUS_SUCCESS; + +} /* end of wnmRunEventTimgingMeasTxDone() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will compose the Timing Measurement frame. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] prStaRec Pointer to the STA_RECORD_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wnmComposeTimingMeasFrame(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec, IN PFN_TX_DONE_HANDLER pfTxDoneHandler) +{ + P_MSDU_INFO_T prMsduInfo; + P_BSS_INFO_T prBssInfo; + P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME prTxFrame; + UINT_16 u2PayloadLen; + + prBssInfo = &prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]; + ASSERT(prBssInfo); + + prMsduInfo = (P_MSDU_INFO_T) cnmMgtPktAlloc(prAdapter, MAC_TX_RESERVED_FIELD + PUBLIC_ACTION_MAX_LEN); + + if (!prMsduInfo) + return; + + prTxFrame = (P_ACTION_UNPROTECTED_WNM_TIMING_MEAS_FRAME) + ((ULONG) (prMsduInfo->prPacket) + MAC_TX_RESERVED_FIELD); + + prTxFrame->u2FrameCtrl = MAC_FRAME_ACTION; + + COPY_MAC_ADDR(prTxFrame->aucDestAddr, prStaRec->aucMacAddr); + COPY_MAC_ADDR(prTxFrame->aucSrcAddr, prBssInfo->aucOwnMacAddr); + COPY_MAC_ADDR(prTxFrame->aucBSSID, prBssInfo->aucBSSID); + + prTxFrame->ucCategory = CATEGORY_UNPROTECTED_WNM_ACTION; + prTxFrame->ucAction = ACTION_UNPROTECTED_WNM_TIMING_MEASUREMENT; + + /* 3 Compose the frame body's frame. */ + prTxFrame->ucDialogToken = prStaRec->rWNMTimingMsmt.ucDialogToken; + prTxFrame->ucFollowUpDialogToken = prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken; + prTxFrame->u4ToD = prStaRec->rWNMTimingMsmt.u4ToD; + prTxFrame->u4ToA = prStaRec->rWNMTimingMsmt.u4ToA; + prTxFrame->ucMaxToDErr = WNM_MAX_TOD_ERROR; + prTxFrame->ucMaxToAErr = WNM_MAX_TOA_ERROR; + + u2PayloadLen = 2 + ACTION_UNPROTECTED_WNM_TIMING_MEAS_LEN; + + /* 4 Update information of MSDU_INFO_T */ + prMsduInfo->ucPacketType = HIF_TX_PACKET_TYPE_MGMT; /* Management frame */ + prMsduInfo->ucStaRecIndex = prStaRec->ucIndex; + prMsduInfo->ucNetworkType = prStaRec->ucNetTypeIndex; + prMsduInfo->ucMacHeaderLength = WLAN_MAC_MGMT_HEADER_LEN; + prMsduInfo->fgIs802_1x = FALSE; + prMsduInfo->fgIs802_11 = TRUE; + prMsduInfo->u2FrameLength = WLAN_MAC_MGMT_HEADER_LEN + u2PayloadLen; + prMsduInfo->ucTxSeqNum = nicIncreaseTxSeqNum(prAdapter); + prMsduInfo->pfTxDoneHandler = pfTxDoneHandler; + prMsduInfo->fgIsBasicRate = FALSE; + + DBGLOG(WNM, TRACE, "wnmComposeTimingMeasFrame: ucDialogToken %d ucFollowUpDialogToken %d u4ToD %x u4ToA %x\n", + prTxFrame->ucDialogToken, prTxFrame->ucFollowUpDialogToken, + prTxFrame->u4ToD, prTxFrame->u4ToA); + + /* 4 Enqueue the frame to send this action frame. */ + nicTxEnqueueMsdu(prAdapter, prMsduInfo); + + return; + +} /* end of wnmComposeTimingMeasFrame() */ + +/*----------------------------------------------------------------------------*/ +/*! +* +* \brief This routine is called to process the 802.11v timing measurement request. +* +* +* \note +* Handle Rx mgmt request +*/ +/*----------------------------------------------------------------------------*/ +VOID wnmTimingMeasRequest(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_ACTION_WNM_TIMING_MEAS_REQ_FRAME prRxFrame = NULL; + P_STA_RECORD_T prStaRec; + + prRxFrame = (P_ACTION_WNM_TIMING_MEAS_REQ_FRAME) prSwRfb->pvHeader; + if (!prRxFrame) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, TRACE, "IEEE 802.11: Received Timing Measuremen Request from %pM\n" + prStaRec->aucMacAdd); + + /* reset timing msmt */ + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = prRxFrame->ucTrigger; + if (!prRxFrame->ucTrigger) + return; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} + +#if WNM_UNIT_TEST +VOID wnmTimingMeasUnitTest1(P_ADAPTER_T prAdapter, UINT_8 ucStaRecIndex) +{ + P_STA_RECORD_T prStaRec; + + prStaRec = cnmGetStaRecByIndex(prAdapter, ucStaRecIndex); + if ((!prStaRec) || (!prStaRec->fgIsInUse)) + return; + + DBGLOG(WNM, INFO, "IEEE 802.11v: Test Timing Measuremen Request from %pM\n", + prStaRec->aucMacAddr); + + prStaRec->rWNMTimingMsmt.fgInitiator = TRUE; + prStaRec->rWNMTimingMsmt.ucTrigger = 1; + + prStaRec->rWNMTimingMsmt.ucDialogToken = ++ucTimingMeasToken; + prStaRec->rWNMTimingMsmt.ucFollowUpDialogToken = 0; + + wnmComposeTimingMeasFrame(prAdapter, prStaRec, wnmRunEventTimgingMeasTxDone); +} +#endif + +#endif /* CFG_SUPPORT_802_11V_TIMING_MEASUREMENT */ + +#endif /* CFG_SUPPORT_802_11V */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c new file mode 100644 index 0000000000000..6f1bb6fd771ec --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/cmd_buf.c @@ -0,0 +1,254 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/cmd_buf.c#1 +*/ + +/*! \file "cmd_buf.c" + \brief This file contain the management function of internal Command Buffer + for CMD_INFO_T. + + We'll convert the OID into Command Packet and then send to FW. Thus we need + to copy the OID information to Command Buffer for following reasons. + 1. The data structure of OID information may not equal to the data structure of + Command, we cannot use the OID buffer directly. + 2. If the Command was not generated by driver we also need a place to store the + information. + 3. Because the CMD is NOT FIFO when doing memory allocation (CMD will be generated + from OID or interrupt handler), thus we'll use the Block style of Memory Allocation + here. +*/ + +/* +** Log: cmd_buf.c + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 02 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. clear prPendingCmdInfo properly + * * 2. while allocating memory for cmdinfo, no need to add extra 4 bytes. +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-10-13 21:59:08 GMT mtk01084 +** remove un-neceasary spaces +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-05-20 12:24:26 GMT mtk01461 +** Increase CMD Buffer - HIF_RX_HW_APPENDED_LEN when doing CMD_INFO_T allocation +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 09:41:08 GMT mtk01461 +** Add init of Driver Domain MCR flag and fix lint MTK WARN +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-17 19:51:45 GMT mtk01461 +** allocation function of CMD_INFO_T +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static BOOLEAN fgCmdDumpIsDone = FALSE; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to initial the MGMT memory pool for CMD Packet. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufInitialize(IN P_ADAPTER_T prAdapter) +{ + P_CMD_INFO_T prCmdInfo; + UINT_32 i; + + ASSERT(prAdapter); + + QUEUE_INITIALIZE(&prAdapter->rFreeCmdList); + + for (i = 0; i < CFG_TX_MAX_CMD_PKT_NUM; i++) { + prCmdInfo = &prAdapter->arHifCmdDesc[i]; + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + } + fgCmdDumpIsDone = FALSE; +} /* end of cmdBufInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief dump CMD queue and print to trace, for debug use only +* @param[in] prQueue Pointer to the command Queue to be dumped +* @param[in] quename Name of the queue +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufDumpCmdQueue(P_QUE_T prQueue, CHAR *queName) +{ + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_HEAD(prQueue); + + DBGLOG(NIC, INFO, "Dump CMD info for %s, Elem number:%u\n", queName, prQueue->u4NumElem); + while (prCmdInfo) { + P_CMD_INFO_T prCmdInfo1, prCmdInfo2, prCmdInfo3; + + prCmdInfo1 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo); + if (!prCmdInfo1) { + DBGLOG(NIC, INFO, "CID:%d SEQ:%d\n", prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum); + break; + } + prCmdInfo2 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo1); + if (!prCmdInfo2) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum); + break; + } + prCmdInfo3 = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo2); + if (!prCmdInfo3) { + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", prCmdInfo->ucCID, + prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, prCmdInfo1->ucCmdSeqNum, + prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum); + break; + } + DBGLOG(NIC, INFO, "CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d; CID:%d, SEQ:%d\n", + prCmdInfo->ucCID, prCmdInfo->ucCmdSeqNum, prCmdInfo1->ucCID, + prCmdInfo1->ucCmdSeqNum, prCmdInfo2->ucCID, prCmdInfo2->ucCmdSeqNum, + prCmdInfo3->ucCID, prCmdInfo3->ucCmdSeqNum); + prCmdInfo = (P_CMD_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prCmdInfo3); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Allocate CMD_INFO_T from a free list and MGMT memory pool. +* +* @param[in] prAdapter Pointer to the Adapter structure. +* @param[in] u4Length Length of the frame buffer to allocate. +* +* @retval NULL Pointer to the valid CMD Packet handler +* @retval !NULL Fail to allocat CMD Packet +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T cmdBufAllocateCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Length) +{ + P_CMD_INFO_T prCmdInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufAllocateCmdInfo"); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + /* Setup initial value in CMD_INFO_T */ + /* Start address of allocated memory */ + prCmdInfo->pucInfoBuffer = cnmMemAlloc(prAdapter, RAM_TYPE_BUF, u4Length); + + if (prCmdInfo->pucInfoBuffer == NULL) { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + prCmdInfo = NULL; + + DBGLOG(NIC, ERROR, "Allocate prCmdInfo->pucInfoBuffer fail!\n"); + } else { + prCmdInfo->u2InfoBufLen = 0; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + } + fgCmdDumpIsDone = FALSE; + } else if (!fgCmdDumpIsDone) { + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + P_QUE_T prCmdQue = &prGlueInfo->rCmdQueue; + P_QUE_T prPendingCmdQue = &prAdapter->rPendingCmdQueue; + P_TX_TCQ_STATUS_T prTc = &prAdapter->rTxCtrl.rTc; + + fgCmdDumpIsDone = TRUE; + cmdBufDumpCmdQueue(prCmdQue, "waiting Tx CMD queue"); + cmdBufDumpCmdQueue(prPendingCmdQue, "waiting response CMD queue"); + DBGLOG(NIC, INFO, "Tc4 number:%d\n", prTc->aucFreeBufferCount[TC4_INDEX]); + if (prTc->aucFreeBufferCount[TC4_INDEX] != 0) + glDoChipReset(); + } + + return prCmdInfo; + +} /* end of cmdBufAllocateCmdInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to free the CMD Packet to the MGMT memory pool. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo CMD Packet handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID cmdBufFreeCmdInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("cmdBufFreeCmdInfo"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo) { + if (prCmdInfo->pucInfoBuffer) { + cnmMemFree(prAdapter, prCmdInfo->pucInfoBuffer); + prCmdInfo->pucInfoBuffer = NULL; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_INSERT_TAIL(&prAdapter->rFreeCmdList, &prCmdInfo->rQueEntry); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + } + + return; + +} /* end of cmdBufFreeCmdPacket() */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c new file mode 100644 index 0000000000000..dfaaedd118bfb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic.c @@ -0,0 +1,4062 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic.c#2 +*/ + +/*! \file nic.c + \brief Functions that provide operation in NIC's (Network Interface Card) point of view. + + This file includes functions which unite multiple hal(Hardware) operations + and also take the responsibility of Software Resource Management in order + to keep the synchronization with Hardware Manipulation. +*/ + +/* +** Log: nic.c + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 05 02 2012 terry.wu + * NULL + * Set the default value of AP StaRec index to "STA_REC_INDEX_NOT_FOUND" in update firmware bss command. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when + * returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 11 22 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * keep debug counter setting after wake up. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 04 2011 cp.wu + * [WCXRP00001079] [MT5931][Driver] Release pending MMPDU only when BSS is being deactivated + * pre-check for NULL before calling MMPDU free function + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * change the DBGLOG for "\n" and "\r\n". LABEL to LOUD for XLOG + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to + * the AP.. + * + * 10 11 2011 terry.wu + * NULL + * Rewrite Assert Dump Function for Portability. + * + * 09 20 2011 cm.chang + * [WCXRP00000997] [MT6620 Wi-Fi][Driver][FW] Handle change of BSS preamble type and slot time + * New CMD definition about RLM parameters + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 03 2011 terry.wu + * [WCXRP00000899] [MT6620] [FW] Reply probe rsp in FW for hotspot mode + * Reply Probe Rsp in FW for Hotspot Mode. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device + * issue. + * Fix GO send deauth frame issue. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 07 11 2011 wh.su + * [WCXRP00000849] [MT6620 Wi-Fi][Driver] Remove some of the WAPI define for make sure the value is initialize, for + * customer not enable WAPI + * For make sure wapi initial value is set. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky + * AP which use space character as hidden SSID + * 1. correct logic + * 2. replace only BSS-DESC which doesn't have a valid SSID. + * + * 06 27 2011 cp.wu + * [WCXRP00000815] [MT6620 Wi-Fi][Driver] allow single BSSID with multiple SSID settings to work around some tricky + * AP which use space character as hidden SSID + * allow to have a single BSSID with multiple SSID to be presented in scanning result + * + * 05 12 2011 puff.wen + * NULL + * FW Assert information dump to driver + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 15 2011 cp.wu + * [WCXRP00000651] [MT6620 Wi-Fi][Driver] Refine RSSI buffering mechanism + * ROLLBACK due to the special design is to workaround incorrect initial RCPI value coming from firmware domain. + * + * 04 14 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 14 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected + * 2. add dummy function for both Win32 and Linux part. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for + * dedicated network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 12 2011 wh.su + * NULL + * enable the p2p check the cipher to set the bssInfo auth mode. + * + * 04 12 2011 wh.su + * NULL + * prepare the code for sync the auth mode and encryption status for P2P and BOW. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 04 10 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * Fix compiler issue. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 04 07 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside + * wlanAdapterStart + * . + * + * 04 07 2011 cp.wu + * [WCXRP00000616] [MT6620 Wi-Fi][Driver] Free memory to pool and kernel in case any unexpected failure happend inside + * wlanAdapterStart + * implementation of internal error handling of nicAllocateAdapterMemory. + * + * 03 31 2011 chinglan.wang + * [WCXRP00000613] [MT6620 Wi-Fi] [FW] [Driver] BssInfo can get the security mode which is WPA/WPA2/WAPI or not. + * . + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similar APIs to hide the difference. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 10 2011 cm.chang + * [WCXRP00000358] [MT6620 Wi-Fi][Driver] Provide concurrent information for each module + * Add some functions to let AIS/Tethering or AIS/BOW be the same channel + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after + * connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 08 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * Use kalPrint to print firmware assert info. + * + * 02 01 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * . + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 31 2011 terry.wu + * [WCXRP00000412] [MT6620 Wi-Fi][FW/Driver] Dump firmware assert info at android kernel log + * Print firmware ASSERT info at Android kernel log, driver side + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 19 2011 cp.wu + * [WCXRP00000372] [MT6620 Wi-Fi][Driver] Check bus access failure inside nicProcessIST() + * check bus error and/or card removal when retrieving interrupt status from HAL + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * 1) correct typo in scan.c + * 2) TX descriptors, RX descriptos and management buffer should use virtually continuous buffer instead of + * physically contineous one + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 12 17 2010 cp.wu + * [WCXRP00000270] [MT6620 Wi-Fi][Driver] Clear issues after concurrent networking support has been merged + * before BSS disconnection is indicated to firmware, all correlated peer should be cleared and freed + * + * 12 07 2010 cm.chang + * [WCXRP00000239] MT6620 Wi-Fi][Driver][FW] Merge concurrent branch back to maintrunk + * 1. BSSINFO include RLM parameter + * 2. free all sta records when network is disconnected + * + * 12 02 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Add more control value but dont use it now. + * + * 11 30 2010 eddie.chen + * [WCXRP00000218] [MT6620 Wi-Fi][Driver] Add auto rate window control in registry + * Add auto rate check window in registry + * + * 11 10 2010 eddie.chen + * [WCXRP00000156] [MT6620][FW] Change Auto rate window to 64 and add throughput swcr + * Use autorate parameter 1 as phy rate mask. + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 10 26 2010 eddie.chen + * [WCXRP00000134] [MT6620 Wi-Fi][Driver] Add a registry to enable auto rate for SQA test by using E1 EVB + * Add auto rate parameter in registry. + * + * 10 18 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to + * BSOD when entering RF test with AIS associated + * 1. remove redundant variables in STA_REC structure + * 2. add STA-REC uninitialization routine for clearing pending events + * + * 10 18 2010 cp.wu + * [WCXRP00000103] [MT6620 Wi-Fi][Driver] Driver crashed when using WZC to connect to AP#B with connection with AP#A + * reset ptrs when IEs are going to be dropped + * + * 10 12 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * add HT (802.11n) fixed rate support. + * + * 10 08 2010 cp.wu + * [WCXRP00000084] [MT6620 Wi-Fi][Driver][FW] Add fixed rate support for distance test + * adding fixed rate support for distance test. (from registry setting) + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * load manufacture data when CFG_SUPPORT_NVRAM is set to 1 + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by + * ENUM_NETWORK_TYPE_INDEX_T only remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test + * with AIS associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 26 2010 yuche.tsai + * NULL + * Fix someones coding error while enable WIFI_DIRECT. + * + * 08 25 2010 george.huang + * NULL + * update OID/ registry control path for PM related settings + * + * 08 24 2010 cm.chang + * NULL + * Support RLM initail channel of Ad-hoc, P2P and BOW + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 08 23 2010 chinghwa.yu + * NULL + * Update for BOW. + * + * 08 20 2010 yuche.tsai + * NULL + * Add state change indication. + * + * 08 16 2010 yuche.tsai + * NULL + * Add support for P2P BSS update info. + * + * 08 12 2010 cp.wu + * NULL + * [removing debugging] not to dump beacon content. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 04 2010 yarco.yang + * NULL + * Add TX_AMPDU and ADDBA_REJECT command + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 28 2010 cp.wu + * NULL + * 1) eliminate redundant variable eOPMode in prAdapter->rWlanInfo + * 2) change nicMediaStateChange() API prototype + * + * 07 28 2010 cp.wu + * NULL + * sync. CMD_BSS_INFO structure change to CMD-EVENT v0.15. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * FIX: structure of CMD_SET_BSS_INFO has been changed but no follow-ups are done. + * + * 07 22 2010 george.huang + * + * . + * + * 07 22 2010 george.huang + * + * Update fgIsQoS information in BSS INFO by CMD + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * update prStaRecOfAP with BSS-INFO. + * + * 07 06 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Update arguments for nicUpdateBeaconIETemplate() + * + * 07 06 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * STA-REC is maintained by CNM only. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) ignore RSN checking when RSN is not turned on. + * 2) set STA-REC deactivation callback as NULL + * 3) add variable initialization API based on PHY configuration + * + * 07 01 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Support sync command of STA_REC + * + * 06 30 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync. with CMD/EVENT document ver0.07. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * correct variable naming for 8-bit variable used in CMD_BEACON_TEMPLATE_UPDATE. + * + * 06 29 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) sync to. CMD/EVENT document v0.03 + * 2) simplify DTIM period parsing in scan.c only, bss.c no longer parses it again. + * 3) send command packet to indicate FW-PM after + * a) 1st beacon is received after AIS has connected to an AP + * b) IBSS-ALONE has been created + * c) IBSS-MERGE has occurred + * + * 06 25 2010 george.huang + * [WPD00001556]Basic power managemenet function + * Create beacon update path, with expose bssUpdateBeaconContent() + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill fgIsUapsdConnection when indicating BSS-CREATE with AIS-STA mode. + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00003827][MT6620 Wi-Fi] Chariot fail and following ping fail, no pkt send from driver + * correct nicProcessIST_impl() for interrupt status brought up by RX enhanced response + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX response + * + * 03 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always process TX interrupt first then RX interrupt. + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add checksum offloading support. +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-12-16 18:03:43 GMT mtk02752 +** handling enhanced response which fields are fetched at different moments +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-12-15 17:00:29 GMT mtk02752 +** if RX enhanced response is used, D2H interrupt status should be coming from buffered result as well +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-12-15 12:01:55 GMT mtk02752 +** if TX_DONE bit is not set but WTSR0/WTSR1 is non-zero, then set TX_DONE +** bit due to time latency of interrupt status enhanced response +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-12-10 16:52:52 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-24 20:51:01 GMT mtk02752 +** integrate with SD1 by invoking qmHandleMailboxRxMessage() +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-16 17:32:33 GMT mtk02752 +** prepare code for invoking rxHandleMailboxRxMessage() +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:08 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-09 22:56:41 GMT mtk01084 +** modify HW access routines +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:20 GMT mtk01084 +** prevent warning +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:54:57 GMT mtk01084 +** init HIF +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:30 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:12 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-09-09 17:26:15 GMT mtk01084 +** modify for CFG_TEST_WITH_MT5921 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-19 10:55:22 GMT mtk01461 +** Unmask the unused HISR +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-18 15:59:13 GMT mtk01084 +** remove debug purpose code +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 14:05:02 GMT mtk01084 +** update for WIFI ownback part on initial +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-04 21:32:57 GMT mtk01084 +** add temporarily code to set driver own on adapter initialization +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:35:41 GMT mtk01461 +** Add init of TX aggregation and fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-24 21:12:10 GMT mtk01104 +** Add function nicRestoreSpiDefMode() +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-21 09:43:31 GMT mtk01461 +** Revise for MTK coding style - nicInitializeAdapter() +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-17 19:52:47 GMT mtk01461 +** Update allocate Adapter Memory for MGMT Memory pool +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:57:08 GMT mtk01461 +** Refine the order of release memory from pucRxCoalescingBufCached +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-19 18:32:57 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:00:14 GMT mtk01426 +** Add CFG_SDIO_RX_ENHANCE support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:27 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:25:59 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const UINT_8 aucPhyCfg2PhyTypeSet[PHY_CONFIG_NUM] = { + PHY_TYPE_SET_802_11ABG, /* PHY_CONFIG_802_11ABG */ + PHY_TYPE_SET_802_11BG, /* PHY_CONFIG_802_11BG */ + PHY_TYPE_SET_802_11G, /* PHY_CONFIG_802_11G */ + PHY_TYPE_SET_802_11A, /* PHY_CONFIG_802_11A */ + PHY_TYPE_SET_802_11B, /* PHY_CONFIG_802_11B */ + PHY_TYPE_SET_802_11ABGN, /* PHY_CONFIG_802_11ABGN */ + PHY_TYPE_SET_802_11BGN, /* PHY_CONFIG_802_11BGN */ + PHY_TYPE_SET_802_11AN, /* PHY_CONFIG_802_11AN */ + PHY_TYPE_SET_802_11GN /* PHY_CONFIG_802_11GN */ +}; + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +#define REQ_GATING_ENABLE_H2D_INT BIT(31) +#define REQ_GATING_DISABLE_H2D_INT BIT(30) +#define ACK_GATING_ENABLE_D2H_INT BIT(31) +#define ACK_GATING_DISABLE_D2H_INT BIT(30) + +#define GATING_CONTROL_POLL_LIMIT 64 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static INT_EVENT_MAP_T arIntEventMapTable[] = { + {WHISR_ABNORMAL_INT, INT_EVENT_ABNORMAL}, + {WHISR_D2H_SW_INT, INT_EVENT_SW_INT}, + {WHISR_TX_DONE_INT, INT_EVENT_TX}, + {(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT), INT_EVENT_RX} +}; + +static const UINT_8 ucIntEventMapSize = (sizeof(arIntEventMapTable) / sizeof(INT_EVENT_MAP_T)); + +static IST_EVENT_FUNCTION apfnEventFuncTable[] = { + nicProcessAbnormalInterrupt, /*!< INT_EVENT_ABNORMAL */ + nicProcessSoftwareInterrupt, /*!< INT_EVENT_SW_INT */ + nicProcessTxInterrupt, /*!< INT_EVENT_TX */ + nicProcessRxInterrupt, /*!< INT_EVENT_RX */ +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*! This macro is used to reduce coding errors inside nicAllocateAdapterMemory() + * and also enhance the readability. + */ +#define LOCAL_NIC_ALLOCATE_MEMORY(pucMem, u4Size, eMemType, pucComment) \ + { \ + DBGLOG(NIC, INFO, "Allocating %u bytes for %s.\n", u4Size, pucComment); \ + pucMem = (PUINT_8)kalMemAlloc(u4Size, eMemType); \ + if (pucMem == (PUINT_8)NULL) { \ + DBGLOG(NIC, ERROR, "Could not allocate %u bytes for %s.\n", u4Size, pucComment); \ + break; \ + } \ + ASSERT(((ULONG)pucMem % 4) == 0); \ + DBGLOG(NIC, TRACE, "Virtual Address = %p for %s.\n", pucMem, pucComment); \ + } + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter) +{ + dumpMemory32((PUINT_32)prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); +} + +VOID HifRegDump(P_ADAPTER_T prAdapter) +{ + UINT_32 i; + UINT_32 RegVal = 0; + + for (i = 0; i <= 0x58; i += 4) { + if ((i != MCR_WTDR0) && (i != MCR_WTDR1) && (i != MCR_WRDR0) && + (i != MCR_WRDR1) && (i != MCR_WSDIOCSR) && (i != MCR_WRPLR)) { + HAL_MCR_RD(prAdapter, i, &RegVal); + DBGLOG(NIC, WARN, "HIF Reg 0x%x = 0x%x\n", i, RegVal); + } + } + DBGLOG(NIC, WARN, "\n\n"); +} + +BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter) +{ + return prAdapter->fgIsFwOwn; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for the allocation of the data structures +* inside the Adapter structure, include: +* 1. SW_RFB_Ts +* 2. Common coalescing buffer for TX PATH. +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @retval WLAN_STATUS_SUCCESS - Has enough memory. +* @retval WLAN_STATUS_RESOURCES - Memory is not enough. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicAllocateAdapterMemory(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS status = WLAN_STATUS_RESOURCES; + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + + DEBUGFUNC("nicAllocateAdapterMemory"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + prTxCtrl = &prAdapter->rTxCtrl; + + do { + /* 4 <0> Reset all Memory Handler */ +#if CFG_DBG_MGT_BUF + prAdapter->u4MemFreeDynamicCount = 0; + prAdapter->u4MemAllocDynamicCount = 0; +#endif + prAdapter->pucMgtBufCached = (PUINT_8) NULL; + prRxCtrl->pucRxCached = (PUINT_8) NULL; + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; + + /* 4 <1> Memory for Management Memory Pool and CMD_INFO_T */ + /* Allocate memory for the CMD_INFO_T and its MGMT memory pool. */ + prAdapter->u4MgtBufCachedSize = MGT_BUFFER_SIZE; + + LOCAL_NIC_ALLOCATE_MEMORY(prAdapter->pucMgtBufCached, + prAdapter->u4MgtBufCachedSize, VIR_MEM_TYPE, "COMMON MGMT MEMORY POOL"); + + /* 4 <2> Memory for RX Descriptor */ + /* Initialize the number of rx buffers we will have in our queue. */ + /* We may setup ucRxPacketDescriptors by GLUE Layer, and using + * this variable directly. + */ + /* Allocate memory for the SW receive structures. */ + prRxCtrl->u4RxCachedSize = CFG_RX_MAX_PKT_NUM * ALIGN_4(sizeof(SW_RFB_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize, VIR_MEM_TYPE, "SW_RFB_T"); + + /* 4 <3> Memory for TX DEscriptor */ + prTxCtrl->u4TxCachedSize = CFG_TX_MAX_PKT_NUM * ALIGN_4(sizeof(MSDU_INFO_T)); + + LOCAL_NIC_ALLOCATE_MEMORY(prTxCtrl->pucTxCached, prTxCtrl->u4TxCachedSize, VIR_MEM_TYPE, "MSDU_INFO_T"); + + /* 4 <4> Memory for Common Coalescing Buffer */ +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; + + /* Allocate memory for the common coalescing buffer. */ + prAdapter->u4CoalescingBufCachedSize = CFG_COALESCING_BUFFER_SIZE > CFG_RX_COALESCING_BUFFER_SIZE ? + CFG_COALESCING_BUFFER_SIZE : CFG_RX_COALESCING_BUFFER_SIZE; + + prAdapter->pucCoalescingBufCached = kalAllocateIOBuffer(prAdapter->u4CoalescingBufCachedSize); + + if (prAdapter->pucCoalescingBufCached == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %u bytes for coalescing buffer.\n", + prAdapter->u4CoalescingBufCachedSize); + break; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* 4 <5> Memory for enhanced interrupt response */ + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if (prAdapter->prSDIOCtrl == NULL) { + DBGLOG(NIC, ERROR, + "Could not allocate %zu bytes for interrupt response.\n", + sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + break; + } + + status = WLAN_STATUS_SUCCESS; + + } while (FALSE); + + if (status != WLAN_STATUS_SUCCESS) + nicReleaseAdapterMemory(prAdapter); + + return status; + +} /* end of nicAllocateAdapterMemory() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is responsible for releasing the allocated memory by +* nicAllocatedAdapterMemory(). +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicReleaseAdapterMemory(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <5> Memory for enhanced interrupt response */ + if (prAdapter->prSDIOCtrl) { + kalReleaseIOBuffer((PVOID) prAdapter->prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) NULL; + } + /* 4 <4> Memory for Common Coalescing Buffer */ +#if CFG_COALESCING_BUFFER_SIZE || CFG_SDIO_RX_AGG + if (prAdapter->pucCoalescingBufCached) { + kalReleaseIOBuffer((PVOID) prAdapter->pucCoalescingBufCached, prAdapter->u4CoalescingBufCachedSize); + prAdapter->pucCoalescingBufCached = (PUINT_8) NULL; + } +#endif /* CFG_COALESCING_BUFFER_SIZE */ + + /* 4 <3> Memory for TX Descriptor */ + if (prTxCtrl->pucTxCached) { + kalMemFree((PVOID) prTxCtrl->pucTxCached, VIR_MEM_TYPE, prTxCtrl->u4TxCachedSize); + prTxCtrl->pucTxCached = (PUINT_8) NULL; + } + /* 4 <2> Memory for RX Descriptor */ + if (prRxCtrl->pucRxCached) { + kalMemFree((PVOID) prRxCtrl->pucRxCached, VIR_MEM_TYPE, prRxCtrl->u4RxCachedSize); + prRxCtrl->pucRxCached = (PUINT_8) NULL; + } + /* 4 <1> Memory for Management Memory Pool */ + if (prAdapter->pucMgtBufCached) { + kalMemFree((PVOID) prAdapter->pucMgtBufCached, VIR_MEM_TYPE, prAdapter->u4MgtBufCachedSize); + prAdapter->pucMgtBufCached = (PUINT_8) NULL; + } +#if CFG_DBG_MGT_BUF + /* Check if all allocated memories are free */ + ASSERT(prAdapter->u4MemFreeDynamicCount == prAdapter->u4MemAllocDynamicCount); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief disable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicDisableInterrupt(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + prAdapter->fgIsIntEnable = FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief enable global interrupt +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicEnableInterrupt(IN P_ADAPTER_T prAdapter) +{ + BOOLEAN fgIsIntEnableCache; + + ASSERT(prAdapter); + fgIsIntEnableCache = prAdapter->fgIsIntEnable; + + prAdapter->fgIsIntEnable = TRUE; /* NOTE(Kevin): It must be placed before MCR GINT write. */ + + /* If need enable INT and also set LPOwn at the same time. */ + if (prAdapter->fgIsIntEnableWithLPOwnSet) { + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; /* NOTE(Kevin): It's better to place it + * before MCR GINT write. + */ + /* If INT was enabled, only set LPOwn */ + if (fgIsIntEnableCache) { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + prAdapter->fgIsFwOwn = TRUE; + } + /* If INT was not enabled, enable it and also set LPOwn now */ + else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET | WHLPCR_INT_EN_SET); + prAdapter->fgIsFwOwn = TRUE; + } + } + /* If INT was not enabled, enable it now */ + else if (!fgIsIntEnableCache) + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_INT_EN_SET); + +} /* end of nicEnableInterrupt() */ + +#if CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief For SDIO enhance mode, set the max rx len and tx status +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + + ASSERT(prAdapter); + + /* 4 <1> Check STATUS Buffer is DW alignment. */ + ASSERT(IS_ALIGN_4((ULONG)&prAdapter->prSDIOCtrl->u4WHISR)); + + /* 4 <2> Setup STATUS count. */ + { + HAL_MCR_RD(prAdapter, MCR_WHCR, &u4Value); + + /* 4 <2.1> Setup the number of maximum RX length to be report */ + u4Value &= ~(WHCR_MAX_HIF_RX_LEN_NUM); + u4Value |= ((SDIO_MAXIMUM_RX_LEN_NUM << WHCR_OFFSET_MAX_HIF_RX_LEN_NUM)); + + /* 4 <2.2> Setup RX enhancement mode */ +#if CFG_SDIO_RX_ENHANCE + u4Value |= WHCR_RX_ENHANCE_MODE_EN; +#else + u4Value &= ~WHCR_RX_ENHANCE_MODE_EN; +#endif /* CFG_SDIO_RX_AGG */ + + HAL_MCR_WR(prAdapter, MCR_WHCR, u4Value); + } + + return; + +} /* end of nicSDIOInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read interrupt status from hardware +* +* @param prAdapter pointer to the Adapter handler +* @param the interrupts +* +* @return N/A +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSDIOReadIntStatus(IN P_ADAPTER_T prAdapter, OUT PUINT_32 pu4IntStatus) +{ + P_SDIO_CTRL_T prSDIOCtrl; + + DEBUGFUNC("nicSDIOReadIntStatus"); + + ASSERT(prAdapter); + ASSERT(pu4IntStatus); + + /* + prSDIOCtrl is from IO buffer. + prAdapter->prSDIOCtrl = (P_SDIO_CTRL_T) + kalAllocateIOBuffer(sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + */ + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + HAL_PORT_RD(prAdapter, + MCR_WHISR, + sizeof(ENHANCE_MODE_DATA_STRUCT_T), (PUINT_8) prSDIOCtrl, sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + *pu4IntStatus = 0; + return; + } + + /* workaround */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + *pu4IntStatus = prSDIOCtrl->u4WHISR; + +} /* end of nicSDIOReadIntStatus() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to read interrupt status and then invoking +* dispatching procedure for the appropriate functions +* corresponding to specific interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4IntStatus = 0; + UINT_32 i; + + DEBUGFUNC("nicProcessIST"); + /* DBGLOG(NIC, LOUD, ("\n")); */ + + ASSERT(prAdapter); + + if (prAdapter->rAcpiState == ACPI_STATE_D3) { + DBGLOG(REQ, WARN, "Fail in set nicProcessIST! (Adapter not ready). ACPI=D%d, Radio=%d\n", + prAdapter->rAcpiState, prAdapter->fgIsRadioOff); + return WLAN_STATUS_ADAPTER_NOT_READY; + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == TRUE) + nicDisableClockGating(prAdapter); +#endif + + for (i = 0; i < CFG_IST_LOOP_COUNT; i++) { /* CFG_IST_LOOP_COUNT = 1 */ + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOReadIntStatus(prAdapter, &u4IntStatus); +#else + HAL_MCR_RD(prAdapter, MCR_WHISR, &u4IntStatus); +#endif /* CFG_SDIO_INTR_ENHANCE */ + +/* DBGLOG(NIC, TRACE, ("u4IntStatus: 0x%x\n", u4IntStatus)); */ + + if (u4IntStatus & ~(WHIER_DEFAULT | WHIER_FW_OWN_BACK_INT_EN)) { + DBGLOG(INTR, WARN, "Un-handled HISR %#x, HISR = %#x (HIER:0x%x)\n", + (UINT_32) (u4IntStatus & ~WHIER_DEFAULT), u4IntStatus, + (UINT_32) WHIER_DEFAULT); + u4IntStatus &= WHIER_DEFAULT; + } + + nicProcessIST_impl(prAdapter, u4IntStatus); + + if (u4IntStatus == 0) { + if (i == 0) + u4Status = WLAN_STATUS_NOT_INDICATING; + break; + } + } + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + if (prAdapter->fgIsClockGatingEnabled == FALSE) + nicEnableClockGating(prAdapter); +#endif + + return u4Status; +} /* end of nicProcessIST() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief The function used to dispatch the appropriate functions for specific +* interrupt bits +* +* @param prAdapter pointer to the Adapter handler +* u4IntStatus interrupt status bits +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_ADAPTER_NOT_READY +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicProcessIST_impl(IN P_ADAPTER_T prAdapter, IN UINT_32 u4IntStatus) +{ + UINT_32 u4IntCount = 0; + P_INT_EVENT_MAP_T prIntEventMap = NULL; + + ASSERT(prAdapter); + + prAdapter->u4IntStatus = u4IntStatus; + + /* Process each of the interrupt status consequently */ + prIntEventMap = &arIntEventMapTable[0]; + for (u4IntCount = 0; u4IntCount < ucIntEventMapSize; prIntEventMap++, u4IntCount++) { + if (prIntEventMap->u4Int & prAdapter->u4IntStatus) { + if (prIntEventMap->u4Event == INT_EVENT_RX && prAdapter->fgIsEnterD3ReqIssued == TRUE) { + /* ignore */ + } else if (apfnEventFuncTable[prIntEventMap->u4Event] != NULL) { + apfnEventFuncTable[prIntEventMap->u4Event] (prAdapter); + } else { + DBGLOG(INTR, WARN, + "Empty INTR handler! ISAR bit#: %u, event:%u, func: %p\n", + prIntEventMap->u4Int, prIntEventMap->u4Event, + apfnEventFuncTable[prIntEventMap->u4Event]); + + ASSERT(0); /* to trap any NULL interrupt handler */ + } + prAdapter->u4IntStatus &= ~prIntEventMap->u4Int; + } + } + + return WLAN_STATUS_SUCCESS; +} /* end of nicProcessIST_impl() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Verify the CHIP ID +* +* @param prAdapter a pointer to adapter private data structure. +* +* +* @retval TRUE CHIP ID is the same as the setting compiled +* @retval FALSE CHIP ID is different from the setting compiled +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicVerifyChipID(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4CIR = 0; + + ASSERT(prAdapter); + + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4CIR); + + DBGLOG(NIC, TRACE, "Chip ID: 0x%x\n", (UINT_32) (u4CIR & WCIR_CHIP_ID)); + DBGLOG(NIC, TRACE, "Revision ID: 0x%x\n", (UINT_32) ((u4CIR & WCIR_REVISION_ID) >> 16)); + +#if 0 + if (((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_72) && ((u4CIR & WCIR_CHIP_ID) != MTK_CHIP_REV_82)) + return FALSE; +#endif + + prAdapter->ucRevID = (UINT_8) (((u4CIR & WCIR_REVISION_ID) >> 16) & 0xF); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the MCR to the appropriate init value, and verify the init +* value +* +* @param prAdapter a pointer to adapter private data structure. +* +* @return - +*/ +/*----------------------------------------------------------------------------*/ +VOID nicMCRInit(IN P_ADAPTER_T prAdapter) +{ + + ASSERT(prAdapter); + + /* 4 <0> Initial value */ +} + +VOID nicHifInit(IN P_ADAPTER_T prAdapter) +{ + + ASSERT(prAdapter); +#if 0 + /* reset event */ + nicPutMailbox(prAdapter, 0, 0x52455345); /* RESE */ + nicPutMailbox(prAdapter, 1, 0x545F5746); /* T_WF */ + nicSetSwIntr(prAdapter, BIT(16)); +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the Adapter soft variable +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicInitializeAdapter(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + ASSERT(prAdapter); + + prAdapter->fgIsIntEnableWithLPOwnSet = FALSE; + + do { + if (!nicVerifyChipID(prAdapter)) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + /* 4 <1> MCR init */ + nicMCRInit(prAdapter); + +#if CFG_SDIO_INTR_ENHANCE + nicSDIOInit(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + HAL_MCR_WR(prAdapter, MCR_WHIER, WHIER_DEFAULT); + + /* 4 <2> init FW HIF */ + nicHifInit(prAdapter); + } while (FALSE); + + return u4Status; +} + +#if defined(_HIF_SPI) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Restore the SPI Mode Select to default mode, +* this is important while driver is unload, and this must be last mcr +* since the operation will let the hif use 8bit mode access +* +* \param[in] prAdapter a pointer to adapter private data structure. +* \param[in] eGPIO2_Mode GPIO2 operation mode +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +void nicRestoreSpiDefMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + HAL_MCR_WR(prAdapter, MCR_WCSR, SPICSR_8BIT_MODE_DATA); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessAbnormalInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Value = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = prAdapter->prGlueInfo; + prGlueInfo->IsrAbnormalCnt++; + HAL_MCR_RD(prAdapter, MCR_WASR, &u4Value); + DBGLOG(REQ, WARN, "MCR_WASR: 0x%x\n", u4Value); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessFwOwnBackInterrupt(IN P_ADAPTER_T prAdapter) +{ + +} /* end of nicProcessFwOwnBackInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief . +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessSoftwareInterrupt(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4IntrBits; + + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + u4IntrBits = prAdapter->u4IntStatus & BITS(8, 31); + + prGlueInfo->IsrSoftWareCnt++; + + if ((u4IntrBits & WHISR_D2H_SW_ASSERT_INFO_INT) != 0) { + nicPrintFirmwareAssertInfo(prAdapter); +#if CFG_CHIP_RESET_SUPPORT + glSendResetRequest(); +#endif + } +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) + ASSERT((u4IntrBits & (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)) + != (ACK_GATING_ENABLE_D2H_INT | ACK_GATING_DISABLE_D2H_INT)); + + if (u4IntrBits & ACK_GATING_ENABLE_D2H_INT) + prAdapter->fgIsClockGatingEnabled = TRUE; + + if (u4IntrBits & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + + /* Indicate Service Thread for TX */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + } +#endif + + DBGLOG(REQ, WARN, "u4IntrBits: 0x%x\n", u4IntrBits); +} /* end of nicProcessSoftwareInterrupt() */ + +VOID nicPutMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, IN UINT_32 u4Data) +{ + if (u4MailboxNum == 0) { + /* HAL_MCR_WR */ + HAL_MCR_WR(prAdapter, MCR_H2DSM0R, u4Data); + } else if (u4MailboxNum == 1) { + /* HAL_MCR_WR */ + HAL_MCR_WR(prAdapter, MCR_H2DSM1R, u4Data); + } else { + ASSERT(0); + } +} + +VOID nicGetMailbox(IN P_ADAPTER_T prAdapter, IN UINT_32 u4MailboxNum, OUT PUINT_32 pu4Data) +{ + if (u4MailboxNum == 0) { + /* HAL_MCR_RD */ + HAL_MCR_RD(prAdapter, MCR_D2HRM0R, pu4Data); + } else if (u4MailboxNum == 1) { + /* HAL_MCR_RD */ + HAL_MCR_RD(prAdapter, MCR_D2HRM1R, pu4Data); + } else { + ASSERT(0); + } +} + +VOID nicSetSwIntr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4SwIntrBitmap) +{ + /* NOTE: + * SW interrupt in HW bit 16 is mapping to SW bit 0 (shift 16bit in HW transparancy) + * SW interrupt valid from b0~b15 + */ + ASSERT((u4SwIntrBitmap & BITS(0, 15)) == 0); +/* DBGLOG(NIC, TRACE, ("u4SwIntrBitmap: 0x%08x\n", u4SwIntrBitmap)); */ + + HAL_MCR_WR(prAdapter, MCR_WSICR, u4SwIntrBitmap); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rPendingCmdQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_CMD_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_CMD_INFO_T nicGetPendingCmdInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + prCmdQue = &prAdapter->rPendingCmdQueue; + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->ucCmdSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + prCmdInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_PENDING); + + return prCmdInfo; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to dequeue from prAdapter->rTxCtrl.rTxMgmtTxingQueue +* with specified sequential number +* +* @param prAdapter Pointer of ADAPTER_T +* ucSeqNum Sequential Number +* +* @retval - P_MSDU_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T nicGetPendingTxMsduInfo(IN P_ADAPTER_T prAdapter, IN UINT_8 ucSeqNum) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if (prMsduInfo->ucTxSeqNum == ucSeqNum) + break; + + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfo; +} + +P_MSDU_INFO_T nicGetPendingStaMMPDU(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx) +{ + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; + P_QUE_T prTxingQue = (P_QUE_T) NULL; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + GLUE_SPIN_LOCK_DECLARATION(); + + if (prAdapter == NULL) { + ASSERT(FALSE); + return NULL; + } + + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + do { + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if ((prMsduInfo->ucStaRecIndex == ucStaRecIdx) && (prMsduInfo->pfTxDoneHandler != NULL)) { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfo, prMsduInfoListHead); + prMsduInfoListHead = prMsduInfo; + } else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + return prMsduInfoListHead; +} /* nicGetPendingStaMMPDU */ + +VOID nicFreePendingTxMsduInfoByNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + P_QUE_T prTxingQue; + QUE_T rTempQue; + P_QUE_T prTempQue = &rTempQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_MSDU_INFO_T prMsduInfoListHead = (P_MSDU_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfoListTail = (P_MSDU_INFO_T) NULL; + P_MSDU_INFO_T prMsduInfo = (P_MSDU_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + prTxingQue = &(prAdapter->rTxCtrl.rTxMgmtTxingQueue); + QUEUE_MOVE_ALL(prTempQue, prTxingQue); + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prMsduInfo = (P_MSDU_INFO_T) prQueueEntry; + + if ((ENUM_NETWORK_TYPE_INDEX_T) (prMsduInfo->ucNetworkType) == eNetworkType) { + if (prMsduInfoListHead == NULL) { + prMsduInfoListHead = prMsduInfoListTail = prMsduInfo; + } else { + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, prMsduInfo); + prMsduInfoListTail = prMsduInfo; + } + } else { + QUEUE_INSERT_TAIL(prTxingQue, prQueueEntry); + + prMsduInfo = NULL; + } + + QUEUE_REMOVE_HEAD(prTempQue, prQueueEntry, P_QUE_ENTRY_T); + } + QUEUE_CONCATENATE_QUEUES(prTxingQue, prTempQue); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + /* free */ + if (prMsduInfoListHead) + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfoListHead); + + return; + +} /* end of nicFreePendingTxMsduInfoByNetwork() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a CMD sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicIncreaseCmdSeqNum(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + prAdapter->ucCmdSeqNum++; + ucRetval = prAdapter->ucCmdSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_SEQ_NUM); + + return ucRetval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This procedure is used to retrieve a TX sequence number atomically +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval - UINT_8 +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicIncreaseTxSeqNum(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucRetval; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + prAdapter->ucTxSeqNum++; + ucRetval = prAdapter->ucTxSeqNum; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_SEQ_NUM); + + return ucRetval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to handle +* media state change event +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicMediaStateChange(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, IN P_EVENT_CONNECTION_STATUS prConnectionStatus) +{ + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + switch (eNetworkType) { + case NETWORK_TYPE_AIS_INDEX: + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + DBGLOG(NIC, TRACE, "DisByMC\n"); + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + + /* reset buffered link quality information */ + prAdapter->fgIsLinkQualityValid = FALSE; + prAdapter->fgIsLinkRateValid = FALSE; + } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { /* connected */ + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + prAdapter->rWlanInfo.rCurrBssId.u4Privacy + = prConnectionStatus->ucEncryptStatus; /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse + = PARAM_NETWORK_TYPE_AUTOMODE; /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; + prAdapter->rWlanInfo.rCurrBssId.eOpMode + = (ENUM_PARAM_OP_MODE_T) prConnectionStatus->ucInfraMode; + + /* always indicate to OS according to MSDN (re-association/roaming) */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_CONNECTED) { + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } else { + /* connected -> connected : roaming ? */ + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_ROAM_OUT_FIND_BEST, NULL, 0); + } + } + break; + +#if CFG_ENABLE_BT_OVER_WIFI + case NETWORK_TYPE_BOW_INDEX: + break; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + case NETWORK_TYPE_P2P_INDEX: + break; +#endif + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} /* nicMediaStateChange */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to convert between +* frequency and channel number +* +* @param u4ChannelNum +* +* @retval - Frequency in unit of KHz, 0 for invalid channel number +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicChannelNum2Freq(UINT_32 u4ChannelNum) +{ + UINT_32 u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return 1000 * u4ChannelInMHz; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to convert between +* frequency and channel number +* +* @param u4FreqInKHz +* +* @retval - Frequency Number, 0 for invalid freqency +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicFreq2ChannelNum(UINT_32 u4FreqInKHz) +{ + switch (u4FreqInKHz) { + case 2412000: + return 1; + case 2417000: + return 2; + case 2422000: + return 3; + case 2427000: + return 4; + case 2432000: + return 5; + case 2437000: + return 6; + case 2442000: + return 7; + case 2447000: + return 8; + case 2452000: + return 9; + case 2457000: + return 10; + case 2462000: + return 11; + case 2467000: + return 12; + case 2472000: + return 13; + case 2484000: + return 14; + case 3665000: + return 133; /* 802.11y */ + case 3685000: + return 137; /* 802.11y */ + case 4915000: + return 183; + case 4920000: + return 184; + case 4925000: + return 185; + case 4930000: + return 186; + case 4935000: + return 187; + case 4940000: + return 188; + case 4945000: + return 189; + case 4960000: + return 192; + case 4980000: + return 196; + case 5170000: + return 34; + case 5180000: + return 36; + case 5190000: + return 38; + case 5200000: + return 40; + case 5210000: + return 42; + case 5220000: + return 44; + case 5230000: + return 46; + case 5240000: + return 48; + case 5250000: + return 50; + case 5260000: + return 52; + case 5270000: + return 54; + case 5280000: + return 56; + case 5290000: + return 58; + case 5300000: + return 60; + case 5320000: + return 64; + case 5500000: + return 100; + case 5520000: + return 104; + case 5540000: + return 108; + case 5560000: + return 112; + case 5580000: + return 116; + case 5600000: + return 120; + case 5620000: + return 124; + case 5640000: + return 128; + case 5660000: + return 132; + case 5680000: + return 136; + case 5700000: + return 140; + case 5745000: + return 149; + case 5765000: + return 153; + case 5785000: + return 157; + case 5805000: + return 161; + case 5825000: + return 165; + case 5845000: + return 169; + case 5865000: + return 173; + default: + return 0; + } +} + +/* firmware command wrapper */ +/* NETWORK (WIFISYS) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to activate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicActivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + P_BSS_INFO_T prBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 1; + + if (((UINT_8) eNetworkTypeIdx) < NETWORK_TYPE_INDEX_NUM) { + prBssInfo = &prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]; + prBssInfo->fg40mBwAllowed = FALSE; + prBssInfo->fgAssoc40mBwAllowed = FALSE; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to deactivate WIFISYS for specified network +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of network type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicDeactivateNetwork(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + WLAN_STATUS u4Status; + CMD_BSS_ACTIVATE_CTRL rCmdActivateCtrl; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdActivateCtrl.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdActivateCtrl.ucActive = 0; + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_BSS_ACTIVATE_CTRL, + TRUE, + FALSE, + FALSE, + NULL, + NULL, sizeof(CMD_BSS_ACTIVATE_CTRL), (PUINT_8)&rCmdActivateCtrl, NULL, 0); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + nicFreePendingTxMsduInfoByNetwork(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); + + return u4Status; +} + +/* BSS-INFO */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to sync bss info with firmware +* when a new BSS has been connected or disconnected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO type +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateBss(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + WLAN_STATUS u4Status; + P_BSS_INFO_T prBssInfo; + CMD_SET_BSS_INFO rCmdSetBssInfo; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + kalMemZero(&rCmdSetBssInfo, sizeof(CMD_SET_BSS_INFO)); + + rCmdSetBssInfo.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdSetBssInfo.ucConnectionState = (UINT_8) prBssInfo->eConnectionState; + rCmdSetBssInfo.ucCurrentOPMode = (UINT_8) prBssInfo->eCurrentOPMode; + rCmdSetBssInfo.ucSSIDLen = (UINT_8) prBssInfo->ucSSIDLen; + kalMemCopy(rCmdSetBssInfo.aucSSID, prBssInfo->aucSSID, prBssInfo->ucSSIDLen); + COPY_MAC_ADDR(rCmdSetBssInfo.aucBSSID, prBssInfo->aucBSSID); + rCmdSetBssInfo.ucIsQBSS = (UINT_8) prBssInfo->fgIsQBSS; + rCmdSetBssInfo.ucNonHTBasicPhyType = prBssInfo->ucNonHTBasicPhyType; + rCmdSetBssInfo.u2OperationalRateSet = prBssInfo->u2OperationalRateSet; + rCmdSetBssInfo.u2BSSBasicRateSet = prBssInfo->u2BSSBasicRateSet; + rCmdSetBssInfo.ucPhyTypeSet = prBssInfo->ucPhyTypeSet; + rCmdSetBssInfo.fgHiddenSsidMode = prBssInfo->eHiddenSsidType; +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + COPY_MAC_ADDR(rCmdSetBssInfo.aucOwnMac, prBssInfo->aucOwnMacAddr); +#endif + + rlmFillSyncCmdParam(&rCmdSetBssInfo.rBssRlmParam, prBssInfo); + + rCmdSetBssInfo.fgWapiMode = (UINT_8) FALSE; + + if (rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + rCmdSetBssInfo.ucAuthMode = (UINT_8) prConnSettings->eAuthMode; + rCmdSetBssInfo.ucEncStatus = (UINT_8) prConnSettings->eEncStatus; + rCmdSetBssInfo.fgWapiMode = (UINT_8) prConnSettings->fgWapiMode; + } +#if CFG_ENABLE_BT_OVER_WIFI + else if (rCmdSetBssInfo.ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) { + /* P_CONNECTION_SETTINGS_T prConnSettings = &(prAdapter->rWifiVar.rConnSettings); */ + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; + } +#endif + else { +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + if (kalP2PGetCipher(prAdapter->prGlueInfo)) { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; + } else { + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_OPEN; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION_DISABLED; + } + /* Need the probe response to detect the PBC overlap */ + rCmdSetBssInfo.fgIsApMode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); + } +#else + rCmdSetBssInfo.ucAuthMode = (UINT_8) AUTH_MODE_WPA2_PSK; + rCmdSetBssInfo.ucEncStatus = (UINT_8) ENUM_ENCRYPTION3_KEY_ABSENT; +#endif + } + + if (eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + + cnmAisInfraConnectNotify(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && + (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) && (prBssInfo->prStaRecOfAP != NULL)) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + else if (eNetworkTypeIdx == NETWORK_TYPE_BOW_INDEX && + prBssInfo->eCurrentOPMode == OP_MODE_BOW && prBssInfo->prStaRecOfAP != NULL) { + rCmdSetBssInfo.ucStaRecIdxOfAP = prBssInfo->prStaRecOfAP->ucIndex; + } +#endif + else + rCmdSetBssInfo.ucStaRecIdxOfAP = STA_REC_INDEX_NOT_FOUND; + + u4Status = wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_BSS_INFO, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_SET_BSS_INFO), (PUINT_8)&rCmdSetBssInfo, NULL, 0); + + /* if BSS-INFO is going to be disconnected state, free all correlated station records */ + if (prBssInfo->eConnectionState == PARAM_MEDIA_STATE_DISCONNECTED) { + /* clear client list */ + bssClearClientList(prAdapter, prBssInfo); + + /* free all correlated station records */ + cnmStaFreeAllStaByNetType(prAdapter, eNetworkTypeIdx, FALSE); + qmFreeAllByNetType(prAdapter, eNetworkTypeIdx); + kalClearSecurityFramesByNetType(prAdapter->prGlueInfo, eNetworkTypeIdx); +#if CFG_ENABLE_GTK_FRAME_FILTER + if (prBssInfo->prIpV4NetAddrList) + FREE_IPV4_NETWORK_ADDR_LIST(prBssInfo->prIpV4NetAddrList); +#endif + } + + return u4Status; +} + +/* BSS-INFO Indication (PM) */ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been created. (for AdHoc / P2P-GO) +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssCreated(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CREATED rCmdIndicatePmBssCreated; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssCreated.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdIndicatePmBssCreated.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssCreated.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssCreated.u2AtimWindow = prBssInfo->u2ATIMWindow; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_CREATED, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_CREATED), (PUINT_8)&rCmdIndicatePmBssCreated, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been connected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssConnected(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_INDICATE_PM_BSS_CONNECTED rCmdIndicatePmBssConnected; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + + rCmdIndicatePmBssConnected.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + rCmdIndicatePmBssConnected.ucDtimPeriod = prBssInfo->ucDTIMPeriod; + rCmdIndicatePmBssConnected.u2AssocId = prBssInfo->u2AssocId; + rCmdIndicatePmBssConnected.u2BeaconInterval = prBssInfo->u2BeaconInterval; + rCmdIndicatePmBssConnected.u2AtimWindow = prBssInfo->u2ATIMWindow; + + rCmdIndicatePmBssConnected.ucBmpDeliveryAC = prBssInfo->rPmProfSetupInfo.ucBmpDeliveryAC; + rCmdIndicatePmBssConnected.ucBmpTriggerAC = prBssInfo->rPmProfSetupInfo.ucBmpTriggerAC; + + /* DBGPRINTF("nicPmIndicateBssConnected: ucBmpDeliveryAC:0x%x, ucBmpTriggerAC:0x%x", */ + /* rCmdIndicatePmBssConnected.ucBmpDeliveryAC, */ + /* rCmdIndicatePmBssConnected.ucBmpTriggerAC); */ + + if ((eNetworkTypeIdx == NETWORK_TYPE_AIS_INDEX) +#if CFG_ENABLE_WIFI_DIRECT + || ((eNetworkTypeIdx == NETWORK_TYPE_P2P_INDEX) && (prAdapter->fgIsP2PRegistered)) +#endif + ) { + if (prBssInfo->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = + (UINT_8) prBssInfo->prStaRecOfAP->fgIsUapsdSupported; + } else { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; /* @FIXME */ + } + } else { + rCmdIndicatePmBssConnected.fgIsUapsdConnection = 0; + } + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_CONNECTED, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_CONNECTED), + (PUINT_8)&rCmdIndicatePmBssConnected, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate PM that +* a BSS has been disconnected +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicPmIndicateBssAbort(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + CMD_INDICATE_PM_BSS_ABORT rCmdIndicatePmBssAbort; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + rCmdIndicatePmBssAbort.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_INDICATE_PM_BSS_ABORT, + TRUE, + FALSE, + FALSE, + NULL, + NULL, + sizeof(CMD_INDICATE_PM_BSS_ABORT), (PUINT_8)&rCmdIndicatePmBssAbort, NULL, 0); +} + +WLAN_STATUS +nicConfigPowerSaveProfile(IN P_ADAPTER_T prAdapter, + ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, PARAM_POWER_MODE ePwrMode, BOOLEAN fgEnCmdEvent) +{ + DEBUGFUNC("nicConfigPowerSaveProfile"); + DBGLOG(NIC, TRACE, "eNetTypeIndex:%d, ePwrMode:%d, fgEnCmdEvent:%d\n", + eNetTypeIndex, ePwrMode, fgEnCmdEvent); + + ASSERT(prAdapter); + + if (eNetTypeIndex >= NETWORK_TYPE_INDEX_NUM) { + ASSERT(0); + return WLAN_STATUS_NOT_SUPPORTED; + } +/* prAdapter->rWlanInfo.ePowerSaveMode.ucNetTypeIndex = eNetTypeIndex; */ +/* prAdapter->rWlanInfo.ePowerSaveMode.ucPsProfile = (UINT_8)ePwrMode; */ + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucNetTypeIndex = eNetTypeIndex; + prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex].ucPsProfile = (UINT_8) ePwrMode; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_POWER_SAVE_MODE, + TRUE, + FALSE, + (fgEnCmdEvent ? TRUE : FALSE), + (fgEnCmdEvent ? nicCmdEventSetCommon : NULL), + (fgEnCmdEvent ? nicOidCmdTimeoutCommon : NULL), + sizeof(CMD_PS_PROFILE_T), + (PUINT_8)&(prAdapter->rWlanInfo.arPowerSaveMode[eNetTypeIndex]), + NULL, sizeof(PARAM_POWER_MODE) + ); + +} /* end of wlanoidSetAcpiDevicePowerStateMode() */ + +WLAN_STATUS nicEnterCtiaMode(IN P_ADAPTER_T prAdapter, BOOLEAN fgEnterCtia, BOOLEAN fgEnCmdEvent) +{ + CMD_SW_DBG_CTRL_T rCmdSwCtrl; + CMD_ACCESS_REG rCmdAccessReg; + WLAN_STATUS rWlanStatus; + + DEBUGFUNC("nicEnterCtiaMode"); + DBGLOG(NIC, TRACE, "nicEnterCtiaMode: %d\n", fgEnterCtia); + + ASSERT(prAdapter); + + rWlanStatus = WLAN_STATUS_SUCCESS; + + if (fgEnterCtia) { + /* 1. Disable On-Lin Scan */ + prAdapter->fgEnOnlineScan = FALSE; + + /* 3. Disable FIFO FULL no ack */ + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x904; + wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ + FALSE, /* TRUE, */ + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); + + /* 4. Disable Roaming */ + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* Disalbe auto tx power */ + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x0; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at CAM mode */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 0; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeCAM; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); + } + + /* 5. Disable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = TRUE; + } else { + /* 1. Enaable On-Lin Scan */ + prAdapter->fgEnOnlineScan = TRUE; + + /* 3. Enable FIFO FULL no ack */ + rCmdAccessReg.u4Address = 0x60140028; + rCmdAccessReg.u4Data = 0x905; + wlanSendSetQueryCmd(prAdapter, CMD_ID_ACCESS_REG, TRUE, /* FALSE, */ + FALSE, /* TRUE, */ + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8)&rCmdAccessReg, NULL, 0); + + /* 4. Enable Roaming */ + rCmdSwCtrl.u4Id = 0x90000204; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + rCmdSwCtrl.u4Id = 0x90000200; + rCmdSwCtrl.u4Data = 0x820000; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* Enable auto tx power */ + /* */ + + rCmdSwCtrl.u4Id = 0xa0100003; + rCmdSwCtrl.u4Data = 0x1; + wlanSendSetQueryCmd(prAdapter, + CMD_ID_SW_DBG_CTRL, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_SW_DBG_CTRL_T), (PUINT_8)&rCmdSwCtrl, NULL, 0); + + /* 2. Keep at Fast PS */ + { + PARAM_POWER_MODE ePowerMode; + + prAdapter->u4CtiaPowerMode = 2; + prAdapter->fgEnCtiaPowerMode = TRUE; + + ePowerMode = Param_PowerModeFast_PSP; + rWlanStatus = nicConfigPowerSaveProfile(prAdapter, + NETWORK_TYPE_AIS_INDEX, ePowerMode, fgEnCmdEvent); + } + + /* 5. Enable Beacon Timeout Detection */ + prAdapter->fgDisBcnLostDetection = FALSE; + + } + + return rWlanStatus; +} /* end of nicEnterCtiaMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to indicate firmware domain +* for beacon generation parameters +* +* @param prAdapter Pointer of ADAPTER_T +* eIeUpdMethod, Update Method +* eNetTypeIndex Index of Network +* u2Capability Capability +* aucIe Pointer to buffer of IEs +* u2IELen Length of IEs +* +* @retval - WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* WLAN_STATUS_PENDING +* WLAN_STATUS_INVALID_DATA +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateBeaconIETemplate(IN P_ADAPTER_T prAdapter, + IN ENUM_IE_UPD_METHOD_T eIeUpdMethod, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIndex, + IN UINT_16 u2Capability, IN PUINT_8 aucIe, IN UINT_16 u2IELen) +{ + P_CMD_BEACON_TEMPLATE_UPDATE prCmdBcnUpdate; + UINT_16 u2CmdBufLen = 0; + P_GLUE_INFO_T prGlueInfo; + P_CMD_INFO_T prCmdInfo; + P_WIFI_CMD_T prWifiCmd; + UINT_8 ucCmdSeqNum; + + DEBUGFUNC("wlanUpdateBeaconIETemplate"); + + DBGLOG(NIC, LOUD, "\nnicUpdateBeaconIETemplate\n"); + + ASSERT(prAdapter); + prGlueInfo = prAdapter->prGlueInfo; + + if (u2IELen > MAX_IE_LENGTH) + return WLAN_STATUS_INVALID_DATA; + + if (eIeUpdMethod == IE_UPD_METHOD_UPDATE_RANDOM || eIeUpdMethod == IE_UPD_METHOD_UPDATE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, aucIE) + u2IELen; + } else if (eIeUpdMethod == IE_UPD_METHOD_DELETE_ALL) { + u2CmdBufLen = OFFSET_OF(CMD_BEACON_TEMPLATE_UPDATE, u2IELen); + } else { + ASSERT(0); + return WLAN_STATUS_FAILURE; + } + + /* prepare command info */ + prCmdInfo = cmdBufAllocateCmdInfo(prAdapter, (CMD_HDR_SIZE + u2CmdBufLen)); + if (!prCmdInfo) { + DBGLOG(NIC, ERROR, "Allocate CMD_INFO_T ==> FAILED.\n"); + return WLAN_STATUS_FAILURE; + } + /* increase command sequence number */ + ucCmdSeqNum = nicIncreaseCmdSeqNum(prAdapter); + DBGLOG(REQ, TRACE, "ucCmdSeqNum =%d\n", ucCmdSeqNum); + + /* Setup common CMD Info Packet */ + prCmdInfo->eCmdType = COMMAND_TYPE_NETWORK_IOCTL; + prCmdInfo->eNetworkType = eNetTypeIndex; + prCmdInfo->u2InfoBufLen = (UINT_16) (CMD_HDR_SIZE + u2CmdBufLen); + prCmdInfo->pfCmdDoneHandler = NULL; /* @FIXME */ + prCmdInfo->pfCmdTimeoutHandler = NULL; /* @FIXME */ + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->ucCID = CMD_ID_UPDATE_BEACON_CONTENT; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + prCmdInfo->fgDriverDomainMCR = FALSE; + prCmdInfo->ucCmdSeqNum = ucCmdSeqNum; + prCmdInfo->u4SetInfoLen = u2CmdBufLen; + prCmdInfo->pvInformationBuffer = NULL; + prCmdInfo->u4InformationBufferLength = 0; + + /* Setup WIFI_CMD_T (no payload) */ + prWifiCmd = (P_WIFI_CMD_T) (prCmdInfo->pucInfoBuffer); + prWifiCmd->u2TxByteCount_UserPriority = prCmdInfo->u2InfoBufLen; + prWifiCmd->ucCID = prCmdInfo->ucCID; + prWifiCmd->ucSetQuery = prCmdInfo->fgSetQuery; + prWifiCmd->ucSeqNum = prCmdInfo->ucCmdSeqNum; + + prCmdBcnUpdate = (P_CMD_BEACON_TEMPLATE_UPDATE) (prWifiCmd->aucBuffer); + + /* fill beacon updating command */ + prCmdBcnUpdate->ucUpdateMethod = (UINT_8) eIeUpdMethod; + prCmdBcnUpdate->ucNetTypeIndex = (UINT_8) eNetTypeIndex; + prCmdBcnUpdate->u2Capability = u2Capability; + prCmdBcnUpdate->u2IELen = u2IELen; + if (u2IELen > 0) + kalMemCopy(prCmdBcnUpdate->aucIE, aucIe, u2IELen); + + /* insert into prCmdQueue */ + kalEnqueueCommand(prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + + /* wakeup txServiceThread later */ + GLUE_SET_EVENT(prGlueInfo); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to initialization PHY related +* varaibles +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicSetAvailablePhyTypeSet(IN P_ADAPTER_T prAdapter) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prAdapter); + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + + if (prConnSettings->eDesiredPhyConfig >= PHY_CONFIG_NUM) { + ASSERT(0); + return; + } + + prAdapter->rWifiVar.ucAvailablePhyTypeSet = aucPhyCfg2PhyTypeSet[prConnSettings->eDesiredPhyConfig]; + + if (prAdapter->rWifiVar.ucAvailablePhyTypeSet & PHY_TYPE_BIT_ERP) + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_ERP_INDEX; + /* NOTE(Kevin): Because we don't have N only mode, TBD */ + else { /* if (ucNonHTPhyTypeSet & PHY_TYPE_HR_DSSS_INDEX) */ + + prAdapter->rWifiVar.eNonHTBasicPhyType2G4 = PHY_TYPE_HR_DSSS_INDEX; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* eNetworkTypeIdx Index of BSS-INFO +* +* @retval - +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicQmUpdateWmmParms(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_BSS_INFO_T prBssInfo; + CMD_UPDATE_WMM_PARMS_T rCmdUpdateWmmParms; + + ASSERT(prAdapter); + ASSERT(eNetworkTypeIdx < NETWORK_TYPE_INDEX_NUM); + + DBGLOG(QM, EVENT, "sizeof(AC_QUE_PARMS_T): %zu\n", sizeof(AC_QUE_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(CMD_UPDATE_WMM_PARMS): %zu\n", sizeof(CMD_UPDATE_WMM_PARMS_T)); + DBGLOG(QM, EVENT, "sizeof(WIFI_CMD_T): %zu\n", sizeof(WIFI_CMD_T)); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkTypeIdx]); + rCmdUpdateWmmParms.ucNetTypeIndex = (UINT_8) eNetworkTypeIdx; + kalMemCopy(&rCmdUpdateWmmParms.arACQueParms[0], &prBssInfo->arACQueParms[0], (sizeof(AC_QUE_PARMS_T) * AC_NUM)); + + rCmdUpdateWmmParms.fgIsQBSS = prBssInfo->fgIsQBSS; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_UPDATE_WMM_PARMS, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_UPDATE_WMM_PARMS_T), (PUINT_8)&rCmdUpdateWmmParms, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power gain corresponding to +* each band/modulation combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_PWR_T), (PUINT_8) prTxPwrParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to set auto tx power parameter +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of Auto TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicSetAutoTxPower(IN P_ADAPTER_T prAdapter, IN P_CMD_AUTO_POWER_PARAM_T prAutoPwrParam) +{ + DEBUGFUNC("nicSetAutoTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_AUTOPWR_CTRL, + TRUE, + FALSE, + FALSE, + NULL, NULL, sizeof(CMD_AUTO_POWER_PARAM_T), (PUINT_8) prAutoPwrParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update TX power gain corresponding to +* each band/modulation combination +* +* @param prAdapter Pointer of ADAPTER_T +* prTxPwrParam Pointer of TX power parameters +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicSetAutoTxPowerControl(IN P_ADAPTER_T prAdapter, IN P_CMD_TX_PWR_T prTxPwrParam) +{ + DEBUGFUNC("nicUpdateTxPower"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_TX_PWR, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_TX_PWR_T), (PUINT_8) prTxPwrParam, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update power offset around 5GHz band +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of 5GHz power offset parameter +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdate5GOffset(IN P_ADAPTER_T prAdapter, IN P_CMD_5G_PWR_OFFSET_T pr5GPwrOffset) +{ + DEBUGFUNC("nicUpdate5GOffset"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_5G_PWR_OFFSET, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_5G_PWR_OFFSET_T), (PUINT_8) pr5GPwrOffset, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update DPD calibration result +* +* @param prAdapter Pointer of ADAPTER_T +* pr5GPwrOffset Pointer of parameter for DPD calibration result +* +* @retval WLAN_STATUS_PENDING +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicUpdateDPD(IN P_ADAPTER_T prAdapter, IN P_CMD_PWR_PARAM_T prDpdCalResult) +{ + DEBUGFUNC("nicUpdateDPD"); + + ASSERT(prAdapter); + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_PWR_PARAM, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_PWR_PARAM_T), (PUINT_8) prDpdCalResult, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function starts system service such as timer and +* memory pools +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* <1> Initialize MGMT Memory pool and STA_REC */ + cnmMemInit(prAdapter); + cnmStaRecInit(prAdapter); + cmdBufInitialize(prAdapter); + + /* <2> Mailbox Initialization */ + mboxInitialize(prAdapter); + + /* <3> Timer Initialization */ + cnmTimerInitialize(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function reset some specific system service, +* such as STA-REC +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicResetSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitSystemService(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + /* Timer Destruction */ + cnmTimerDestroy(prAdapter); + + /* Mailbox Destruction */ + mboxDestroy(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicInitMGMT(IN P_ADAPTER_T prAdapter, IN P_REG_INFO_T prRegInfo) +{ + ASSERT(prAdapter); + + /* CNM Module - initialization */ + cnmInit(prAdapter); + + /* RLM Module - initialization */ + rlmFsmEventInit(prAdapter); + + /* SCN Module - initialization */ + scnInit(prAdapter); + + /* AIS Module - intiailization */ + aisInitializeConnectionSettings(prAdapter, prRegInfo); + aisFsmInit(prAdapter); + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - intiailization */ + roamingFsmInit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + +#if CFG_SUPPORT_SWCR + swCrDebugInit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +#if (CFG_SUPPORT_TDLS == 1) + TdlsexInit(prAdapter); +#endif /* CFG_SUPPORT_TDLS */ + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to update WMM Parms +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUninitMGMT(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +#if CFG_SUPPORT_SWCR + swCrDebugUninit(prAdapter); +#endif /* CFG_SUPPORT_SWCR */ + +#if CFG_SUPPORT_ROAMING + /* Roaming Module - unintiailization */ + roamingFsmUninit(prAdapter); +#endif /* CFG_SUPPORT_ROAMING */ + + /* AIS Module - unintiailization */ + aisFsmUninit(prAdapter); + + /* SCN Module - unintiailization */ + scnUninit(prAdapter); + + /* RLM Module - uninitialization */ + rlmFsmEventUninit(prAdapter); + + /* CNM Module - uninitialization */ + cnmUninit(prAdapter); + +#if (CFG_SUPPORT_TDLS == 1) + TdlsexUninit(prAdapter); +#endif /* CFG_SUPPORT_TDLS */ + +} + +#if (MT6620_E1_ASIC_HIFSYS_WORKAROUND == 1) +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to enable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicEnableClockGating(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsClockGatingEnabled == TRUE) + return WLAN_STATUS_SUCCESS; + + nicSetSwIntr(prAdapter, REQ_GATING_ENABLE_H2D_INT); + + i = 0; + while (i < GATING_CONTROL_POLL_LIMIT) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if (u4WHISR & ACK_GATING_ENABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = TRUE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is to inform firmware to disable MCU clock gating +* +* @param prAdapter Pointer of ADAPTER_T +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicDisableClockGating(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4WHISR = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsClockGatingEnabled == FALSE) + return WLAN_STATUS_SUCCESS; + + nicSetSwIntr(prAdapter, REQ_GATING_DISABLE_H2D_INT); + + i = 0; + while (i < GATING_CONTROL_POLL_LIMIT) { + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) + return WLAN_STATUS_FAILURE; + + HAL_READ_INTR_STATUS(prAdapter, sizeof(UINT_32), (PUINT_8)&u4WHISR); + + if (u4WHISR & ACK_GATING_DISABLE_D2H_INT) { + prAdapter->fgIsClockGatingEnabled = FALSE; + return WLAN_STATUS_SUCCESS; + } + } + + ASSERT(0); + return WLAN_STATUS_PENDING; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param rMacAddr BSSID +* @param prSsid Pointer to SSID +* @param u4Privacy Privacy settings (0: Open / 1: WEP/WPA/WPA2 enabled) +* @param rRssi Received Strength (-10 ~ -200 dBm) +* @param eNetworkType Network Type (a/b/g) +* @param prConfiguration Network Parameter +* @param eOpMode Infra/Ad-Hoc +* @param rSupportedRates Supported basic rates +* @param u2IELength IE Length +* @param pucIEBuf Pointer to Information Elements(IEs) +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicAddScanResult(IN P_ADAPTER_T prAdapter, + IN PARAM_MAC_ADDRESS rMacAddr, + IN P_PARAM_SSID_T prSsid, + IN UINT_32 u4Privacy, + IN PARAM_RSSI rRssi, + IN ENUM_PARAM_NETWORK_TYPE_T eNetworkType, + IN P_PARAM_802_11_CONFIG_T prConfiguration, + IN ENUM_PARAM_OP_MODE_T eOpMode, + IN PARAM_RATES_EX rSupportedRates, IN UINT_16 u2IELength, IN PUINT_8 pucIEBuf) +{ + BOOLEAN bReplace; + UINT_32 i; + UINT_32 u4IdxWeakest = 0; + PARAM_RSSI rWeakestRssi; + UINT_32 u4BufferSize; + + ASSERT(prAdapter); + + rWeakestRssi = (PARAM_RSSI) INT_MAX; + u4BufferSize = sizeof(prAdapter->rWlanInfo.aucScanIEBuf) / sizeof(prAdapter->rWlanInfo.aucScanIEBuf[0]); + + bReplace = FALSE; + + /* decide to replace or add */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + /* find weakest entry && not connected one */ + if (UNEQUAL_MAC_ADDR + (prAdapter->rWlanInfo.arScanResult[i].arMacAddress, prAdapter->rWlanInfo.rCurrBssId.arMacAddress) + && prAdapter->rWlanInfo.arScanResult[i].rRssi < rWeakestRssi) { + u4IdxWeakest = i; + rWeakestRssi = prAdapter->rWlanInfo.arScanResult[i].rRssi; + } + + if (prAdapter->rWlanInfo.arScanResult[i].eOpMode == eOpMode && + EQUAL_MAC_ADDR(&(prAdapter->rWlanInfo.arScanResult[i].arMacAddress), rMacAddr) && + (EQUAL_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen) + || prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen == 0)) { + /* replace entry */ + bReplace = TRUE; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + /* IE - allocate buffer and update pointer */ + if (u2IELength > 0) { + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + break; + } + } + + if (bReplace == FALSE) { + if (prAdapter->rWlanInfo.u4ScanResultNum < (CFG_MAX_NUM_BSS_LIST - 1)) { + i = prAdapter->rWlanInfo.u4ScanResultNum; + + /* zero */ + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + /* IE - allocate buffer and update pointer */ + if (u2IELength > 0) { + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + + prAdapter->rWlanInfo.u4ScanResultNum++; + } else if (rWeakestRssi != (PARAM_RSSI) INT_MAX) { + /* replace weakest one */ + i = u4IdxWeakest; + + /* free IE buffer then zero */ + nicFreeScanResultIE(prAdapter, i); + kalMemZero(&(prAdapter->rWlanInfo.arScanResult[i]), OFFSET_OF(PARAM_BSSID_EX_T, aucIEs)); + + /* then fill buffer */ + prAdapter->rWlanInfo.arScanResult[i].u4Length = + OFFSET_OF(PARAM_BSSID_EX_T, aucIEs) + u2IELength; + COPY_MAC_ADDR(prAdapter->rWlanInfo.arScanResult[i].arMacAddress, rMacAddr); + COPY_SSID(prAdapter->rWlanInfo.arScanResult[i].rSsid.aucSsid, + prAdapter->rWlanInfo.arScanResult[i].rSsid.u4SsidLen, + prSsid->aucSsid, prSsid->u4SsidLen); + prAdapter->rWlanInfo.arScanResult[i].u4Privacy = u4Privacy; + prAdapter->rWlanInfo.arScanResult[i].rRssi = rRssi; + prAdapter->rWlanInfo.arScanResult[i].eNetworkTypeInUse = eNetworkType; + kalMemCopy(&(prAdapter->rWlanInfo.arScanResult[i].rConfiguration), + prConfiguration, sizeof(PARAM_802_11_CONFIG_T)); + prAdapter->rWlanInfo.arScanResult[i].eOpMode = eOpMode; + kalMemCopy((prAdapter->rWlanInfo.arScanResult[i].rSupportedRates), + rSupportedRates, sizeof(PARAM_RATES_EX)); + prAdapter->rWlanInfo.arScanResult[i].u4IELength = (UINT_32) u2IELength; + + if (u2IELength > 0) { + /* IE - allocate buffer and update pointer */ + if (ALIGN_4(u2IELength) + prAdapter->rWlanInfo.u4ScanIEBufferUsage <= u4BufferSize) { + kalMemCopy(& + (prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]), + pucIEBuf, u2IELength); + + prAdapter->rWlanInfo.apucScanResultIEs[i] = + &(prAdapter-> + rWlanInfo.aucScanIEBuf[prAdapter->rWlanInfo.u4ScanIEBufferUsage]); + + prAdapter->rWlanInfo.u4ScanIEBufferUsage += ALIGN_4(u2IELength); + } else { + /* buffer is not enough */ + prAdapter->rWlanInfo.arScanResult[i].u4Length -= u2IELength; + prAdapter->rWlanInfo.arScanResult[i].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } else { + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is invoked to free IE buffer for dedicated scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4Idx Index of Scan Result +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicFreeScanResultIE(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Idx) +{ + UINT_32 i; + PUINT_8 pucPivot, pucMovePivot; + UINT_32 u4MoveSize, u4FreeSize, u4ReserveSize; + + ASSERT(prAdapter); + ASSERT(u4Idx < CFG_MAX_NUM_BSS_LIST); + + if (prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength == 0 + || prAdapter->rWlanInfo.apucScanResultIEs[u4Idx] == NULL) { + return; + } + + u4FreeSize = ALIGN_4(prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength); + + pucPivot = prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]; + pucMovePivot = (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[u4Idx]) + u4FreeSize); + + u4ReserveSize = ((ULONG) pucPivot) - (ULONG) (&(prAdapter->rWlanInfo.aucScanIEBuf[0])); + u4MoveSize = prAdapter->rWlanInfo.u4ScanIEBufferUsage - u4ReserveSize - u4FreeSize; + + /* 1. rest of buffer to move forward */ + kalMemCopy(pucPivot, pucMovePivot, u4MoveSize); + + /* 1.1 modify pointers */ + for (i = 0; i < prAdapter->rWlanInfo.u4ScanResultNum; i++) { + if (i != u4Idx) { + if (prAdapter->rWlanInfo.apucScanResultIEs[i] >= pucMovePivot) { + prAdapter->rWlanInfo.apucScanResultIEs[i] = + (PUINT_8) ((ULONG) (prAdapter->rWlanInfo.apucScanResultIEs[i]) - u4FreeSize); + } + } + } + + /* 1.2 reset the freed one */ + prAdapter->rWlanInfo.arScanResult[u4Idx].u4IELength = 0; + prAdapter->rWlanInfo.apucScanResultIEs[i] = NULL; + + /* 2. reduce IE buffer usage */ + prAdapter->rWlanInfo.u4ScanIEBufferUsage -= u4FreeSize; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is to hack parameters for WLAN TABLE for +* fixed rate settings +* +* @param prAdapter Pointer to the Adapter structure. +* @param eRateSetting +* @param pu2DesiredNonHTRateSet, +* @param pu2BSSBasicRateSet, +* @param pucMcsSet +* @param pucSupMcs32 +* @param pu2HtCapInfo +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicUpdateRateParams(IN P_ADAPTER_T prAdapter, + IN ENUM_REGISTRY_FIXED_RATE_T eRateSetting, + IN PUINT_8 pucDesiredPhyTypeSet, + IN PUINT_16 pu2DesiredNonHTRateSet, + IN PUINT_16 pu2BSSBasicRateSet, + IN PUINT_8 pucMcsSet, IN PUINT_8 pucSupMcs32, IN PUINT_16 pu2HtCapInfo) +{ + ASSERT(prAdapter); + ASSERT(eRateSetting > FIXED_RATE_NONE && eRateSetting < FIXED_RATE_NUM); + + switch (prAdapter->rWifiVar.eRateSetting) { + case FIXED_RATE_1M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_1M; + *pu2BSSBasicRateSet = RATE_SET_BIT_1M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_2M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_2M; + *pu2BSSBasicRateSet = RATE_SET_BIT_2M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_5_5M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_5_5M; + *pu2BSSBasicRateSet = RATE_SET_BIT_5_5M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_11M: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HR_DSSS; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_11M; + *pu2BSSBasicRateSet = RATE_SET_BIT_11M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_6M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_6M; + *pu2BSSBasicRateSet = RATE_SET_BIT_6M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_9M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_9M; + *pu2BSSBasicRateSet = RATE_SET_BIT_9M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_12M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_12M; + *pu2BSSBasicRateSet = RATE_SET_BIT_12M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_18M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_18M; + *pu2BSSBasicRateSet = RATE_SET_BIT_18M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_24M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_24M; + *pu2BSSBasicRateSet = RATE_SET_BIT_24M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_36M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_36M; + *pu2BSSBasicRateSet = RATE_SET_BIT_36M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_48M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_48M; + *pu2BSSBasicRateSet = RATE_SET_BIT_48M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_54M: + if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_ERP) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_ERP; + else if ((*pucDesiredPhyTypeSet) & PHY_TYPE_BIT_OFDM) + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_OFDM; + + *pu2DesiredNonHTRateSet = RATE_SET_BIT_54M; + *pu2BSSBasicRateSet = RATE_SET_BIT_54M; + *pucMcsSet = 0; + *pucSupMcs32 = 0; + *pu2HtCapInfo = 0; + break; + + case FIXED_RATE_MCS0_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS1_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS2_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS3_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS4_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS5_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS6_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS7_20M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH + | HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + break; + + case FIXED_RATE_MCS0_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS1_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS2_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS3_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS4_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS5_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS6_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS7_20M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SHORT_GI_20M; + break; + + case FIXED_RATE_MCS0_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS1_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS2_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS3_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS4_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS5_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS6_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS7_40M_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS32_800NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_SHORT_GI_40M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= HT_CAP_INFO_SUP_CHNL_WIDTH; + break; + + case FIXED_RATE_MCS0_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS0_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS1_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS1_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS2_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS2_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS3_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS3_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS4_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS4_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS5_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS5_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS6_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS6_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS7_40M_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS7_INDEX; + *pucSupMcs32 = 0; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + case FIXED_RATE_MCS32_400NS: + *pucDesiredPhyTypeSet = PHY_TYPE_BIT_HT; + *pu2DesiredNonHTRateSet = RATE_SET_BIT_HT_PHY; + *pu2BSSBasicRateSet = RATE_SET_BIT_HT_PHY; + *pucMcsSet = HT_RATE_MCS32_INDEX; + *pucSupMcs32 = 1; + (*pu2HtCapInfo) &= ~(HT_CAP_INFO_SHORT_GI_20M | HT_CAP_INFO_HT_GF); + (*pu2HtCapInfo) |= (HT_CAP_INFO_SUP_CHNL_WIDTH | HT_CAP_INFO_SHORT_GI_40M); + break; + + default: + ASSERT(0); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to write the register +* +* @param u4Address Register address +* u4Value the value to be written +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicWriteMcr(IN P_ADAPTER_T prAdapter, IN UINT_32 u4Address, IN UINT_32 u4Value) +{ + CMD_ACCESS_REG rCmdAccessReg; + + rCmdAccessReg.u4Address = u4Address; + rCmdAccessReg.u4Data = u4Value; + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_ACCESS_REG, + TRUE, + FALSE, + FALSE, NULL, NULL, sizeof(CMD_ACCESS_REG), (PUINT_8) &rCmdAccessReg, NULL, 0); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to modify the auto rate parameters +* +* @param u4ArSysParam0 see description below +* u4ArSysParam1 +* u4ArSysParam2 +* u4ArSysParam3 +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* ArSysParam0[0:3] -> auto rate version (0:disable 1:version1 2:version2) +* ArSysParam0[4:5]-> auto bw version (0:disable 1:version1 2:version2) +* ArSysParam0[6:7]-> auto gi version (0:disable 1:version1 2:version2) +* ArSysParam0[8:15]-> HT rate clear mask +* ArSysParam0[16:31]-> Legacy rate clear mask +* ArSysParam1[0:7]-> Auto Rate check weighting window +* ArSysParam1[8:15]-> Auto Rate v1 Force Rate down +* ArSysParam1[16:23]-> Auto Rate v1 PerH +* ArSysParam1[24:31]-> Auto Rate v1 PerL +* +* Examples +* ArSysParam0 = 1, +* Enable auto rate version 1 +* +* ArSysParam0 = 983041, +* Enable auto rate version 1 +* Remove CCK 1M, 2M, 5.5M, 11M +* +* ArSysParam0 = 786433 +* Enable auto rate version 1 +* Remove CCK 5.5M 11M +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRlmArUpdateParms(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4ArSysParam0, + IN UINT_32 u4ArSysParam1, IN UINT_32 u4ArSysParam2, IN UINT_32 u4ArSysParam3) +{ + UINT_8 ucArVer, ucAbwVer, ucAgiVer; + UINT_16 u2HtClrMask; + UINT_16 u2LegacyClrMask; + UINT_8 ucArCheckWindow; + UINT_8 ucArPerL; + UINT_8 ucArPerH; + UINT_8 ucArPerForceRateDownPer; + + ucArVer = (UINT_8) (u4ArSysParam0 & BITS(0, 3)); + ucAbwVer = (UINT_8) ((u4ArSysParam0 & BITS(4, 5)) >> 4); + ucAgiVer = (UINT_8) ((u4ArSysParam0 & BITS(6, 7)) >> 6); + u2HtClrMask = (UINT_16) ((u4ArSysParam0 & BITS(8, 15)) >> 8); + u2LegacyClrMask = (UINT_16) ((u4ArSysParam0 & BITS(16, 31)) >> 16); + +#if 0 + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (UINT_8) ((u4ArSysParam1 & BITS(8, 15) >> 8)); + ucArPerH = (UINT_8) ((u4ArSysParam1 & BITS(16, 23)) >> 16); + ucArPerL = (UINT_8) ((u4ArSysParam1 & BITS(24, 31)) >> 24); +#endif + + ucArCheckWindow = (UINT_8) (u4ArSysParam1 & BITS(0, 7)); + ucArPerForceRateDownPer = (UINT_8) (((u4ArSysParam1 >> 8) & BITS(0, 7))); + ucArPerH = (UINT_8) (((u4ArSysParam1 >> 16) & BITS(0, 7))); + ucArPerL = (UINT_8) (((u4ArSysParam1 >> 24) & BITS(0, 7))); + + DBGLOG(NIC, INFO, "ArParam %u %u %u %u\n", u4ArSysParam0, u4ArSysParam1, u4ArSysParam2, u4ArSysParam3); + DBGLOG(NIC, INFO, "ArVer %u AbwVer %u AgiVer %u\n", ucArVer, ucAbwVer, ucAgiVer); + DBGLOG(NIC, INFO, "HtMask %x LegacyMask %x\n", u2HtClrMask, u2LegacyClrMask); + DBGLOG(NIC, INFO, + "CheckWin %u RateDownPer %u PerH %u PerL %u\n", ucArCheckWindow, ucArPerForceRateDownPer, ucArPerH, + ucArPerL); + +#define SWCR_DATA_ADDR(MOD, ADDR) (0x90000000+(MOD<<8)+(ADDR)) +#define SWCR_DATA_CMD(CATE, WRITE, INDEX, OPT0, OPT1) ((CATE<<24) | (WRITE<<23) | (INDEX<<16) | (OPT0 << 8) | OPT1) +#define SWCR_DATA0 0x0 +#define SWCR_DATA1 0x4 +#define SWCR_DATA2 0x8 +#define SWCR_DATA3 0xC +#define SWCR_DATA4 0x10 +#define SWCR_WRITE 1 +#define SWCR_READ 0 + + if (ucArVer > 0) { + /* dummy = WiFi.WriteMCR(&h90000104, &h00000001) */ + /* dummy = WiFi.WriteMCR(&h90000100, &h00850000) */ + + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 1); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); + } else { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), 0); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 5, 0, 0)); + } + + /* ucArVer 0: none 1:PER 2:Rcpi */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArVer); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 7, 0, 0)); + + /* Candidate rate Ht mask */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2HtClrMask); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1c, 0, 0)); + + /* Candidate rate legacy mask */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), u2LegacyClrMask); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1d, 0, 0)); + +#if 0 + if (ucArCheckWindow != 0) { + /* TX DONE MCS INDEX CHECK STA RATE DOWN TH */ + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x14, 0, 0)); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArCheckWindow); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0xc, 0, 0)); + } + + if (ucArPerForceRateDownPer != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerForceRateDownPer); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x18, 0, 0)); + } + if (ucArPerH != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerH); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x1, 0, 0)); + } + if (ucArPerL != 0) { + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA1), ucArPerL); + nicWriteMcr(prAdapter, SWCR_DATA_ADDR(1 /*MOD*/, SWCR_DATA0), SWCR_DATA_CMD(0, SWCR_WRITE, 0x2, 0, 0)); + } +#endif + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This utility function is used to enable roaming +* +* @param u4EnableRoaming +* +* +* @retval WLAN_STATUS_SUCCESS +* WLAN_STATUS_FAILURE +* +* @note +* u4EnableRoaming -> Enable Romaing +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRoamingUpdateParams(IN P_ADAPTER_T prAdapter, IN UINT_32 u4EnableRoaming) +{ + P_CONNECTION_SETTINGS_T prConnSettings; + + prConnSettings = &(prAdapter->rWifiVar.rConnSettings); + prConnSettings->fgIsEnableRoaming = ((u4EnableRoaming > 0) ? (TRUE) : (FALSE)); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief dump firmware Assert message +* +* \param[in] +* prAdapter +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID nicPrintFirmwareAssertInfo(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4MailBox0, u4MailBox1; + UINT_32 line = 0; + UINT_8 aucAssertFile[7]; + UINT_32 u4ChipId; + +#if CFG_SDIO_INTR_ENHANCE + u4MailBox0 = prAdapter->prSDIOCtrl->u4RcvMailbox0; + u4MailBox1 = prAdapter->prSDIOCtrl->u4RcvMailbox1; +#else + nicGetMailbox(prAdapter, 0, &u4MailBox0); + nicGetMailbox(prAdapter, 1, &u4MailBox1); +#endif + + line = u4MailBox0 & 0x0000FFFF; + + u4MailBox0 = ((u4MailBox0 >> 16) & 0x0000FFFF); + + kalMemCopy(&aucAssertFile[0], &u4MailBox0, 2); + kalMemCopy(&aucAssertFile[2], &u4MailBox1, 4); + + aucAssertFile[6] = '\0'; + +#if defined(MT6620) + u4ChipId = 6620; +#elif defined(MT6628) + u4ChipId = 6582; +#endif + + kalPrint("\n[MT%u][wifi][Firmware] Assert at \"%s\" #%u\n\n", u4ChipId, aucAssertFile, line); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateLinkQuality(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN P_EVENT_LINK_QUALITY prEventLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + ASSERT(prEventLinkQuality); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* check is to prevent RSSI to be updated by incorrect initial RSSI from hardware */ + /* buffer statistics for further query */ + if (prAdapter->fgIsLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateRSSI(prAdapter, eNetTypeIdx, prEventLinkQuality->cRssi, + prEventLinkQuality->cLinkQuality); + } + + if (prAdapter->fgIsLinkRateValid == FALSE + || (kalGetTimeTick() - prAdapter->rLinkRateUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + nicUpdateLinkSpeed(prAdapter, eNetTypeIdx, prEventLinkQuality->u2LinkSpeed); + } + } + break; +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + if (prAdapter->fgIsP2pLinkQualityValid == FALSE + || (kalGetTimeTick() - prAdapter->rP2pLinkQualityUpdateTime) > CFG_LINK_QUALITY_VALID_PERIOD) { + P_EVENT_LINK_QUALITY_EX prEventLQEx = (P_EVENT_LINK_QUALITY_EX) prEventLinkQuality; + + nicUpdateRSSI(prAdapter, NETWORK_TYPE_P2P_INDEX, prEventLQEx->cRssiP2P, + prEventLQEx->cLinkQualityP2P); + } + break; +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update RSSI and Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicUpdateRSSI(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + prAdapter->fgIsLinkQualityValid = TRUE; + prAdapter->rLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.cRssi = cRssi; + prAdapter->rLinkQuality.cLinkQuality = cLinkQuality; + + /* indicate to glue layer */ + kalUpdateRSSI(prAdapter->prGlueInfo, + KAL_NETWORK_TYPE_AIS_INDEX, + prAdapter->rLinkQuality.cRssi, prAdapter->rLinkQuality.cLinkQuality); + } + + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case NETWORK_TYPE_P2P_INDEX: + prAdapter->fgIsP2pLinkQualityValid = TRUE; + prAdapter->rP2pLinkQualityUpdateTime = kalGetTimeTick(); + + prAdapter->rP2pLinkQuality.cRssi = cRssi; + prAdapter->rP2pLinkQuality.cLinkQuality = cLinkQuality; + + kalUpdateRSSI(prAdapter->prGlueInfo, KAL_NETWORK_TYPE_P2P_INDEX, cRssi, cLinkQuality); + break; +#endif +#endif + default: + break; + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called to update Link Quality information +* +* @param prAdapter Pointer of Adapter Data Structure +* eNetTypeIdx +* prEventLinkQuality +* cRssi +* cLinkQuality +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicUpdateLinkSpeed(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN UINT_16 u2LinkSpeed) +{ + ASSERT(prAdapter); + ASSERT(eNetTypeIdx < NETWORK_TYPE_INDEX_NUM); + + switch (eNetTypeIdx) { + case NETWORK_TYPE_AIS_INDEX: + if (prAdapter->rWifiVar.arBssInfo[eNetTypeIdx].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + /* buffer statistics for further query */ + prAdapter->fgIsLinkRateValid = TRUE; + prAdapter->rLinkRateUpdateTime = kalGetTimeTick(); + + prAdapter->rLinkQuality.u2LinkSpeed = u2LinkSpeed; + } + break; + + default: + break; + + } + +} + +#if CFG_SUPPORT_RDD_TEST_MODE +WLAN_STATUS nicUpdateRddTestMode(IN P_ADAPTER_T prAdapter, IN P_CMD_RDD_CH_T prRddChParam) +{ + DEBUGFUNC("nicUpdateRddTestMode.\n"); + + ASSERT(prAdapter); + +/* aisFsmScanRequest(prAdapter, NULL); */ + + return wlanSendSetQueryCmd(prAdapter, + CMD_ID_SET_RDD_CH, + TRUE, + FALSE, FALSE, NULL, NULL, sizeof(CMD_RDD_CH_T), (PUINT_8) prRddChParam, NULL, 0); +} +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c new file mode 100644 index 0000000000000..3c9c24f9542bc --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_cmd_event.c @@ -0,0 +1,1636 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_cmd_event.c#1 +*/ + +/*! \file nic_cmd_event.c + \brief Callback functions for Command packets. + + Various Event packet handlers which will be setup in the callback function of + a command packet. +*/ + +/* +** Log: nic_cmd_event.c + * + * 04 10 2012 yuche.tsai + * NULL + * Update address for wifi direct connection issue. + * + * 06 15 2011 cm.chang + * [WCXRP00000785] [MT6620 Wi-Fi][Driver][FW] P2P/BOW MAC address is XOR with AIS MAC address + * P2P/BOW mac address XOR with local bit instead of OR + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 02 24 2011 cp.wu + * [WCXRP00000493] [MT6620 Wi-Fi][Driver] Do not indicate redundant disconnection to host when entering into RF + * test mode + * only indicate DISCONNECTION to host when entering RF test if necessary (connected -> disconnected cases) + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to + * system scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being + * loaded + * + * 12 01 2010 cp.wu + * [WCXRP00000223] MT6620 Wi-Fi][Driver][FW] Adopt NVRAM parameters when enter/exit RF test mode + * reload NVRAM settings before entering RF test mode and leaving from RF test mode. + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 20 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * use OID_CUSTOM_TEST_MODE as indication for driver reset + * by dropping pending TX packets + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + * associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 15 2010 yuche.tsai + * NULL + * Start to test AT GO only when P2P state is not IDLE. + * + * 09 09 2010 yuche.tsai + * NULL + * Add AT GO Test mode after MAC address available. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 16 2010 cp.wu + * NULL + * Replace CFG_SUPPORT_BOW by CFG_ENABLE_BT_OVER_WIFI. + * There is no CFG_SUPPORT_BOW in driver domain source. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 11 2010 yuche.tsai + * NULL + * Add support for P2P Device Address query from FW. + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 08 02 2010 cp.wu + * NULL + * reset FSMs before entering RF test mode. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 05 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) change fake BSS_DESC from channel 6 to channel 1 due to channel switching is not done yet. + * 2) after MAC address is queried from firmware, all related variables in driver domain should be updated as well + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change upon request: indicate as disconnected in driver domain when leaving from RF test mode + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * do not clear scanning list array after disassociation + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) disable NETWORK_LAYER_ADDRESSES handling temporally. + * 2) finish statistics OIDs + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * change OID behavior to meet WHQL requirement. + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 05 17 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct OID_802_11_DISASSOCIATE handling. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * are done in adapter layer. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glude code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sync statistics data structure definition with firmware implementation + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * statistics information OIDs are now handled by querying from firmware domain + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * indicate media stream mode after set is done + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement custom OID: EEPROM read/write access + * + * 03 03 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_3_MULTICAST_LIST oid handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * limit RSSI return value to micxxsoft defined range. + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * block until firmware finished RF test enter/leave then indicate completion to upper layer + * + * 01 29 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when entering RF test mode and leaving from RF test mode, wait for W_FUNC_RDY bit to be asserted forever until it + * is set or card is removed. + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * * 4. correct some HAL implementation + * + * 01 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Under WinXP with SDIO, use prGlueInfo->rHifInfo.pvInformationBuffer instead of prGlueInfo->pvInformationBuffer + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * * OID_802_11_RSSI, + * * * * * OID_802_11_RSSI_TRIGGER, + * * * * * OID_802_11_STATISTICS, + * * * * * OID_802_11_DISASSOCIATE, + * * * * * OID_802_11_POWER_MODE + * + * 01 21 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement OID_802_11_MEDIA_STREAM_MODE + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-10 16:47:47 GMT mtk02752 +** only handle MCR read when accessing FW domain register +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-08 17:37:28 GMT mtk02752 +** * refine nicCmdEventQueryMcrRead +** + add TxStatus/RxStatus for RF test QueryInformation OIDs +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 22:05:45 GMT mtk02752 +** kalOidComplete() will decrease i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-12-01 23:02:57 GMT mtk02752 +** remove unnecessary spin locks +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-12-01 22:51:18 GMT mtk02752 +** maintein i4OidPendingCount +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-11-30 10:55:03 GMT mtk02752 +** modify for compatibility +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-23 14:46:32 GMT mtk02752 +** add another version of command-done handler upon new event structure +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-04-29 15:42:33 GMT mtk01461 +** Add comment +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-04-21 19:32:42 GMT mtk01461 +** Add nicCmdEventSetCommon() for general set OID +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-04-21 01:40:35 GMT mtk01461 +** Command Done Handler +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +VOID nicCmdEventQueryMcrRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MCR_RW_STRUCT_T prMcrRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_ACCESS_REG prCmdAccessReg; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdAccessReg = (P_CMD_ACCESS_REG) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T); + + prMcrRdInfo = (P_PARAM_CUSTOM_MCR_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMcrRdInfo->u4McrOffset = prCmdAccessReg->u4Address; + prMcrRdInfo->u4McrData = prCmdAccessReg->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventQuerySwCtrlRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_SW_CTRL_STRUCT_T prSwCtrlInfo; + P_GLUE_INFO_T prGlueInfo; + P_CMD_SW_DBG_CTRL_T prCmdSwCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prCmdSwCtrl = (P_CMD_SW_DBG_CTRL_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T); + + prSwCtrlInfo = (P_PARAM_CUSTOM_SW_CTRL_STRUCT_T) prCmdInfo->pvInformationBuffer; + prSwCtrlInfo->u4Id = prCmdSwCtrl->u4Id; + prSwCtrlInfo->u4Data = prCmdSwCtrl->u4Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4InformationBufferLength, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventSetDisassociate(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + } + + DBGLOG(NIC, TRACE, "DisByCmdE\n"); + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + +#if !defined(LINUX) + prAdapter->fgIsRadioOff = TRUE; +#endif + +} + +VOID nicCmdEventSetIpAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4Count; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + u4Count = (prCmdInfo->u4SetInfoLen - OFFSET_OF(CMD_SET_NETWORK_ADDRESS_LIST, arNetAddress)) + / sizeof(IPV4_NETWORK_ADDRESS); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress) + u4Count * + (OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP)), + WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryRfTestATInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_TEST_STATUS prTestStatus, prQueryBuffer; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTestStatus = (P_EVENT_TEST_STATUS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prQueryBuffer = (P_EVENT_TEST_STATUS) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prQueryBuffer, prTestStatus, sizeof(EVENT_TEST_STATUS)); + + u4QueryInfoLen = sizeof(EVENT_TEST_STATUS); + + /* Update Query Information Length */ + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryLinkQuality(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_RSSI rRssi, *prRssi; + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + rRssi = (PARAM_RSSI) prLinkQuality->cRssi; /* ranged from (-128 ~ 30) in unit of dBm */ + DBGLOG(NIC, INFO, " %s: rRssi = %d\n", __func__, rRssi); + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) { + if (rRssi > PARAM_WHQL_RSSI_MAX_DBM) + rRssi = PARAM_WHQL_RSSI_MAX_DBM; + else if (rRssi < PARAM_WHQL_RSSI_MIN_DBM) + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } else { + rRssi = PARAM_WHQL_RSSI_MIN_DBM; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prRssi = (PARAM_RSSI *) prCmdInfo->pvInformationBuffer; + + kalMemCopy(prRssi, &rRssi, sizeof(PARAM_RSSI)); + u4QueryInfoLen = sizeof(PARAM_RSSI); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is in response of OID_GEN_LINK_SPEED query request +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the pending command info +* @param pucEventBuf +* +* @retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryLinkSpeed(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_LINK_QUALITY prLinkQuality; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4LinkSpeed; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prLinkQuality = (P_EVENT_LINK_QUALITY) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + pu4LinkSpeed = (PUINT_32) (prCmdInfo->pvInformationBuffer); + + *pu4LinkSpeed = prLinkQuality->u2LinkSpeed * 5000; + + u4QueryInfoLen = sizeof(UINT_32); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_PARAM_802_11_STATISTICS_STRUCT_T prStatistics; + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + u4QueryInfoLen = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics = (P_PARAM_802_11_STATISTICS_STRUCT_T) prCmdInfo->pvInformationBuffer; + + prStatistics->u4Length = sizeof(PARAM_802_11_STATISTICS_STRUCT_T); + prStatistics->rTransmittedFragmentCount = prEventStatistics->rTransmittedFragmentCount; + prStatistics->rMulticastTransmittedFrameCount = prEventStatistics->rMulticastTransmittedFrameCount; + prStatistics->rFailedCount = prEventStatistics->rFailedCount; + prStatistics->rRetryCount = prEventStatistics->rRetryCount; + prStatistics->rMultipleRetryCount = prEventStatistics->rMultipleRetryCount; + prStatistics->rRTSSuccessCount = prEventStatistics->rRTSSuccessCount; + prStatistics->rRTSFailureCount = prEventStatistics->rRTSFailureCount; + prStatistics->rACKFailureCount = prEventStatistics->rACKFailureCount; + prStatistics->rFrameDuplicateCount = prEventStatistics->rFrameDuplicateCount; + prStatistics->rReceivedFragmentCount = prEventStatistics->rReceivedFragmentCount; + prStatistics->rMulticastReceivedFrameCount = prEventStatistics->rMulticastReceivedFrameCount; + prStatistics->rFCSErrorCount = prEventStatistics->rFCSErrorCount; + prStatistics->rTKIPLocalMICFailures.QuadPart = 0; + prStatistics->rTKIPICVErrors.QuadPart = 0; + prStatistics->rTKIPCounterMeasuresInvoked.QuadPart = 0; + prStatistics->rTKIPReplays.QuadPart = 0; + prStatistics->rCCMPFormatErrors.QuadPart = 0; + prStatistics->rCCMPReplays.QuadPart = 0; + prStatistics->rCCMPDecryptErrors.QuadPart = 0; + prStatistics->rFourWayHandshakeFailures.QuadPart = 0; + prStatistics->rWEPUndecryptableCount.QuadPart = 0; + prStatistics->rWEPICVErrorCount.QuadPart = 0; + prStatistics->rDecryptSuccessCount.QuadPart = 0; + prStatistics->rDecryptFailureCount.QuadPart = 0; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventEnterRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* [driver-land] */ + prAdapter->fgTestMode = TRUE; + + /* 0. always indicate disconnection */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + /* 1. Remove pending TX */ + nicTxRelease(prAdapter); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. Reset driver-domain FSMs */ + nicUninitMGMT(prAdapter); + + nicResetSystemService(prAdapter); + nicInitMGMT(prAdapter, NULL); + + /* 3. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 4. Block til firmware completed entering into RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + u2RetryCnt++; + } + + /* 5. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + /* 6. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 7. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 8. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + +} + +VOID nicCmdEventLeaveRfTest(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ +#define WAIT_FW_READY_RETRY_CNT 200 + + UINT_32 u4WHISR = 0, u4Value = 0; + UINT_8 aucTxCount[8]; + UINT_16 u2RetryCnt = 0; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + /* 1. Disable Interrupt */ + HAL_INTR_DISABLE(prAdapter); + + /* 2. Block til firmware completed leaving from RF test mode */ + kalMsleep(500); + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE || + kalIsResetting() || u2RetryCnt >= WAIT_FW_READY_RETRY_CNT) { + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, + prCmdInfo->u4SetInfoLen, WLAN_STATUS_NOT_SUPPORTED); + + } + return; + } + kalMsleep(10); + u2RetryCnt++; + } + + /* 3. Clear Interrupt Status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)&u4WHISR); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + /* 4. Reset TX Counter */ + nicTxResetResource(prAdapter); + + /* 5. Re-enable Interrupt */ + HAL_INTR_ENABLE(prAdapter); + + /* 6. set driver-land variable */ + prAdapter->fgTestMode = FALSE; + + /* 7. completion indication */ + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + /* 8. Indicate as disconnected */ + if (kalGetMediaStateIndicated(prAdapter->prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } +#if CFG_SUPPORT_NVRAM + /* 9. load manufacture data */ + wlanLoadManufactureData(prAdapter, kalGetConfiguration(prAdapter->prGlueInfo)); +#endif + + /* 10. Override network address */ + wlanUpdateNetworkAddress(prAdapter); + +} + +VOID nicCmdEventQueryAddress(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_BASIC_CONFIG prEventBasicConfig; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + prEventBasicConfig = (P_EVENT_BASIC_CONFIG) (pucEventBuf); + + /* copy to adapter */ + kalMemCopy(&(prAdapter->rMyMacAddr), &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + kalMemCopy(prCmdInfo->pvInformationBuffer, &(prEventBasicConfig->rMyMacAddr), MAC_ADDR_LEN); + u4QueryInfoLen = MAC_ADDR_LEN; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + /* 4 <3> Update new MAC address and all 3 networks */ + COPY_MAC_ADDR(prAdapter->rWifiVar.aucMacAddress, prAdapter->rMyMacAddr); + COPY_MAC_ADDR(prAdapter->rWifiVar.aucDeviceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucDeviceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.aucInterfaceAddress, prAdapter->rMyMacAddr); + prAdapter->rWifiVar.aucInterfaceAddress[0] ^= MAC_ADDR_LOCAL_ADMIN; + + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].aucOwnMacAddr, prAdapter->rMyMacAddr); + +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + COPY_MAC_ADDR(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_BOW_INDEX].aucOwnMacAddr, + prAdapter->rWifiVar.aucDeviceAddress); +#endif + +#if CFG_TEST_WIFI_DIRECT_GO + if (prAdapter->rWifiVar.prP2pFsmInfo->eCurrentState == P2P_STATE_IDLE) { + wlanEnableP2pFunction(prAdapter); + + wlanEnableATGO(prAdapter); + } +#endif + + kalUpdateMACAddress(prAdapter->prGlueInfo, prAdapter->rWifiVar.aucMacAddress); + +} + +VOID nicCmdEventQueryMcastAddr(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_MAC_MCAST_ADDR prEventMacMcastAddr; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventMacMcastAddr = (P_EVENT_MAC_MCAST_ADDR) (pucEventBuf); + + u4QueryInfoLen = prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN; + + /* buffer length check */ + if (prCmdInfo->u4InformationBufferLength < u4QueryInfoLen) { + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_BUFFER_TOO_SHORT); + } else { + kalMemCopy(prCmdInfo->pvInformationBuffer, + prEventMacMcastAddr->arAddress, + prEventMacMcastAddr->u4NumOfGroupAddr * MAC_ADDR_LEN); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + } +} + +VOID nicCmdEventQueryEepromRead(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T prEepromRdInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_ACCESS_EEPROM prEventAccessEeprom; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventAccessEeprom = (P_EVENT_ACCESS_EEPROM) (pucEventBuf); + + u4QueryInfoLen = sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T); + + prEepromRdInfo = (P_PARAM_CUSTOM_EEPROM_RW_STRUCT_T) prCmdInfo->pvInformationBuffer; + prEepromRdInfo->ucEepromIndex = (UINT_8) (prEventAccessEeprom->u2Offset); + prEepromRdInfo->u2EepromData = prEventAccessEeprom->u2Data; + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + + return; + +} + +VOID nicCmdEventSetMediaStreamMode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + PARAM_MEDIA_STREAMING_INDICATION rParamMediaStreamIndication; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + if (prCmdInfo->fgIsOid) { + /* Update Set Information Length */ + kalOidComplete(prAdapter->prGlueInfo, + prCmdInfo->fgSetQuery, prCmdInfo->u4SetInfoLen, WLAN_STATUS_SUCCESS); + } + + rParamMediaStreamIndication.rStatus.eStatusType = ENUM_STATUS_TYPE_MEDIA_STREAM_MODE; + rParamMediaStreamIndication.eMediaStreamMode = + prAdapter->rWlanInfo.eLinkAttr.ucMediaStreamMode == 0 ? ENUM_MEDIA_STREAM_OFF : ENUM_MEDIA_STREAM_ON; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&rParamMediaStreamIndication, sizeof(PARAM_MEDIA_STREAMING_INDICATION)); +} + +/* Statistics responder */ +VOID nicCmdEventQueryXmitOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rTransmittedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rTransmittedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvOk(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rReceivedFragmentCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rReceivedFragmentCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + /* @FIXME, RX_ERROR_DROP_COUNT/RX_FIFO_FULL_DROP_COUNT is not calculated */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvNoBuffer(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = 0; /* @FIXME? */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME? */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvCrcError(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFCSErrorCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = prEventStatistics->rFCSErrorCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryRecvErrorAlignment(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) 0; /* @FIXME */ + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = 0; /* @FIXME */ + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitOneCollision(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = + (UINT_32) (prEventStatistics->rMultipleRetryCount.QuadPart - + prEventStatistics->rRetryCount.QuadPart); + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = + (UINT_64) (prEventStatistics->rMultipleRetryCount.QuadPart - + prEventStatistics->rRetryCount.QuadPart); + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitMoreCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rMultipleRetryCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rMultipleRetryCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +VOID nicCmdEventQueryXmitMaxCollisions(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + P_EVENT_STATISTICS prEventStatistics; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4QueryInfoLen; + PUINT_32 pu4Data; + PUINT_64 pu8Data; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prEventStatistics = (P_EVENT_STATISTICS) pucEventBuf; + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + + if (prCmdInfo->u4InformationBufferLength == sizeof(UINT_32)) { + u4QueryInfoLen = sizeof(UINT_32); + + pu4Data = (PUINT_32) prCmdInfo->pvInformationBuffer; + *pu4Data = (UINT_32) prEventStatistics->rFailedCount.QuadPart; + } else { + u4QueryInfoLen = sizeof(UINT_64); + + pu8Data = (PUINT_64) prCmdInfo->pvInformationBuffer; + *pu8Data = (UINT_64) prEventStatistics->rFailedCount.QuadPart; + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command by OID/ioctl has been timeout +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +VOID nicOidCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a generic command timeout handler +* +* @param pfnOidHandler Pointer to the OID handler +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdTimeoutCommon(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for entering RF test has +* failed sending due to timeout (highly possibly by firmware crash) +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicOidCmdEnterRFTestTimeout(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo) +{ + ASSERT(prAdapter); + + /* 1. Remove pending TX frames */ + nicTxRelease(prAdapter); + + /* 1.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 1.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 2. indicate for OID failure */ + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_FAILURE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when command for memory dump has +* replied a event. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryMemDump(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T prMemDumpInfo; + P_GLUE_INFO_T prGlueInfo; + P_EVENT_DUMP_MEM_T prEventDumpMem; + static UINT_8 aucPath[256]; + static UINT_32 u4CurTimeTick; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventDumpMem = (P_EVENT_DUMP_MEM_T) (pucEventBuf); + + u4QueryInfoLen = sizeof(P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T); + + prMemDumpInfo = (P_PARAM_CUSTOM_MEM_DUMP_STRUCT_T) prCmdInfo->pvInformationBuffer; + prMemDumpInfo->u4Address = prEventDumpMem->u4Address; + prMemDumpInfo->u4Length = prEventDumpMem->u4Length; + prMemDumpInfo->u4RemainLength = prEventDumpMem->u4RemainLength; + prMemDumpInfo->ucFragNum = prEventDumpMem->ucFragNum; + +#if 0 + do { + UINT_32 i = 0; + + DBGLOG(REQ, TRACE, "Rx dump address 0x%X, Length %d, FragNum %d, remain %d\n", + prEventDumpMem->u4Address, + prEventDumpMem->u4Length, prEventDumpMem->ucFragNum, prEventDumpMem->u4RemainLength); +#if 0 + for (i = 0; i < prEventDumpMem->u4Length; i++) { + DBGLOG(REQ, TRACE, "%02X ", prEventDumpMem->aucBuffer[i]); + if (i % 32 == 31) + DBGLOG(REQ, TRACE, "\n"); + } +#endif + } while (FALSE); +#endif + + if (prEventDumpMem->ucFragNum == 1) { + /* Store memory dump into sdcard, + * path /sdcard/dump___.hex + */ + u4CurTimeTick = kalGetTimeTick(); + sprintf(aucPath, "/sdcard/dump_%d_0x%08X_%d.hex", + u4CurTimeTick, + prEventDumpMem->u4Address, prEventDumpMem->u4Length + prEventDumpMem->u4RemainLength); + kalWriteToFile(aucPath, FALSE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } else { + /* Append current memory dump to the hex file */ + kalWriteToFile(aucPath, TRUE, &prEventDumpMem->aucBuffer[0], prEventDumpMem->u4Length); + } + + if (prEventDumpMem->u4RemainLength == 0 || prEventDumpMem->u4Address == 0xFFFFFFFF) { + /* The request is finished or firmware response a error */ + /* Reply time tick to iwpriv */ + *((PUINT_32) prCmdInfo->pvInformationBuffer) = u4CurTimeTick; + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } else { + /* The memory dump request is not finished, Send next command */ + wlanSendMemDumpCmd(prAdapter, + prCmdInfo->pvInformationBuffer, prCmdInfo->u4InformationBufferLength); + } + } + + return; + +} + +#if CFG_SUPPORT_BATCH_SCAN +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for SUPPORT_BATCH_SCAN +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBatchScanResult(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BATCH_RESULT_T prEventBatchResult; + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(SCN, TRACE, "nicCmdEventBatchScanResult"); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEventBatchResult = (P_EVENT_BATCH_RESULT_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_BATCH_RESULT_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEventBatchResult, sizeof(EVENT_BATCH_RESULT_T)); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +#if CFG_SUPPORT_BUILD_DATE_CODE +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for build date code information +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventBuildDateCode(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_BUILD_DATE_CODE prEvent; + P_GLUE_INFO_T prGlueInfo; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_BUILD_DATE_CODE) pucEventBuf; + + u4QueryInfoLen = sizeof(UINT_8) * 16; + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent->aucDateCode, sizeof(UINT_8) * 16); + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query STA link status +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryStaStatistics(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_STA_STATISTICS_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_STA_STATISTICS prStaStatistics; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_STA_STATISTICS_T) pucEventBuf; + prStaStatistics = (P_PARAM_GET_STA_STATISTICS) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_STA_STA_STATISTICS); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prStaStatistics->ucPer = prEvent->ucPer; + prStaStatistics->ucRcpi = prEvent->ucRcpi; + prStaStatistics->u4PhyMode = prEvent->u4PhyMode; + prStaStatistics->u2LinkSpeed = prEvent->u2LinkSpeed; + + prStaStatistics->u4TxFailCount = prEvent->u4TxFailCount; + prStaStatistics->u4TxLifeTimeoutCount = prEvent->u4TxLifeTimeoutCount; + + if (prEvent->u4TxCount) { + UINT_32 u4TxDoneAirTimeMs = USEC_TO_MSEC(prEvent->u4TxDoneAirTime * 32); + + prStaStatistics->u4TxAverageAirTime = (u4TxDoneAirTimeMs / prEvent->u4TxCount); + } else { + prStaStatistics->u4TxAverageAirTime = 0; + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + +/* 4 Auto Channel Selection */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query STA link status +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicCmdEventQueryChannelLoad(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_CHN_LOAD_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_CHN_LOAD prChnLoad; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_CHN_LOAD_T) pucEventBuf; /* 4 The firmware responsed data */ + /* 4 Fill the firmware data in and send it back to host */ + prChnLoad = (P_PARAM_GET_CHN_LOAD) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_CHN_LOAD); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + prChnLoad->rEachChnLoad[0].ucChannel = prEvent->ucChannel; + prChnLoad->rEachChnLoad[0].u2ChannelLoad = prEvent->u2ChannelLoad; + DBGLOG(P2P, INFO, "CHN[%d]=%d\n", prEvent->ucChannel, prEvent->u2ChannelLoad); + + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} + +VOID nicCmdEventQueryLTESafeChn(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_8 ucIdx = 0; + UINT_32 u4QueryInfoLen; + P_EVENT_LTE_MODE_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_PARAM_GET_CHN_LOAD prLteSafeChnInfo; + + if ((prAdapter == NULL) + || (prCmdInfo == NULL) + || (pucEventBuf == NULL) + || (prCmdInfo->pvInformationBuffer == NULL)) { + ASSERT(FALSE); + return; + } + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_LTE_MODE_T) pucEventBuf; /* 4 The firmware responsed data */ + + prLteSafeChnInfo = (P_PARAM_GET_CHN_LOAD) prCmdInfo->pvInformationBuffer; + + u4QueryInfoLen = sizeof(PARAM_GET_CHN_LOAD); + + /* Statistics from FW is valid */ + if (prEvent->u4Flags & BIT(0)) { + for (ucIdx = 0; ucIdx < (NL80211_TESTMODE_AVAILABLE_CHAN_NUM - 1); ucIdx++) { + prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx] = + prEvent->rLteSafeChn.au4SafeChannelBitmask[ucIdx]; + + DBGLOG(P2P, INFO, + "[Auto Channel]LTE safe channels [%d]=[%x]\n", ucIdx, + (UINT32) prLteSafeChnInfo->rLteSafeChnList.au4SafeChannelBitmask[ucIdx]); + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is called when event for query FW bss info +* has been retrieved +* +* @param prAdapter Pointer to the Adapter structure. +* @param prCmdInfo Pointer to the command information +* @param pucEventBuf Pointer to the event buffer +* +* @return none +* +*/ +/*----------------------------------------------------------------------------*/ + +VOID nicCmdEventGetBSSInfo(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf) +{ + UINT_32 u4QueryInfoLen; + P_EVENT_AIS_BSS_INFO_T prEvent; + P_GLUE_INFO_T prGlueInfo; + P_BSS_INFO_T prAisBssInfo; + + ASSERT(prAdapter); + + ASSERT(prCmdInfo); + ASSERT(pucEventBuf); + + /* 4 <2> Update information of OID */ + if (prCmdInfo->fgIsOid) { + prGlueInfo = prAdapter->prGlueInfo; + prEvent = (P_EVENT_AIS_BSS_INFO_T) pucEventBuf; + + u4QueryInfoLen = sizeof(EVENT_AIS_BSS_INFO_T); + kalMemCopy(prCmdInfo->pvInformationBuffer, prEvent, sizeof(EVENT_AIS_BSS_INFO_T)); + prAisBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + + if (prEvent->eCurrentOPMode == OP_MODE_INFRASTRUCTURE) { + if (prEvent->eConnectionState != prAisBssInfo->eConnectionState) { + DBGLOG(NIC, ERROR, "driver[%d] & FW[%d] status didn't sync !!!\n", + prAisBssInfo->eConnectionState, prEvent->eCurrentOPMode); + aisFsmStateAbort(prAdapter, DISCONNECT_REASON_CODE_RADIO_LOST, FALSE); + } + } + + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, u4QueryInfoLen, WLAN_STATUS_SUCCESS); + } + +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c new file mode 100644 index 0000000000000..cf80fd999a240 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_pwr_mgt.c @@ -0,0 +1,669 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_pwr_mgt.c#1 +*/ + +/*! \file "nic_pwr_mgt.c" + \brief In this file we define the STATE and EVENT for Power Management FSM. + + The SCAN FSM is responsible for performing SCAN behavior when the Arbiter enter + ARB_STATE_SCAN. The STATE and EVENT for SCAN FSM are defined here with detail + description. +*/ + +/* +** Log: nic_pwr_mgt.c + * + * 11 28 2011 cp.wu + * [WCXRP00001125] [MT6620 Wi-Fi][Firmware] Strengthen Wi-Fi power off sequence to have a clearroom environment when + * returining to ROM code + * 1. Due to firmware now stops HIF DMA for powering off, do not try to receive any packet from firmware + * 2. Take use of prAdapter->fgIsEnterD3ReqIssued for tracking whether it is powering off or not + * + * 10 03 2011 cp.wu + * [WCXRP00001022] [MT6628 Driver][Firmware Download] Add multi section independent download functionality + * add firmware download path in divided scatters. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * reuse firmware download logic of MT6620 for MT6628. + * + * 05 11 2011 cp.wu + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * ACPI APIs migrate to wlan_lib.c for glue layer to invoke. + * + * 04 29 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * fix for compilation error when applied with FW_DOWNLOAD = 0 + * + * 04 18 2011 cp.wu + * [WCXRP00000636] [WHQL][MT5931 Driver] 2c_PMHibernate (hang on 2h) + * 1) add API for glue layer to query ACPI state + * 2) Windows glue should not access to hardware after switched into D3 state + * + * 04 13 2011 cp.wu + * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete + * refine for MT5931/MT6620 logic separation. + * + * 04 13 2011 cp.wu + * [WCXRP00000639] [WHQL][MT5931 Driver] 2c_PMStandby test item can not complete + * bugfix: firmware download procedure for ACPI state transition is not complete. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system + * scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being + * loaded + * + * 12 31 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * check success or failure for setting fw-own + * + * 12 30 2010 cp.wu + * [WCXRP00000327] [MT6620 Wi-Fi][Driver] Improve HEC WHQA 6972 workaround coverage in driver side + * host driver not to set FW-own when there is still pending interrupts + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * add firmware download for MT5931. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + * associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 30 2010 cp.wu + * NULL + * reset ACPI power state before waking up MT6620 Wi-Fi firmware. + * + * 08 12 2010 cp.wu + * NULL + * [AIS-FSM] honor registry setting for adhoc running mode. (A/B/G) + * + * 08 03 2010 cp.wu + * NULL + * Centralize mgmt/system service procedures into independent calls. + * + * 07 22 2010 cp.wu + * + * 1) refine AIS-FSM indent. + * 2) when entering RF Test mode, flush 802.1X frames as well + * 3) when entering D3 state, flush 802.1X frames as well + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) when acquiring LP-own, write for clr-own with lower frequency compared to read poll + * 2) correct address list parsing + * + * 05 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * sleepy notify is only used for sleepy state, + * while wake-up state is automatically set when host needs to access device + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct hibernation problem. + * + * 04 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) surpress compiler warning + * 2) when acqruing LP-own, keep writing WHLPCR whenever OWN is not acquired yet + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when acquiring driver-own, wait for up to 8 seconds. + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove redundant firmware image unloading + * * 2) use compile-time macros to separate logic related to accquiring own + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * are now handled in glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * ePowerCtrl is not necessary as a glue variable. + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * always send CMD_NIC_POWER_CTRL packet when nic is being halted + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct typo. + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX + * response + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-10-13 21:59:15 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-09-09 17:26:36 GMT mtk01084 +** remove CMD52 access +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-05-18 14:50:29 GMT mtk01084 +** modify lines in nicpmSetDriverOwn() +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-23 16:55:37 GMT mtk01084 +** modify nicpmSetDriverOwn() +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-19 18:33:00 GMT mtk01084 +** update for basic power management functions +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-03-19 15:05:32 GMT mtk01084 +** Initial version +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER ON procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicpmSetFWOwn(IN P_ADAPTER_T prAdapter, IN BOOLEAN fgEnableGlobalInt) +{ + UINT_32 u4RegValue = 0; + + ASSERT(prAdapter); + + if (prAdapter->fgIsFwOwn == TRUE) + return; + + if (nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + /* pending interrupts */ + return; + } + + if (fgEnableGlobalInt) { + prAdapter->fgIsIntEnableWithLPOwnSet = TRUE; + } else { + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_SET); + + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + /* if set firmware own not successful (possibly pending interrupts), */ + /* indicate an own clear event */ + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + + return; + } + + prAdapter->fgIsFwOwn = TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to process the POWER OFF procedure. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4OriRegValue = 0; +BOOLEAN nicpmSetDriverOwn(IN P_ADAPTER_T prAdapter) +{ +#define LP_OWN_BACK_TOTAL_DELAY_MS 2000 /* exponential of 2 */ +#define LP_OWN_BACK_LOOP_DELAY_MS 1 /* exponential of 2 */ +#define LP_OWN_BACK_CLR_OWN_ITERATION 256 /* exponential of 2 */ + + BOOLEAN fgStatus = TRUE; + UINT_32 i, u4CurrTick; + UINT_32 u4RegValue = 0; + GL_HIF_INFO_T *HifInfo; + + ASSERT(prAdapter); + + if (prAdapter->fgIsFwOwn == FALSE) + return fgStatus; + + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + + u4CurrTick = kalGetTimeTick(); + STATS_DRIVER_OWN_START_RECORD(); + i = 0; + + while (1) { + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); + prAdapter->fgIsFwOwn = FALSE; + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE + || fgIsBusAccessFailed == TRUE + || (kalGetTimeTick() - u4CurrTick) > LP_OWN_BACK_TOTAL_DELAY_MS || fgIsResetting == TRUE) { + /* ERRORLOG(("LP cannot be own back (for %ld ms)", kalGetTimeTick() - u4CurrTick)); */ + fgStatus = FALSE; + if (fgIsResetting != TRUE) { + UINT_32 u4FwCnt; + static unsigned int u4OwnCnt; + /* MCR_D2HRM2R: low 4 bit means interrupt times, + * high 4 bit means firmware response times. + * ORI_MCR_D2HRM2R: the last successful value. + * for example: + * MCR_D2HRM2R = 0x44, ORI_MCR_D2HRM2R = 0x44 + * means firmware no receive interrupt form hardware. + * MCR_D2HRM2R = 0x45, ORI_MCR_D2HRM2R = 0x44 + * means firmware no send response. + * MCR_D2HRM2R = 0x55, ORI_MCR_D2HRM2R = 0x44 + * means firmware send response, but driver no receive. */ + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); + DBGLOG(NIC, WARN, " [1]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", + u4RegValue, u4OriRegValue); + + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + HAL_MCR_RD(prAdapter, MCR_WHLPCR, &u4RegValue); + if (u4RegValue & WHLPCR_FW_OWN_REQ_SET) { + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4OriRegValue); + prAdapter->fgIsFwOwn = FALSE; + break; + } + HAL_MCR_RD(prAdapter, MCR_D2HRM2R, &u4RegValue); + DBGLOG(NIC, WARN, " [2]MCR_D2HRM2R = 0x%x, ORI_MCR_D2HRM2R = 0x%x\n", + u4RegValue, u4OriRegValue); + DBGLOG(NIC, WARN, + " Fatal error! Driver own fail!!!!!!!!!!!! %d, fgIsBusAccessFailed: %d\n", + u4OwnCnt++, fgIsBusAccessFailed); + + DBGLOG(NIC, WARN, "CONNSYS FW CPUINFO:\n"); + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(NIC, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ + kalSendAeeWarning("[Fatal error! Driver own fail!]", __func__); + glDoChipReset(); + } + break; + } + if ((i & (LP_OWN_BACK_CLR_OWN_ITERATION - 1)) == 0) { + /* Software get LP ownership - per 256 iterations */ + HAL_MCR_WR(prAdapter, MCR_WHLPCR, WHLPCR_FW_OWN_REQ_CLR); + } + + /* Delay for LP engine to complete its operation. */ + kalMsleep(LP_OWN_BACK_LOOP_DELAY_MS); + i++; + } + + STATS_DRIVER_OWN_END_RECORD(); + STATS_DRIVER_OWN_STOP(); + + return fgStatus; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set ACPI power mode to D0. +* +* \param[in] pvAdapter Pointer to the Adapter structure. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicpmSetAcpiPowerD0(IN P_ADAPTER_T prAdapter) +{ + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + UINT_32 u4Value = 0, u4WHISR = 0; + UINT_8 aucTxCount[8]; + UINT_32 i; +#if CFG_ENABLE_FW_DOWNLOAD + UINT_32 u4FwImgLength, u4FwLoadAddr, u4ImgSecSize; + PVOID prFwMappingHandle; + PVOID pvFwImageMapFile = NULL; +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + UINT_32 j; + P_FIRMWARE_DIVIDED_DOWNLOAD_T prFwHead; + BOOLEAN fgValidHead; + const UINT_32 u4CRCOffset = offsetof(FIRMWARE_DIVIDED_DOWNLOAD_T, u4NumOfEntries); +#endif +#endif + + DEBUGFUNC("nicpmSetAcpiPowerD0"); + ASSERT(prAdapter); + + do { + /* 0. Reset variables in ADAPTER_T */ + prAdapter->fgIsFwOwn = TRUE; + prAdapter->fgWiFiInSleepyState = FALSE; + prAdapter->rAcpiState = ACPI_STATE_D0; + prAdapter->fgIsEnterD3ReqIssued = FALSE; + + /* 1. Request Ownership to enter F/W download state */ + ACQUIRE_POWER_CONTROL_FROM_PM(prAdapter); +#if !CFG_ENABLE_FULL_PM + nicpmSetDriverOwn(prAdapter); +#endif + + /* 2. Initialize the Adapter */ + u4Status = nicInitializeAdapter(prAdapter); + if (u4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "nicInitializeAdapter failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + +#if CFG_ENABLE_FW_DOWNLOAD + prFwMappingHandle = kalFirmwareImageMapping(prAdapter->prGlueInfo, &pvFwImageMapFile, &u4FwImgLength); + if (!prFwMappingHandle) { + DBGLOG(NIC, ERROR, "Fail to load FW image from file!\n"); + pvFwImageMapFile = NULL; + } + + if (pvFwImageMapFile == NULL) { + u4Status = WLAN_STATUS_FAILURE; + break; + } + + /* 3.1 disable interrupt, download is done by polling mode only */ + nicDisableInterrupt(prAdapter); + + /* 3.2 Initialize Tx Resource to fw download state */ + nicTxInitResetResource(prAdapter); + + /* 3.3 FW download here */ + u4FwLoadAddr = kalGetFwLoadAddress(prAdapter->prGlueInfo); + +#if CFG_ENABLE_FW_DIVIDED_DOWNLOAD + /* 3a. parse file header for decision of divided firmware download or not */ + prFwHead = (P_FIRMWARE_DIVIDED_DOWNLOAD_T) pvFwImageMapFile; + + if (prFwHead->u4Signature == MTK_WIFI_SIGNATURE && + prFwHead->u4CRC == wlanCRC32((PUINT_8) pvFwImageMapFile + u4CRCOffset, + u4FwImgLength - u4CRCOffset)) { + fgValidHead = TRUE; + } else { + fgValidHead = FALSE; + } + + /* 3b. engage divided firmware downloading */ + if (fgValidHead == TRUE) { + for (i = 0; i < prFwHead->u4NumOfEntries; i++) { +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + prFwHead->arSection[i].u4DestAddr, + prFwHead->arSection[i].u4Length, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset) != + WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (j = 0; j < prFwHead->arSection[i].u4Length; j += CMD_PKT_SIZE_FOR_IMAGE) { + if (j + CMD_PKT_SIZE_FOR_IMAGE < prFwHead->arSection[i].u4Length) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = prFwHead->arSection[i].u4Length - j; + + if (wlanImageSectionDownload(prAdapter, + prFwHead->arSection[i].u4DestAddr + j, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + + prFwHead->arSection[i].u4Offset + j) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + /* escape from loop if any pending error occurs */ + if (u4Status == WLAN_STATUS_FAILURE) + break; + } + } else +#endif +#if CFG_ENABLE_FW_DOWNLOAD_AGGREGATION + if (wlanImageSectionDownloadAggregated(prAdapter, + u4FwLoadAddr, + u4FwImgLength, + (PUINT_8) pvFwImageMapFile) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "Firmware scatter download failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + } +#else + for (i = 0; i < u4FwImgLength; i += CMD_PKT_SIZE_FOR_IMAGE) { + if (i + CMD_PKT_SIZE_FOR_IMAGE < u4FwImgLength) + u4ImgSecSize = CMD_PKT_SIZE_FOR_IMAGE; + else + u4ImgSecSize = u4FwImgLength - i; + + if (wlanImageSectionDownload(prAdapter, + u4FwLoadAddr + i, + u4ImgSecSize, + (PUINT_8) pvFwImageMapFile + i) != WLAN_STATUS_SUCCESS) { + DBGLOG(NIC, ERROR, "wlanImageSectionDownload failed!\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + } +#endif + + if (u4Status != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + break; + } +#if !CFG_ENABLE_FW_DOWNLOAD_ACK + /* Send INIT_CMD_ID_QUERY_PENDING_ERROR command and wait for response */ + if (wlanImageQueryStatus(prAdapter) != WLAN_STATUS_SUCCESS) { + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + u4Status = WLAN_STATUS_FAILURE; + break; + } +#endif + kalFirmwareImageUnmapping(prAdapter->prGlueInfo, prFwMappingHandle, pvFwImageMapFile); + + /* 4. send Wi-Fi Start command */ +#if CFG_OVERRIDE_FW_START_ADDRESS + wlanConfigWifiFunc(prAdapter, TRUE, kalGetFwStartAddress(prAdapter->prGlueInfo)); +#else + wlanConfigWifiFunc(prAdapter, FALSE, 0); +#endif +#endif /* if CFG_ENABLE_FW_DOWNLOAD */ + + /* 5. check Wi-Fi FW asserts ready bit */ + DBGLOG(NIC, TRACE, "wlanAdapterStart(): Waiting for Ready bit..\n"); + i = 0; + while (1) { + HAL_MCR_RD(prAdapter, MCR_WCIR, &u4Value); + + if (u4Value & WCIR_WLAN_READY) { + DBGLOG(NIC, TRACE, "Ready bit asserted\n"); + break; + } else if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (i >= CFG_RESPONSE_POLLING_TIMEOUT) { + DBGLOG(NIC, ERROR, "Waiting for Ready bit: Timeout\n"); + u4Status = WLAN_STATUS_FAILURE; + break; + } + i++; + kalMsleep(10); + } + + if (u4Status == WLAN_STATUS_SUCCESS) { + /* 6.1 reset interrupt status */ + HAL_READ_INTR_STATUS(prAdapter, 4, (PUINT_8)(&u4WHISR)); + if (HAL_IS_TX_DONE_INTR(u4WHISR)) + HAL_READ_TX_RELEASED_COUNT(prAdapter, aucTxCount); + + /* 6.2 reset TX Resource for normal operation */ + nicTxResetResource(prAdapter); + + /* 6.3 Enable interrupt */ + nicEnableInterrupt(prAdapter); + + /* 6.4 Override network address */ + wlanUpdateNetworkAddress(prAdapter); + + /* 6.5 indicate disconnection as default status */ + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + } + + RECLAIM_POWER_CONTROL_TO_PM(prAdapter, FALSE); + + /* MGMT Initialization */ + nicInitMGMT(prAdapter, NULL); + + } while (FALSE); + + if (u4Status != WLAN_STATUS_SUCCESS) + return FALSE; + else + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is used to set ACPI power mode to D3. +* +* @param prAdapter pointer to the Adapter handler +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicpmSetAcpiPowerD3(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + + ASSERT(prAdapter); + + /* 1. MGMT - unitialization */ + nicUninitMGMT(prAdapter); + + /* 2. Disable Interrupt */ + nicDisableInterrupt(prAdapter); + + /* 3. emit CMD_NIC_POWER_CTRL command packet */ + wlanSendNicPowerCtrlCmd(prAdapter, 1); + + /* 4. Clear Interrupt Status */ + i = 0; + while (i < CFG_IST_LOOP_COUNT && nicProcessIST(prAdapter) != WLAN_STATUS_NOT_INDICATING) { + i++; + }; + + /* 5. Remove pending TX */ + nicTxRelease(prAdapter); + + /* 5.1 clear pending Security / Management Frames */ + kalClearSecurityFrames(prAdapter->prGlueInfo); + kalClearMgmtFrames(prAdapter->prGlueInfo); + + /* 5.2 clear pending TX packet queued in glue layer */ + kalFlushPendingTxPackets(prAdapter->prGlueInfo); + + /* 6. Set Onwership to F/W */ + nicpmSetFWOwn(prAdapter, FALSE); + + /* 7. Set variables */ + prAdapter->rAcpiState = ACPI_STATE_D3; + + return TRUE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c new file mode 100644 index 0000000000000..ba4840414da85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_rx.c @@ -0,0 +1,3782 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_rx.c#3 +*/ + +/*! \file nic_rx.c + \brief Functions that provide many rx-related functions + + This file includes the functions used to process RFB and dispatch RFBs to + the appropriate related rx functions for protocols. +*/ + +/* +** Log: nic_rx.c +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously, +** one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 14 2012 cp.wu + * NULL + * remove another assertion by error message dump + * + * 01 05 2012 tsaiyuan.hsu + * [WCXRP00001157] [MT6620 Wi-Fi][FW][DRV] add timing measurement support for 802.11v + * add timing measurement support for 802.11v. + * + * 11 19 2011 yuche.tsai + * NULL + * Update RSSI for P2P. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 09 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for beacon timeout and sta aging timeout. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 10 21 2011 eddie.chen + * [WCXRP00001051] [MT6620 Wi-Fi][Driver/Fw] Adjust the STA aging timeout + * Add switch to ignore the STA aging timeout. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 08 26 2011 cp.wu + * [WCXRP00000958] [MT6620 Wi-Fi][Driver] Extend polling timeout from 25ms to 1sec due to RF calibration might took + * up to 600ms + * extend polling RX response timeout period from 25ms to 1000ms. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 27 2011 cp.wu + * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently available RX counter and QUE_MGT used count + * correct comment. + * + * 07 27 2011 cp.wu + * [WCXRP00000876] [MT5931][Drver] Decide to retain according to currently available RX counter and QUE_MGT used count + * take use of QUE_MGT exported function to estimate currently RX buffer usage count. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 09 2011 tsaiyuan.hsu + * [WCXRP00000760] [MT5931 Wi-Fi][FW] Refine rxmHandleMacRxDone to reduce code size + * move send_auth at rxmHandleMacRxDone in firmware to driver to reduce code size. + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 05 05 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add delay after whole-chip resetting for MT5931 E1 ASIC. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support for GO. + * + * 04 01 2011 tsaiyuan.hsu + * [WCXRP00000615] [MT 6620 Wi-Fi][Driver] Fix klocwork issues + * fix the klocwork issues, 57500, 57501, 57502 and 57503. + * + * 03 19 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Add beacon timeout support for WiFi Direct Network. + * + * 03 18 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * enable the Anti_piracy check at driver . + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after + * connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000419] [Volunteer Patch][MT6620/MT5931][Driver] Provide function of disconnect to target station for AAA + * module. + * Remove Station Record after Aging timeout. + * + * 02 10 2011 cp.wu + * [WCXRP00000434] [MT6620 Wi-Fi][Driver] Obsolete unused event packet handlers + * EVENT_ID_CONNECTION_STATUS has been obsoleted and no need to handle. + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add MLME deauthentication support for Hot-Spot mode. + * + * 02 09 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Adjust variable order. + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * . + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Remove comments. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 24 2011 cm.chang + * [WCXRP00000384] [MT6620 Wi-Fi][Driver][FW] Handle 20/40 action frame in AP mode and stop ampdu timer when sta_rec + * is freed + * Process received 20/40 coexistence action frame for AP mode + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * update beacon for NoA + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 27 2010 george.huang + * [WCXRP00000127] [MT6620 Wi-Fi][Driver] Add a registry to disable Beacon Timeout function for SQA test by using E1 EVB + * Support registry option for disable beacon lost detection. + * + * 10 20 2010 wh.su + * NULL + * add a cmd to reset the p2p key + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * fixed compilier error. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 23 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * eliminate reference of CFG_RESPONSE_MAX_PKT_SIZE + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + * associated + * release RX packet to packet pool when in RF test mode + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + @ associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 08 2010 cp.wu + * NULL + * use static memory pool for storing IEs of scanning result. + * + * 09 07 2010 yuche.tsai + * NULL + * Add a common buffer, store the IE of a P2P device in this common buffer. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 20 2010 cm.chang + * NULL + * Migrate RLM code to host from FW + * + * 08 20 2010 yuche.tsai + * NULL + * When enable WiFi Direct function, check each packet to tell which interface to indicate. + * + * 08 05 2010 yuche.tsai + * NULL + * Add P2P Device Discovery Function. + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 george.huang + * NULL + * handle event for updating NOA parameters indicated from FW + * + * 08 02 2010 yuche.tsai + * NULL + * Add support API for RX public action frame. + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 30 2010 cp.wu + * NULL + * 1) BoW wrapper: use definitions instead of hard-coded constant for error code + * 2) AIS-FSM: eliminate use of desired RF parameters, use prTargetBssDesc instead + * 3) add handling for RX_PKT_DESTINATION_HOST_WITH_FORWARD for GO-broadcast frames + * + * 07 26 2010 yuche.tsai + * + * Update Device Capability Bitmap & Group Capability Bitmap from 16 bits to 8 bits. + * + * 07 24 2010 wh.su + * + * .support the Wi-Fi RSN + * + * 07 23 2010 cp.wu + * + * add AIS-FSM handling for beacon timeout event. + * + * 07 21 2010 yuche.tsai + * + * Add P2P Scan & Scan Result Parsing & Saving. + * + * 07 19 2010 cm.chang + * + * Set RLM parameters and enable CNM channel manager + * + * 07 19 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration. + * Add Ad-Hoc support to AIS-FSM + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 15 2010 cp.wu + * + * sync. bluetooth-over-Wi-Fi interface to driver interface document v0.2.6. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill ucStaRecIdx into SW_RFB_T. + * + * 07 02 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) for event packet, no need to fill RFB. + * 2) when wlanAdapterStart() failed, no need to initialize state machines + * 3) after Beacon/ProbeResp parsing, corresponding BSS_DESC_T should be marked as IE-parsed + * + * 07 01 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implementation of DRV-SCN and related mailbox message handling. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * refine TX-DONE callback. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * implement TX_DONE callback path. + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add TX Done Event handle entry + * + * 06 21 2010 wh.su + * [WPD00003840][MT6620 5931] Security migration + * remove duplicate variable for migration. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * saa_fsm.c is migrated. + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add management dispatching function table. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) eliminate CFG_CMD_EVENT_VERSION_0_9 + * 2) when disconnected, indicate nic directly (no event is needed) + * + * 06 08 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * cnm_timer has been migrated. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * merge wlan_def.h. + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * sync with MT6620 driver for scan result replacement policy + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) integrate OID_GEN_NETWORK_LAYER_ADDRESSES with CMD_ID_SET_IP_ADDRESS + * 2) buffer statistics data for 2 seconds + * 3) use default value for adhoc parameters instead of 0 + * + * 05 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) do not take timeout mechanism for power mode oids + * 2) retrieve network type from connection status + * 3) after disassciation, set radio state to off + * 4) TCP option over IPv6 is supported + * + * 04 29 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * fixing the PMKID candicate indicate code. + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * basic implementation for EVENT_BT_OVER_WIFI + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 16 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * treat BUS access failure as kind of card removal. + * + * 04 14 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * nicRxProcessEvent packet doesn't access spin-lock directly from now on. + * + * 04 14 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * do not need to release the spin lock due to it is done inside nicGetPendingCmdInfo() + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add channel frequency <-> number conversion + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * 2) add KAPI for handling association info + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve Linux supplicant compliance + * + * 03 31 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl which may cause cmdinfo memory leak + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * rWlanInfo is modified before data is indicated to OS + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * rWlanInfo is modified before data is indicated to OS + * + * 03 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a temporary flag for integration with CMD/EVENT v0.9. + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * * the frequency is used for adhoc connection only + * * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * . + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * * + * + * 03 19 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add ACPI D0/D3 state switching support + * * * * * * * * * 2) use more formal way to handle interrupt when the status is retrieved from enhanced RX + * response + * + * 03 15 2010 kevin.huang + * [WPD00003820][MT6620 Wi-Fi] Modify the code for meet the WHQL test + * Add event for activate STA_RECORD_T + * + * 03 12 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct fgSetQuery/fgNeedResp check + * + * 03 11 2010 cp.wu + * [WPD00003821][BUG] Host driver stops processing RX packets from HIF RX0 + * add RX starvation warning debug message controlled by CFG_HIF_RX_STARVATION_WARNING + * + * 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) the use of prPendingOid revised, all accessing are now protected by spin lock + * * * * 2) ensure wlanReleasePendingOid will clear all command queues + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * move EVENT_ID_ASSOC_INFO from nic_rx.c to gl_kal_ndis_51.c + * * 'cause it involves OS dependent data structure handling + * + * 02 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * correct behavior to prevent duplicated RX handling for RX0_DONE and RX1_DONE + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Updated API interfaces for qmHandleEventRxAddBa() and qmHandleEventRxDelBa() + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement host-side firmware download logic + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * * 4) nicRxWaitResponse() revised + * * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 01 27 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * . + * + * 01 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * implement following 802.11 OIDs: + * * * * * * OID_802_11_RSSI, + * * * * * * OID_802_11_RSSI_TRIGGER, + * * * * * * OID_802_11_STATISTICS, + * * * * * * OID_802_11_DISASSOCIATE, + * * * * * * OID_802_11_POWER_MODE + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * * 2) add 4 counter for recording aggregation statistics + * + * 12 23 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add a precheck: if free sw rfb is not enough, do not invoke read transactionu1rwduu`wvpghlqg|fu+rp + * + * 12 22 2009 cp.wu + * [WPD00003809][Bug] Host driver will crash when processing reordered MSDUs + * The root cause is pointer accessing by mistake. After dequeued from reordering-buffer, handling logic should access + * returned pointer instead of pointer which has been passed in before. +** \main\maintrunk.MT6620WiFiDriver_Prj\58 2009-12-17 13:40:33 GMT mtk02752 +** always update prAdapter->rSDIOCtrl when enhanced response is read by RX +** \main\maintrunk.MT6620WiFiDriver_Prj\57 2009-12-16 18:01:38 GMT mtk02752 +** if interrupt enhanced response is fetched by RX enhanced response, RX needs to invoke interrupt handlers too +** \main\maintrunk.MT6620WiFiDriver_Prj\56 2009-12-16 14:16:52 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\55 2009-12-15 20:03:12 GMT mtk02752 +** ASSERT when RX FreeSwRfb is not enough +** \main\maintrunk.MT6620WiFiDriver_Prj\54 2009-12-15 17:01:29 GMT mtk02752 +** when CFG_SDIO_RX_ENHANCE is enabled, after enhanced response is read, rx procedure should process +** 1) TX_DONE_INT 2) D2H INT as well +** \main\maintrunk.MT6620WiFiDriver_Prj\53 2009-12-14 20:45:28 GMT mtk02752 +** when CFG_SDIO_RX_ENHANCE is set, TC counter must be updated each time RX enhance response is read +** +** \main\maintrunk.MT6620WiFiDriver_Prj\52 2009-12-14 11:34:16 GMT mtk02752 +** correct a trivial logic issue +** \main\maintrunk.MT6620WiFiDriver_Prj\51 2009-12-14 10:28:25 GMT mtk02752 +** add a protection to avoid out-of-boundary access +** \main\maintrunk.MT6620WiFiDriver_Prj\50 2009-12-10 16:55:18 GMT mtk02752 +** code clean +** \main\maintrunk.MT6620WiFiDriver_Prj\49 2009-12-09 14:06:47 GMT MTK02468 +** Added parsing event packets with EVENT_ID_RX_ADDBA or EVENT_ID_RX_DELBA +** \main\maintrunk.MT6620WiFiDriver_Prj\48 2009-12-08 17:37:51 GMT mtk02752 +** handle EVENT_ID_TEST_STATUS as well +** \main\maintrunk.MT6620WiFiDriver_Prj\47 2009-12-04 17:59:11 GMT mtk02752 +** to pass free-build compilation check +** \main\maintrunk.MT6620WiFiDriver_Prj\46 2009-12-04 12:09:52 GMT mtk02752 +** correct trivial mistake +** \main\maintrunk.MT6620WiFiDriver_Prj\45 2009-12-04 11:53:37 GMT mtk02752 +** all API should be compilable under SD1_SD3_DATAPATH_INTEGRATION == 0 +** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-03 16:19:48 GMT mtk01461 +** Fix the Connected Event +** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-11-30 10:56:18 GMT mtk02752 +** 1st DW of WIFI_EVENT_T is shared with HIF_RX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-11-30 10:11:27 GMT mtk02752 +** implement replacement for bss scan result +** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-11-27 11:08:05 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-11-26 09:38:59 GMT mtk02752 +** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-11-26 09:29:40 GMT mtk02752 +** enable packet forwarding path (for AP mode) +** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-11-25 21:37:00 GMT mtk02752 +** sync. with EVENT_SCAN_RESULT_T change, and add an assert for checking event size +** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-25 20:17:41 GMT mtk02752 +** fill HIF_TX_HEADER_T.u2SeqNo +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-25 18:18:57 GMT mtk02752 +** buffer scan result to prGlueInfo->rWlanInfo.arScanResult directly. +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-24 22:42:45 GMT mtk02752 +** add nicRxAddScanResult() to prepare to handle SCAN_RESULT event (not implemented yet) +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-24 20:51:41 GMT mtk02752 +** integrate with SD1's data path API +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-24 19:56:17 GMT mtk02752 +** adopt P_HIF_RX_HEADER_T in new path +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-23 20:31:21 GMT mtk02752 +** payload to send into pfCmdDoneHandler() will not include WIFI_EVENT_T +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-23 17:51:34 GMT mtk02752 +** when event packet corresponding to some pendingOID is received, pendingOID should be cleared +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 14:46:54 GMT mtk02752 +** implement nicRxProcessEventPacket() +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-17 22:40:54 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-16 21:48:22 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION data path handling +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-16 15:41:18 GMT mtk01084 +** modify the length to be read in emu mode +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-13 17:00:12 GMT mtk02752 +** add blank function for event packet +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-13 13:54:24 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-11 14:41:51 GMT mtk02752 +** fix typo +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-11 14:33:46 GMT mtk02752 +** add protection when there is no packet avilable +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 12:33:36 GMT mtk02752 +** add RX1 read path for aggregated/enhanced/normal packet read procedures +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-11 10:36:18 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-11-04 14:11:08 GMT mtk01084 +** modify lines in RX aggregation +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-30 18:17:23 GMT mtk01084 +** modify RX aggregation handling +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-29 19:56:12 GMT mtk01084 +** modify HAL part +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-10-23 16:08:34 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-10-13 21:59:20 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-10-02 13:59:08 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-05-21 23:39:05 GMT mtk01461 +** Fix the paste error of RX STATUS in OOB of HIF Loopback CTRL +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-05-20 12:25:32 GMT mtk01461 +** Fix process of Read Done, and add u4MaxEventBufferLen to nicRxWaitResponse() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-05-18 21:13:18 GMT mtk01426 +** Fixed compiler error +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-05-18 21:05:29 GMT mtk01426 +** Fixed nicRxSDIOAggReceiveRFBs() ASSERT issue +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-28 10:38:43 GMT mtk01461 +** Fix RX STATUS is DW align for SDIO_STATUS_ENHANCE mode and refine nicRxSDIOAggeceiveRFBs() for RX Aggregation +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-22 09:12:17 GMT mtk01461 +** Fix nicRxProcessHIFLoopbackPacket(), the size of HIF CTRL LENGTH field is 1 byte +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-14 15:51:26 GMT mtk01426 +** Update RX OOB Setting +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-03 14:58:58 GMT mtk01426 +** Fixed logical error +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-04-01 10:58:31 GMT mtk01461 +** Rename the HIF_PKT_TYPE_DATA +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 21:51:18 GMT mtk01461 +** Fix u4HeaderOffset in nicRxProcessHIFLoopbackPacket() +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 21:02:58 GMT mtk01426 +** Add CFG_SDIO_RX_ENHANCE and CFG_HIF_LOOPBACK support +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-17 20:20:59 GMT mtk01426 +** Add nicRxWaitResponse function +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:01 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#ifndef LINUX +#include +#else +#include +#endif + +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define RX_RESPONSE_TIMEOUT (1000) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_MGMT_FRAME_HANDLING +static PROCESS_RX_MGT_FUNCTION apfnProcessRxMgtFrame[MAX_NUM_OF_FC_SUBTYPES] = { +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0000: Association request */ +#else + NULL, /* subtype 0000: Association request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0001: Association response */ +#if CFG_SUPPORT_AAA + aaaFsmRunEventRxAssoc, /* subtype 0010: Reassociation request */ +#else + NULL, /* subtype 0010: Reassociation request */ +#endif /* CFG_SUPPORT_AAA */ + saaFsmRunEventRxAssoc, /* subtype 0011: Reassociation response */ +#if (CFG_SUPPORT_ADHOC) || (CFG_SUPPORT_AAA) + bssProcessProbeRequest, /* subtype 0100: Probe request */ +#else + NULL, /* subtype 0100: Probe request */ +#endif /* CFG_SUPPORT_ADHOC */ + scanProcessBeaconAndProbeResp, /* subtype 0101: Probe response */ + NULL, /* subtype 0110: reserved */ + NULL, /* subtype 0111: reserved */ + scanProcessBeaconAndProbeResp, /* subtype 1000: Beacon */ + NULL, /* subtype 1001: ATIM */ + saaFsmRunEventRxDisassoc, /* subtype 1010: Disassociation */ + authCheckRxAuthFrameTransSeq, /* subtype 1011: Authentication */ + saaFsmRunEventRxDeauth, /* subtype 1100: Deauthentication */ + nicRxProcessActionFrame, /* subtype 1101: Action */ + NULL, /* subtype 1110: reserved */ + NULL /* subtype 1111: reserved */ +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief Initialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxInitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucMemHandle; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 i; + + DEBUGFUNC("nicRxInitialize"); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + + /* 4 <0> Clear allocated memory. */ + kalMemZero((PVOID) prRxCtrl->pucRxCached, prRxCtrl->u4RxCachedSize); + + /* 4 <1> Initialize the RFB lists */ + QUEUE_INITIALIZE(&prRxCtrl->rFreeSwRfbList); + QUEUE_INITIALIZE(&prRxCtrl->rReceivedRfbList); + QUEUE_INITIALIZE(&prRxCtrl->rIndicatedRfbList); + + pucMemHandle = prRxCtrl->pucRxCached; + for (i = CFG_RX_MAX_PKT_NUM; i != 0; i--) { + prSwRfb = (P_SW_RFB_T) pucMemHandle; + + nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + + pucMemHandle += ALIGN_4(sizeof(SW_RFB_T)); + } + + ASSERT(prRxCtrl->rFreeSwRfbList.u4NumElem == CFG_RX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((ULONG) (pucMemHandle - prRxCtrl->pucRxCached) == prRxCtrl->u4RxCachedSize); + + /* 4 <2> Clear all RX counters */ + RX_RESET_ALL_CNTS(prRxCtrl); + +#if CFG_SDIO_RX_AGG + prRxCtrl->pucRxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, CFG_SDIO_MAX_RX_AGG_NUM); +#else + HAL_CFG_MAX_HIF_RX_LEN_NUM(prAdapter, 1); +#endif + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum = 0; + prRxCtrl->u4TotalRxPacketNum = 0; +#endif + +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt = 0; + prRxCtrl->u4DequeuedCnt = 0; +#endif + +} /* end of nicRxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Uninitialize the RFBs +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUninitialize(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + nicRxFlush(prAdapter); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + if (prSwRfb) { + if (prSwRfb->pvPacket) + kalPacketFree(prAdapter->prGlueInfo, prSwRfb->pvPacket); + prSwRfb->pvPacket = NULL; + } else { + break; + } + } while (TRUE); + +} /* end of nicRxUninitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb specify the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillRFB(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4PktLen = 0; + UINT_32 u4MacHeaderLen; + UINT_32 u4HeaderOffset; + + DEBUGFUNC("nicRxFillRFB"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + u4PktLen = prHifRxHdr->u2PacketLen; + + u4HeaderOffset = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + u4MacHeaderLen = (UINT_32) (prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_LEN) + >> HIF_RX_HDR_HEADER_LEN_OFFSET; + + /* DBGLOG(RX, TRACE, ("u4HeaderOffset = %d, u4MacHeaderLen = %d\n", */ + /* u4HeaderOffset, u4MacHeaderLen)); */ + + prSwRfb->u2HeaderLen = (UINT_16) u4MacHeaderLen; + prSwRfb->pvHeader = (PUINT_8) prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + prSwRfb->u2PacketLen = (UINT_16) (u4PktLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); + + /* DBGLOG(RX, TRACE, ("Dump Rx packet, u2PacketLen = %d\n", prSwRfb->u2PacketLen)); */ + /* DBGLOG_MEM8(RX, TRACE, prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + +#if 0 + if (prHifRxHdr->ucReorder & HIF_RX_HDR_80211_HEADER_FORMAT) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_802_11_FORMAT; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_802_11_FORMAT\n"); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_DO_REORDER) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_DO_REORDERING; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_DO_REORDERING\n"); + + /* Get Seq. No and TID, Wlan Index info */ + if (prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_BAR_FRAME) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_BAR_FRAME; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_BAR_FRAME\n"); + } + + prSwRfb->u2SSN = prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_SEQ_NO_MASK; + prSwRfb->ucTid = (UINT_8) ((prHifRxHdr->u2SeqNoTid & HIF_RX_HDR_TID_MASK) + >> HIF_RX_HDR_TID_OFFSET); + DBGLOG(RX, TRACE, "u2SSN = %d, ucTid = %d\n", prSwRfb->u2SSN, prSwRfb->ucTid); + } + + if (prHifRxHdr->ucReorder & HIF_RX_HDR_WDS) { + prSwRfb->u4HifRxHdrFlag |= HIF_RX_HDR_FLAG_AMP_WDS; + DBGLOG(RX, TRACE, "HIF_RX_HDR_FLAG_AMP_WDS\n"); + } +#endif +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 +/*----------------------------------------------------------------------------*/ +/*! +* @brief Fill checksum status in RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* @param u4TcpUdpIpCksStatus specify the Checksum status +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxFillChksumStatus(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb, IN UINT_32 u4TcpUdpIpCksStatus) +{ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prAdapter->u4CSUMFlags != CSUM_NOT_SUPPORTED) { + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv4) { /* IPv4 packet */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_IP) { /* IP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_SUCCESS; + } + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_IPv6) { /* IPv6 packet */ + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_SUCCESS; + + if (u4TcpUdpIpCksStatus & RX_CS_TYPE_TCP) { /* TCP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_TCP) { /* TCP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_SUCCESS; + } + } else if (u4TcpUdpIpCksStatus & RX_CS_TYPE_UDP) { /* UDP packet */ + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + if (u4TcpUdpIpCksStatus & RX_CS_STATUS_UDP) { /* UDP packet csum failed */ + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_FAILED; + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_SUCCESS; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_UDP] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_TCP] = CSUM_RES_NONE; + } + } else { + prSwRfb->aeCSUM[CSUM_TYPE_IPV4] = CSUM_RES_NONE; + prSwRfb->aeCSUM[CSUM_TYPE_IPV6] = CSUM_RES_NONE; + } + } + +} +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process packet doesn't need to do buffer reordering +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessPktWithoutReorder(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_TX_CTRL_T prTxCtrl; + BOOLEAN fgIsRetained = FALSE; + UINT_32 u4CurrentRxBufferCount; + P_STA_RECORD_T prStaRec = (P_STA_RECORD_T) NULL; + + DEBUGFUNC("nicRxProcessPktWithoutReorder"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + u4CurrentRxBufferCount = prRxCtrl->rFreeSwRfbList.u4NumElem; + /* QM USED = $A, AVAILABLE COUNT = $B, INDICATED TO OS = $C + * TOTAL = $A + $B + $C + * + * Case #1 (Retain) + * ------------------------------------------------------- + * $A + $B < THRESHOLD := $A + $B + $C < THRESHOLD + $C := $TOTAL - THRESHOLD < $C + * => $C used too much, retain + * + * Case #2 (Non-Retain) + * ------------------------------------------------------- + * $A + $B > THRESHOLD := $A + $B + $C > THRESHOLD + $C := $TOTAL - THRESHOLD > $C + * => still available for $C to use + * + */ + fgIsRetained = (((u4CurrentRxBufferCount + + qmGetRxReorderQueuedBufferCount(prAdapter) + + prTxCtrl->i4PendingFwdFrameCount) < CFG_RX_RETAINED_PKT_THRESHOLD) ? TRUE : FALSE); + + /* DBGLOG(RX, INFO, ("fgIsRetained = %d\n", fgIsRetained)); */ + + if (kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, fgIsRetained, prSwRfb->aeCSUM) != WLAN_STATUS_SUCCESS) { + DBGLOG(RX, ERROR, "kalProcessRxPacket return value != WLAN_STATUS_SUCCESS\n"); + ASSERT(0); + + nicRxReturnRFB(prAdapter, prSwRfb); + return; + } + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + + if (prStaRec) { +#if CFG_ENABLE_WIFI_DIRECT + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX && prAdapter->fgIsP2PRegistered == TRUE) + GLUE_SET_PKT_FLAG_P2P(prSwRfb->pvPacket); +#endif +#if CFG_ENABLE_BT_OVER_WIFI + if (prStaRec->ucNetTypeIndex == NETWORK_TYPE_BOW_INDEX) + GLUE_SET_PKT_FLAG_PAL(prSwRfb->pvPacket); +#endif + + /* record the count to pass to os */ + STATS_RX_PASS2OS_INC(prStaRec, prSwRfb); + } + prRxCtrl->apvIndPacket[prRxCtrl->ucNumIndPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumIndPacket++; + + if (fgIsRetained) { + prRxCtrl->apvRetainedPacket[prRxCtrl->ucNumRetainedPacket] = prSwRfb->pvPacket; + prRxCtrl->ucNumRetainedPacket++; + /* TODO : error handling of nicRxSetupRFB */ + nicRxSetupRFB(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } else { + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process forwarding data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessForwardPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_MSDU_INFO_T prMsduInfo, prRetMsduInfoList; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessForwardPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rFreeMsduInfoList, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + if (prMsduInfo && kalProcessRxPacket(prAdapter->prGlueInfo, + prSwRfb->pvPacket, + prSwRfb->pvHeader, + (UINT_32) prSwRfb->u2PacketLen, + prRxCtrl->rFreeSwRfbList.u4NumElem < + CFG_RX_RETAINED_PKT_THRESHOLD ? TRUE : FALSE, + prSwRfb->aeCSUM) == WLAN_STATUS_SUCCESS) { + + prMsduInfo->eSrc = TX_PACKET_FORWARDING; + /* pack into MSDU_INFO_T */ + nicTxFillMsduInfo(prAdapter, prMsduInfo, (P_NATIVE_PACKET) (prSwRfb->pvPacket)); + /* Overwrite the ucNetworkType */ + prMsduInfo->ucNetworkType = HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr); + + /* release RX buffer (to rIndicatedRfbList) */ + prSwRfb->pvPacket = NULL; + nicRxReturnRFB(prAdapter, prSwRfb); + + /* increase forward frame counter */ + GLUE_INC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + + /* send into TX queue */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfoList = qmEnqueueTxPackets(prAdapter, prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prRetMsduInfoList != NULL) { /* TX queue refuses queuing the packet */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfoList); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfoList); + } + /* indicate service thread for sending */ + if (prTxCtrl->i4PendingFwdFrameCount > 0) + kalSetEvent(prAdapter->prGlueInfo); + } else /* no TX resource */ + nicRxReturnRFB(prAdapter, prSwRfb); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process broadcast data packet for both host and forwarding +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessGOBroadcastPkt(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_SW_RFB_T prSwRfbDuplicated; + P_TX_CTRL_T prTxCtrl; + P_RX_CTRL_T prRxCtrl; + P_HIF_RX_HEADER_T prHifRxHdr; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessGOBroadcastPkt"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prTxCtrl = &prAdapter->rTxCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + ASSERT(CFG_NUM_OF_QM_RX_PKT_NUM >= 16); + + if (prRxCtrl->rFreeSwRfbList.u4NumElem + >= (CFG_RX_MAX_PKT_NUM - (CFG_NUM_OF_QM_RX_PKT_NUM - 16 /* Reserved for others */))) { + + /* 1. Duplicate SW_RFB_T */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfbDuplicated, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfbDuplicated) { + kalMemCopy(prSwRfbDuplicated->pucRecvBuff, + prSwRfb->pucRecvBuff, ALIGN_4(prHifRxHdr->u2PacketLen + HIF_RX_HW_APPENDED_LEN)); + + prSwRfbDuplicated->ucPacketType = HIF_RX_PKT_TYPE_DATA; + prSwRfbDuplicated->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + nicRxFillRFB(prAdapter, prSwRfbDuplicated); + + /* 2. Modify eDst */ + prSwRfbDuplicated->eDst = RX_PKT_DESTINATION_FORWARD; + + /* 4. Forward */ + nicRxProcessForwardPkt(prAdapter, prSwRfbDuplicated); + } + } else { + DBGLOG(RX, WARN, "Stop to forward BMC packet due to less free Sw Rfb %u\n", + prRxCtrl->rFreeSwRfbList.u4NumElem); + } + + /* 3. Indicate to host */ + prSwRfb->eDst = RX_PKT_DESTINATION_HOST; + nicRxProcessPktWithoutReorder(prAdapter, prSwRfb); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF data packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessDataPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prRetSwRfb, prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + P_STA_RECORD_T prStaRec; + BOOLEAN fIsDummy = FALSE; + + DEBUGFUNC("nicRxProcessDataPacket"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prHifRxHdr = prSwRfb->prHifRxHdr; + prRxCtrl = &prAdapter->rRxCtrl; + + fIsDummy = (prHifRxHdr->u2PacketLen >= 12) ? FALSE : TRUE; + + nicRxFillRFB(prAdapter, prSwRfb); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + { + UINT_32 u4TcpUdpIpCksStatus; + + u4TcpUdpIpCksStatus = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); + nicRxFillChksumStatus(prAdapter, prSwRfb, u4TcpUdpIpCksStatus); + + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + prStaRec = cnmGetStaRecByIndex(prAdapter, prHifRxHdr->ucStaRecIdx); + if (secCheckClassError(prAdapter, prSwRfb, prStaRec) == TRUE && prAdapter->fgTestMode == FALSE) { +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4QueuedCnt++; +#endif + prRetSwRfb = qmHandleRxPackets(prAdapter, prSwRfb); + if (prRetSwRfb != NULL) { + do { + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prRetSwRfb); + if (fIsDummy == TRUE) { + nicRxReturnRFB(prAdapter, prRetSwRfb); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, WARN, "Drop Dummy Packets"); + + } else { + switch (prRetSwRfb->eDst) { + case RX_PKT_DESTINATION_HOST: +#if ARP_MONITER_ENABLE + if (IS_STA_IN_AIS(prStaRec)) + qmHandleRxArpPackets(prAdapter, prRetSwRfb); +#endif + nicRxProcessPktWithoutReorder(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_FORWARD: + nicRxProcessForwardPkt(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_HOST_WITH_FORWARD: + nicRxProcessGOBroadcastPkt(prAdapter, prRetSwRfb); + break; + + case RX_PKT_DESTINATION_NULL: + nicRxReturnRFB(prAdapter, prRetSwRfb); + RX_INC_CNT(prRxCtrl, RX_DST_NULL_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + break; + + default: + break; + } + } +#if CFG_HIF_RX_STARVATION_WARNING + prRxCtrl->u4DequeuedCnt++; +#endif + prRetSwRfb = prNextSwRfb; + } while (prRetSwRfb); + } + } else { + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_CLASS_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF event packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ + +UINT_8 nicRxProcessGSCNEvent(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_WIFI_EVENT_T prEvent; + P_GLUE_INFO_T prGlueInfo; + struct sk_buff *skb; + struct wiphy *wiphy; + + UINT_32 real_num = 0; + + P_EVENT_GSCAN_SCAN_AVAILABLE_T prEventGscnAvailable; + P_EVENT_GSCAN_RESULT_T prEventBuffer; + P_WIFI_GSCAN_RESULT_T prEventGscnResult; + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_32 scan_id; + UINT_8 scan_flag; + P_EVENT_GSCAN_CAPABILITY_T prEventGscnCapbiblity; + P_EVENT_GSCAN_SCAN_COMPLETE_T prEventGscnScnDone; + P_WIFI_GSCAN_RESULT_T prEventGscnFullResult; + P_PARAM_WIFI_GSCAN_RESULT prParamGscnFullResult; + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnSignificantChange; + P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T prEventGscnGeofenceFound; + + P_PARAM_WIFI_GSCAN_RESULT prResults; + + DEBUGFUNC("nicRxProcessGSCNEvent"); + /* DBGLOG(RX, TRACE, ("\n")); */ + + DBGLOG(SCN, INFO, "nicRxProcessGSCNEvent\n"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + + /* Push the data to the skb */ + wiphy = priv_to_wiphy(prGlueInfo); + + /* prGlueInfo-> */ + + /* Event Handling */ + switch (prEvent->ucEID) { + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + { + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_AVAILABLE\n"); + + prEventGscnAvailable = (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer); + memcpy(prEventGscnAvailable, (P_EVENT_GSCAN_SCAN_AVAILABLE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SCAN_AVAILABLE_T)); + + mtk_cfg80211_vendor_event_scan_results_available(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, + prEventGscnAvailable->u2Num); + } + break; + + case EVENT_ID_GSCAN_RESULT: + { + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_RESULT 2\n"); + + prEventBuffer = (P_EVENT_GSCAN_RESULT_T) (prEvent->aucBuffer); + prEventGscnResult = prEventBuffer->rResult; +/* + the following event struct should moved to kal and use the kal api to avoid future porting effort + +*/ + scan_id = prEventBuffer->u2ScanId; + scan_flag = prEventBuffer->u2ScanFlags; + real_num = prEventBuffer->u2NumOfResults; + + DBGLOG(SCN, INFO, "scan_id=%d, scan_flag =%d, real_num=%d\r\n", scan_id, scan_flag, real_num); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num); + if (!skb) { + DBGLOG(RX, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + attr = nla_nest_start(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS); + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_SCAN_ID, scan_id);*/ + { + unsigned int __tmp = scan_id; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_ID, sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, 1);*/ + { + unsigned char __tmp = 1; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_FLAGS, sizeof(u8), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, real_num);*/ + { + unsigned int __tmp = real_num; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_NUM_OF_RESULTS, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + prResults = (P_PARAM_WIFI_GSCAN_RESULT) prEventGscnResult; + if (prResults) + DBGLOG(SCN, INFO, "ssid=%s, rssi=%d, channel=%d \r\n", + prResults->ssid, prResults->rssi, prResults->channel); + /*NLA_PUT(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, sizeof(PARAM_WIFI_GSCAN_RESULT) * real_num, + prResults);*/ + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS, + sizeof(PARAM_WIFI_GSCAN_RESULT)*real_num, prResults) < 0)) + goto nla_put_failure; + + DBGLOG(SCN, INFO, "NLA_PUT scan results over\t"); + + if (attr) + nla_nest_end(skb, attr); + /* report_events=1 */ + /*NLA_PUT_U8(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, 1);*/ + { + unsigned char __tmp = 1; + + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + i4Status = cfg80211_vendor_cmd_reply(skb); + skb = NULL; + DBGLOG(SCN, INFO, " i4Status %d\n", i4Status); + } + break; + + case EVENT_ID_GSCAN_CAPABILITY: + { + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_CAPABILITY\n"); + + prEventGscnCapbiblity = (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer); + memcpy(prEventGscnCapbiblity, (P_EVENT_GSCAN_CAPABILITY_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_CAPABILITY_T)); + + mtk_cfg80211_vendor_get_gscan_capabilities(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, + prEventGscnCapbiblity, sizeof(EVENT_GSCAN_CAPABILITY_T)); + } + break; + + case EVENT_ID_GSCAN_SCAN_COMPLETE: + { + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_SCAN_COMPLETE\n"); + prEventGscnScnDone = (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer); + memcpy(prEventGscnScnDone, (P_EVENT_GSCAN_SCAN_COMPLETE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SCAN_COMPLETE_T)); + + mtk_cfg80211_vendor_event_complete_scan(wiphy, prGlueInfo->prDevHandler->ieee80211_ptr, + prEventGscnScnDone->ucScanState); + } + break; + + case EVENT_ID_GSCAN_FULL_RESULT: + { + DBGLOG(SCN, INFO, "EVENT_ID_GSCAN_FULL_RESULT\n"); + + prEventGscnFullResult = kalMemAlloc(sizeof(WIFI_GSCAN_RESULT_T), VIR_MEM_TYPE); + if (prEventGscnFullResult) + memcpy(prEventGscnFullResult, (P_WIFI_GSCAN_RESULT_T) (prEvent->aucBuffer), + sizeof(WIFI_GSCAN_RESULT_T)); + + prParamGscnFullResult = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_RESULT), VIR_MEM_TYPE); + if (prEventGscnFullResult && prParamGscnFullResult) { + kalMemZero(prParamGscnFullResult, sizeof(PARAM_WIFI_GSCAN_RESULT)); + memcpy(prParamGscnFullResult, prEventGscnFullResult, sizeof(WIFI_GSCAN_RESULT_T)); + + mtk_cfg80211_vendor_event_full_scan_results(wiphy, + prGlueInfo->prDevHandler->ieee80211_ptr, + prParamGscnFullResult, + sizeof(PARAM_WIFI_GSCAN_RESULT)); + } + } + break; + + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + { + prEventGscnSignificantChange = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnSignificantChange, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + { + prEventGscnGeofenceFound = (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer); + memcpy(prEventGscnGeofenceFound, (P_EVENT_GSCAN_SIGNIFICANT_CHANGE_T) (prEvent->aucBuffer), + sizeof(EVENT_GSCAN_SIGNIFICANT_CHANGE_T)); + } + break; + + default: + DBGLOG(SCN, INFO, "not GSCN event ????\n"); + break; + } + + DBGLOG(SCN, INFO, "Done with GSCN event handling\n"); + return real_num; /* cfg80211_vendor_cmd_reply(skb); */ + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + DBGLOG(SCN, INFO, "nla_put_failure\n"); + return 0; /* cfg80211_vendor_cmd_reply(skb); */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process HIF event packet +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessEventPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + P_WIFI_EVENT_T prEvent; + P_GLUE_INFO_T prGlueInfo; + + DEBUGFUNC("nicRxProcessEventPacket"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + prGlueInfo = prAdapter->prGlueInfo; + + DBGLOG(RX, EVENT, "prEvent->ucEID = 0x%02x\n", prEvent->ucEID); + /* Event Handling */ + switch (prEvent->ucEID) { + case EVENT_ID_CMD_RESULT: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + P_EVENT_CMD_RESULT prCmdResult; + + prCmdResult = (P_EVENT_CMD_RESULT) ((PUINT_8) prEvent + EVENT_HDR_SIZE); + + /* CMD_RESULT should be only in response to Set commands */ + ASSERT(prCmdInfo->fgSetQuery == FALSE || prCmdInfo->fgNeedResp == TRUE); + + if (prCmdResult->ucStatus == 0) { /* success */ + if (prCmdInfo->pfCmdDoneHandler) { + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + } else if (prCmdInfo->fgIsOid == TRUE) { + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_SUCCESS); + } + } else if (prCmdResult->ucStatus == 1) { /* reject */ + if (prCmdInfo->fgIsOid == TRUE) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_FAILURE); + } else if (prCmdResult->ucStatus == 2) { /* unknown CMD */ + if (prCmdInfo->fgIsOid == TRUE) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, + WLAN_STATUS_NOT_SUPPORTED); + } + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + +#if 0 + case EVENT_ID_CONNECTION_STATUS: + /* OBSELETE */ + { + P_EVENT_CONNECTION_STATUS prConnectionStatus; + + prConnectionStatus = (P_EVENT_CONNECTION_STATUS) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_CONNECTION_STATUS = %d\n", prConnectionStatus->ucMediaStatus); + if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_DISCONNECTED) { + /* disconnected */ + if (kalGetMediaStateIndicated(prGlueInfo) != PARAM_MEDIA_STATE_DISCONNECTED) { + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_DISCONNECT, NULL, 0); + + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + } + } else if (prConnectionStatus->ucMediaStatus == PARAM_MEDIA_STATE_CONNECTED) { + /* connected */ + prAdapter->rWlanInfo.u4SysTime = kalGetTimeTick(); + + /* fill information for association result */ + prAdapter->rWlanInfo.rCurrBssId.rSsid.u4SsidLen = prConnectionStatus->ucSsidLen; + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.rSsid.aucSsid, + prConnectionStatus->aucSsid, prConnectionStatus->ucSsidLen); + + kalMemCopy(prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + prConnectionStatus->aucBssid, MAC_ADDR_LEN); + + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.u4Privacy = prConnectionStatus->ucEncryptStatus; + prAdapter->rWlanInfo.rCurrBssId.rRssi = 0; /* @FIXME */ + /* @FIXME */ + prAdapter->rWlanInfo.rCurrBssId.eNetworkTypeInUse = PARAM_NETWORK_TYPE_AUTOMODE; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4BeaconPeriod + = prConnectionStatus->u2BeaconPeriod; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4ATIMWindow + = prConnectionStatus->u2ATIMWindow; + prAdapter->rWlanInfo.rCurrBssId.rConfiguration.u4DSConfig + = prConnectionStatus->u4FreqInKHz; + prAdapter->rWlanInfo.ucNetworkType = prConnectionStatus->ucNetworkType; + + switch (prConnectionStatus->ucInfraMode) { + case 0: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_IBSS; + break; + case 1: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_INFRA; + break; + case 2: + default: + prAdapter->rWlanInfo.rCurrBssId.eOpMode = NET_TYPE_AUTO_SWITCH; + break; + } + /* always indicate to OS according to MSDN (re-association/roaming) */ + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_MEDIA_CONNECT, NULL, 0); + } + } + break; + + case EVENT_ID_SCAN_RESULT: + /* OBSELETE */ + break; +#endif + + case EVENT_ID_RX_ADDBA: + /* The FW indicates that an RX BA agreement will be established */ + qmHandleEventRxAddBa(prAdapter, prEvent); + break; + + case EVENT_ID_RX_DELBA: + /* The FW indicates that an RX BA agreement has been deleted */ + qmHandleEventRxDelBa(prAdapter, prEvent); + break; + + case EVENT_ID_LINK_QUALITY: +#if CFG_ENABLE_WIFI_DIRECT && CFG_SUPPORT_P2P_RSSI_QUERY + if (prEvent->u2PacketLen == EVENT_HDR_SIZE + sizeof(EVENT_LINK_QUALITY_EX)) { + P_EVENT_LINK_QUALITY_EX prLqEx = (P_EVENT_LINK_QUALITY_EX) (prEvent->aucBuffer); + + if (prLqEx->ucIsLQ0Rdy) + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY) prLqEx); + if (prLqEx->ucIsLQ1Rdy) + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_P2P_INDEX, (P_EVENT_LINK_QUALITY) prLqEx); + } else { + /* For old FW, P2P may invoke link quality query, and make driver flag becone TRUE. */ + DBGLOG(P2P, WARN, "Old FW version, not support P2P RSSI query.\n"); + + /* Must not use NETWORK_TYPE_P2P_INDEX, cause the structure is mismatch. */ + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, + (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); + } +#else + nicUpdateLinkQuality(prAdapter, NETWORK_TYPE_AIS_INDEX, (P_EVENT_LINK_QUALITY) (prEvent->aucBuffer)); +#endif + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } +#ifndef LINUX + if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_GREATER && + prAdapter->rWlanInfo.rRssiTriggerValue >= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(PARAM_RSSI)); + } else if (prAdapter->rWlanInfo.eRssiTriggerType == ENUM_RSSI_TRIGGER_LESS + && prAdapter->rWlanInfo.rRssiTriggerValue <= (PARAM_RSSI) (prAdapter->rLinkQuality.cRssi)) { + prAdapter->rWlanInfo.eRssiTriggerType = ENUM_RSSI_TRIGGER_TRIGGERED; + + kalIndicateStatusAndComplete(prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID)&(prAdapter->rWlanInfo.rRssiTriggerValue), + sizeof(PARAM_RSSI)); + } +#endif + + break; + + case EVENT_ID_MIC_ERR_INFO: + { + P_EVENT_MIC_ERR_INFO prMicError; + /* P_PARAM_AUTH_EVENT_T prAuthEvent; */ + P_STA_RECORD_T prStaRec; + + DBGLOG(RSN, EVENT, "EVENT_ID_MIC_ERR_INFO\n"); + + prMicError = (P_EVENT_MIC_ERR_INFO) (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByAddress(prAdapter, + (UINT_8) NETWORK_TYPE_AIS_INDEX, + prAdapter->rWlanInfo.rCurrBssId.arMacAddress); + ASSERT(prStaRec); + + if (prStaRec) + rsnTkipHandleMICFailure(prAdapter, prStaRec, (BOOLEAN) prMicError->u4Flags); + else + DBGLOG(RSN, WARN, "No STA rec!!\n"); +#if 0 + prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; + + /* Status type: Authentication Event */ + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_AUTHENTICATION; + + /* Authentication request */ + prAuthEvent->arRequest[0].u4Length = sizeof(PARAM_AUTH_REQUEST_T); + kalMemCopy((PVOID) prAuthEvent->arRequest[0].arBssid, + (PVOID) prAdapter->rWlanInfo.rCurrBssId.arMacAddress, + /* whsu:Todo? */PARAM_MAC_ADDR_LEN); + + if (prMicError->u4Flags != 0) + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_GROUP_ERROR; + else + prAuthEvent->arRequest[0].u4Flags = PARAM_AUTH_REQUEST_PAIRWISE_ERROR; + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + sizeof(PARAM_AUTH_REQUEST_T)); +#endif + } + break; + + case EVENT_ID_ASSOC_INFO: + { + P_EVENT_ASSOC_INFO prAssocInfo; + + prAssocInfo = (P_EVENT_ASSOC_INFO) (prEvent->aucBuffer); + + kalHandleAssocInfo(prAdapter->prGlueInfo, prAssocInfo); + } + break; + + case EVENT_ID_802_11_PMKID: + { + P_PARAM_AUTH_EVENT_T prAuthEvent; + PUINT_8 cp; + UINT_32 u4LenOfUsedBuffer; + + prAuthEvent = (P_PARAM_AUTH_EVENT_T) prAdapter->aucIndicationEventBuffer; + + prAuthEvent->rStatus.eStatusType = ENUM_STATUS_TYPE_CANDIDATE_LIST; + + u4LenOfUsedBuffer = (UINT_32) (prEvent->u2PacketLen - 8); + + prAuthEvent->arRequest[0].u4Length = u4LenOfUsedBuffer; + + cp = (PUINT_8) &prAuthEvent->arRequest[0]; + + /* Status type: PMKID Candidatelist Event */ + kalMemCopy(cp, (P_EVENT_PMKID_CANDIDATE_LIST_T) (prEvent->aucBuffer), prEvent->u2PacketLen - 8); + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_MEDIA_SPECIFIC_INDICATION, + (PVOID) prAuthEvent, + sizeof(PARAM_STATUS_INDICATION_T) + u4LenOfUsedBuffer); + } + break; + +#if 0 + case EVENT_ID_ACTIVATE_STA_REC_T: + { + P_EVENT_ACTIVATE_STA_REC_T prActivateStaRec; + + prActivateStaRec = (P_EVENT_ACTIVATE_STA_REC_T) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_ACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", + prActivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); + + qmActivateStaRec(prAdapter, + (UINT_32) prActivateStaRec->ucStaRecIdx, + ((prActivateStaRec->fgIsQoS) ? TRUE : FALSE), + prActivateStaRec->ucNetworkTypeIndex, + ((prActivateStaRec->fgIsAP) ? TRUE : FALSE), prActivateStaRec->aucMacAddr); + + } + break; + + case EVENT_ID_DEACTIVATE_STA_REC_T: + { + P_EVENT_DEACTIVATE_STA_REC_T prDeactivateStaRec; + + prDeactivateStaRec = (P_EVENT_DEACTIVATE_STA_REC_T) (prEvent->aucBuffer); + + DbgPrint("RX EVENT: EVENT_ID_DEACTIVATE_STA_REC_T Index:%d, MAC:[%pM]\n", + prDeactivateStaRec->ucStaRecIdx, prActivateStaRec->aucMacAddr); + + qmDeactivateStaRec(prAdapter, prDeactivateStaRec->ucStaRecIdx); + } + break; +#endif + + case EVENT_ID_SCAN_DONE: + scnEventScanDone(prAdapter, (P_EVENT_SCAN_DONE) (prEvent->aucBuffer)); + break; + + case EVENT_ID_TX_DONE_STATUS: + STATS_TX_PKT_DONE_INFO_DISPLAY(prAdapter, prEvent->aucBuffer); + break; + + case EVENT_ID_TX_DONE: + { + P_EVENT_TX_DONE_T prTxDone; + + prTxDone = (P_EVENT_TX_DONE_T) (prEvent->aucBuffer); + if (prTxDone->ucStatus) + DBGLOG(RX, INFO, "EVENT_ID_TX_DONE PacketSeq:%u ucStatus: %u SN: %u\n", + prTxDone->ucPacketSeq, prTxDone->ucStatus, prTxDone->u2SequenceNumber); + + /* call related TX Done Handler */ + prMsduInfo = nicGetPendingTxMsduInfo(prAdapter, prTxDone->ucPacketSeq); + +#if CFG_SUPPORT_802_11V_TIMING_MEASUREMENT + DBGLOG(RX, TRACE, "EVENT_ID_TX_DONE u4TimeStamp = %x u2AirDelay = %x\n", + prTxDone->au4Reserved1, prTxDone->au4Reserved2); + + wnmReportTimingMeas(prAdapter, prMsduInfo->ucStaRecIndex, + prTxDone->au4Reserved1, prTxDone->au4Reserved1 + prTxDone->au4Reserved2); +#endif + + if (prMsduInfo) { + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, + (ENUM_TX_RESULT_CODE_T) (prTxDone->ucStatus)); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } + } + break; + case EVENT_ID_SLEEPY_NOTIFY: + { + P_EVENT_SLEEPY_NOTIFY prEventSleepyNotify; + + prEventSleepyNotify = (P_EVENT_SLEEPY_NOTIFY) (prEvent->aucBuffer); + + /* DBGLOG(RX, INFO, ("ucSleepyState = %d\n", prEventSleepyNotify->ucSleepyState)); */ + + prAdapter->fgWiFiInSleepyState = (BOOLEAN) (prEventSleepyNotify->ucSleepyState); + } + break; + case EVENT_ID_BT_OVER_WIFI: +#if CFG_ENABLE_BT_OVER_WIFI + { + UINT_8 aucTmp[sizeof(AMPC_EVENT) + sizeof(BOW_LINK_DISCONNECTED)]; + P_EVENT_BT_OVER_WIFI prEventBtOverWifi; + P_AMPC_EVENT prBowEvent; + P_BOW_LINK_CONNECTED prBowLinkConnected; + P_BOW_LINK_DISCONNECTED prBowLinkDisconnected; + + prEventBtOverWifi = (P_EVENT_BT_OVER_WIFI) (prEvent->aucBuffer); + + /* construct event header */ + prBowEvent = (P_AMPC_EVENT) aucTmp; + + if (prEventBtOverWifi->ucLinkStatus == 0) { + /* Connection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_CONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_CONNECTED); + + /* fill event body */ + prBowLinkConnected = (P_BOW_LINK_CONNECTED) (prBowEvent->aucPayload); + prBowLinkConnected->rChannel.ucChannelNum = prEventBtOverWifi->ucSelectedChannel; + kalMemZero(prBowLinkConnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } else { + /* Disconnection */ + prBowEvent->rHeader.ucEventId = BOW_EVENT_ID_LINK_DISCONNECTED; + prBowEvent->rHeader.ucSeqNumber = 0; + prBowEvent->rHeader.u2PayloadLength = sizeof(BOW_LINK_DISCONNECTED); + + /* fill event body */ + prBowLinkDisconnected = (P_BOW_LINK_DISCONNECTED) (prBowEvent->aucPayload); + prBowLinkDisconnected->ucReason = 0; /* @FIXME */ + kalMemZero(prBowLinkDisconnected->aucPeerAddress, MAC_ADDR_LEN); /* @FIXME */ + + kalIndicateBOWEvent(prAdapter->prGlueInfo, prBowEvent); + } + } + break; +#endif + case EVENT_ID_STATISTICS: + /* buffer statistics for further query */ + prAdapter->fgIsStatValid = TRUE; + prAdapter->rStatUpdateTime = kalGetTimeTick(); + kalMemCopy(&prAdapter->rStatStruct, prEvent->aucBuffer, sizeof(EVENT_STATISTICS)); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + + case EVENT_ID_CH_PRIVILEGE: + cnmChMngrHandleChEvent(prAdapter, prEvent); + break; + + case EVENT_ID_BSS_ABSENCE_PRESENCE: + qmHandleEventBssAbsencePresence(prAdapter, prEvent); + break; + + case EVENT_ID_STA_CHANGE_PS_MODE: + qmHandleEventStaChangePsMode(prAdapter, prEvent); + break; +#if CFG_ENABLE_WIFI_DIRECT + case EVENT_ID_STA_UPDATE_FREE_QUOTA: + qmHandleEventStaUpdateFreeQuota(prAdapter, prEvent); + break; +#endif + case EVENT_ID_BSS_BEACON_TIMEOUT: + if (prAdapter->fgDisBcnLostDetection == FALSE) { + P_EVENT_BSS_BEACON_TIMEOUT_T prEventBssBeaconTimeout; + + prEventBssBeaconTimeout = (P_EVENT_BSS_BEACON_TIMEOUT_T) (prEvent->aucBuffer); + + DBGLOG(RX, INFO, "Beacon Timeout Reason = %u\n", prEventBssBeaconTimeout->ucReason); + + if (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_AIS_INDEX) { + /* Request stats report before beacon timeout */ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (prBssInfo) { + prStaRec = cnmGetStaRecByAddress(prAdapter, + NETWORK_TYPE_AIS_INDEX, + prBssInfo->aucBSSID); + if (prStaRec) + STATS_ENV_REPORT_DETECT(prAdapter, prStaRec->ucIndex); + } + aisBssBeaconTimeout(prAdapter); + } +#if CFG_ENABLE_WIFI_DIRECT + else if ((prAdapter->fgIsP2PRegistered) && + (prEventBssBeaconTimeout->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX)) + + p2pFsmRunEventBeaconTimeout(prAdapter); +#endif + else { + DBGLOG(RX, ERROR, "EVENT_ID_BSS_BEACON_TIMEOUT: (ucNetTypeIdx = %d)\n", + prEventBssBeaconTimeout->ucNetTypeIndex); + } + } + + break; + case EVENT_ID_UPDATE_NOA_PARAMS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) { + P_EVENT_UPDATE_NOA_PARAMS_T prEventUpdateNoaParam; + + prEventUpdateNoaParam = (P_EVENT_UPDATE_NOA_PARAMS_T) (prEvent->aucBuffer); + + if (prEventUpdateNoaParam->ucNetTypeIndex == NETWORK_TYPE_P2P_INDEX) { + p2pProcessEvent_UpdateNOAParam(prAdapter, + prEventUpdateNoaParam->ucNetTypeIndex, + prEventUpdateNoaParam); + } else { + ASSERT(0); + } + } +#else + ASSERT(0); +#endif + break; + + case EVENT_ID_STA_AGING_TIMEOUT: +#if CFG_ENABLE_WIFI_DIRECT + { + if (prAdapter->fgDisStaAgingTimeoutDetection == FALSE) { + P_EVENT_STA_AGING_TIMEOUT_T prEventStaAgingTimeout; + P_STA_RECORD_T prStaRec; + P_BSS_INFO_T prBssInfo = (P_BSS_INFO_T) NULL; + + prEventStaAgingTimeout = (P_EVENT_STA_AGING_TIMEOUT_T) (prEvent->aucBuffer); + prStaRec = cnmGetStaRecByIndex(prAdapter, prEventStaAgingTimeout->ucStaRecIdx); + if (prStaRec == NULL) + break; + + DBGLOG(RX, INFO, "EVENT_ID_STA_AGING_TIMEOUT %u %pM\n", + prEventStaAgingTimeout->ucStaRecIdx, + prStaRec->aucMacAddr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + bssRemoveStaRecFromClientList(prAdapter, prBssInfo, prStaRec); + + /* Call False Auth */ + if (prAdapter->fgIsP2PRegistered) + p2pFuncDisconnect(prAdapter, prStaRec, TRUE, REASON_CODE_DISASSOC_INACTIVITY); + + } + /* gDisStaAgingTimeoutDetection */ + } +#endif + break; + + case EVENT_ID_AP_OBSS_STATUS: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmHandleObssStatusEventPkt(prAdapter, (P_EVENT_AP_OBSS_STATUS_T) prEvent->aucBuffer); +#endif + break; + + case EVENT_ID_ROAMING_STATUS: +#if CFG_SUPPORT_ROAMING + { + P_ROAMING_PARAM_T prParam; + + prParam = (P_ROAMING_PARAM_T) (prEvent->aucBuffer); + roamingFsmProcessEvent(prAdapter, prParam); + } +#endif /* CFG_SUPPORT_ROAMING */ + break; + case EVENT_ID_SEND_DEAUTH: + { + P_WLAN_MAC_HEADER_T prWlanMacHeader; + P_STA_RECORD_T prStaRec; + + prWlanMacHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + DBGLOG(RSN, INFO, "nicRx: aucAddr1: %pM, nicRx: aucAddr2: %pM\n", + prWlanMacHeader->aucAddr1, prWlanMacHeader->aucAddr2); + prStaRec = cnmGetStaRecByAddress(prAdapter, NETWORK_TYPE_AIS_INDEX, prWlanMacHeader->aucAddr2); + if (prStaRec != NULL && prStaRec->ucStaState == STA_STATE_3) { + DBGLOG(RSN, WARN, "Ignore Deauth for Rx Class 3 error!\n"); + } else { + /* receive packets without StaRec */ + prSwRfb->pvHeader = (P_WLAN_MAC_HEADER_T) &prEvent->aucBuffer[0]; + if (WLAN_STATUS_SUCCESS == authSendDeauthFrame(prAdapter, + NULL, + prSwRfb, + REASON_CODE_CLASS_3_ERR, + (PFN_TX_DONE_HANDLER) NULL)) + DBGLOG(RSN, INFO, "Send Deauth for Rx Class3 Error\n"); + else + DBGLOG(RSN, WARN, "failed to send deauth for Rx class3 error\n"); + } + } + break; + +#if CFG_SUPPORT_RDD_TEST_MODE + case EVENT_ID_UPDATE_RDD_STATUS: + { + P_EVENT_RDD_STATUS_T prEventRddStatus; + + prEventRddStatus = (P_EVENT_RDD_STATUS_T) (prEvent->aucBuffer); + + prAdapter->ucRddStatus = prEventRddStatus->ucRddStatus; + } + + break; +#endif + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case EVENT_ID_UPDATE_BWCS_STATUS: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, INFO, + "BCM BWCS Event: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); + + DBGLOG(RSN, INFO, + "BCM BWCS Event: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); +#endif + + kalIndicateStatusAndComplete(prAdapter->prGlueInfo, + WLAN_STATUS_BWCS_UPDATE, + (PVOID) prEventBwcsStatus, sizeof(PTA_IPC_T)); + } + + break; + + case EVENT_ID_UPDATE_BCM_DEBUG: + { + P_PTA_IPC_T prEventBwcsStatus; + + prEventBwcsStatus = (P_PTA_IPC_T) (prEvent->aucBuffer); + +#if CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(RSN, INFO, + "BCM FW status: %02x%02x%02x%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]); + + DBGLOG(RSN, INFO, + "BCM FW status: BTPParams[0]:%02x, BTPParams[1]:%02x, BTPParams[2]:%02x, BTPParams[3]:%02x\n", + prEventBwcsStatus->u.aucBTPParams[0], prEventBwcsStatus->u.aucBTPParams[1], + prEventBwcsStatus->u.aucBTPParams[2], prEventBwcsStatus->u.aucBTPParams[3]; +#endif + } + + break; +#endif + + case EVENT_ID_DEBUG_CODE: /* only for debug */ + { + UINT_32 u4CodeId; + + DBGLOG(RSN, INFO, "[wlan-fw] function sequence: "); + for (u4CodeId = 0; u4CodeId < 1000; u4CodeId++) + DBGLOG(RSN, INFO, "%d ", prEvent->aucBuffer[u4CodeId]); + DBGLOG(RSN, INFO, "\n\n"); + } + break; + + case EVENT_ID_RFTEST_READY: + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + + case EVENT_ID_GSCAN_SCAN_AVAILABLE: + case EVENT_ID_GSCAN_CAPABILITY: + case EVENT_ID_GSCAN_SCAN_COMPLETE: + case EVENT_ID_GSCAN_FULL_RESULT: + case EVENT_ID_GSCAN_SIGNIFICANT_CHANGE: + case EVENT_ID_GSCAN_GEOFENCE_FOUND: + nicRxProcessGSCNEvent(prAdapter, prSwRfb); + break; + + case EVENT_ID_GSCAN_RESULT: + { + + UINT_8 realnum = 0; + + DBGLOG(SCN, TRACE, "nicRxProcessGSCNEvent ----->\n"); + realnum = nicRxProcessGSCNEvent(prAdapter, prSwRfb); + DBGLOG(SCN, TRACE, "nicRxProcessGSCNEvent <-----\n"); + +#if 0 /* workaround for FW events cnt mis-match with the actual reqirements from wifi_hal */ + if (g_GetResultsCmdCnt == 0) { + DBGLOG(SCN, INFO, + "FW report events more than the wifi_hal asked number, buffer the results\n"); + UINT_8 i = 0; + + for (i = 0; i < MAX_BUFFERED_GSCN_RESULTS; i++) { +#if 1 + if (!g_arGscanResultsIndicateNumber[i]) { + DBGLOG(SCN, INFO, + "found available index %d to insert results number %d into buffer\r\n", + i, realnum); + + g_arGscnResultsTempBuffer[i] = prSwRfb; + g_arGscanResultsIndicateNumber[i] = realnum; + g_GetResultsBufferedCnt++; + fgKeepprSwRfb = TRUE; + DBGLOG(SCN, INFO, "results buffered in index[%d] \r\n", i); + break; + } +#endif + } + if (i == MAX_BUFFERED_GSCN_RESULTS) + DBGLOG(SCN, INFO, + "Gscn results buffer is full(all valid), no space to buffer result\r\n"); + } else if (g_GetResultsCmdCnt > 0) { + DBGLOG(SCN, INFO, "FW report events match the wifi_hal asked number\n"); + g_GetResultsCmdCnt--; + } else + DBGLOG(SCN, INFO, "g_GetResultsCmdCnt < 0 ??? unexpected case\n"); +#endif + /* end of workaround */ + + } + break; + + case EVENT_ID_NLO_DONE: + prAdapter->rWifiVar.rScanInfo.fgPscnOnnning = FALSE; + + DBGLOG(INIT, INFO, "EVENT_ID_NLO_DONE\n"); + scnEventNloDone(prAdapter, (P_EVENT_NLO_DONE_T) (prEvent->aucBuffer)); + + break; + +#if CFG_SUPPORT_BATCH_SCAN + case EVENT_ID_BATCH_RESULT: + DBGLOG(SCN, TRACE, "Got EVENT_ID_BATCH_RESULT"); + + /* command response handling */ + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; +#endif /* CFG_SUPPORT_BATCH_SCAN */ + +#if (CFG_SUPPORT_TDLS == 1) + case EVENT_ID_TDLS: + TdlsexEventHandle(prAdapter->prGlueInfo, + (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); + break; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_STATISTICS == 1) + case EVENT_ID_STATS_ENV: + statsEventHandle(prAdapter->prGlueInfo, + (UINT8 *) prEvent->aucBuffer, (UINT32) (prEvent->u2PacketLen - 8)); + break; +#endif /* CFG_SUPPORT_STATISTICS */ + + case EVENT_ID_FW_LOG_ENV: + { + P_EVENT_FW_LOG_T prEventLog; + + prEventLog = (P_EVENT_FW_LOG_T) (prEvent->aucBuffer); + DBGLOG(RX, INFO, "[F-L]%s\n", prEventLog->log); + } + break; + + default: + prCmdInfo = nicGetPendingCmdInfo(prAdapter, prEvent->ucSeqNum); + + if (prCmdInfo != NULL) { + if (prCmdInfo->pfCmdDoneHandler) + prCmdInfo->pfCmdDoneHandler(prAdapter, prCmdInfo, prEvent->aucBuffer); + else if (prCmdInfo->fgIsOid) + kalOidComplete(prAdapter->prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_SUCCESS); + /* return prCmdInfo */ + cmdBufFreeCmdInfo(prAdapter, prCmdInfo); + } + + break; + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicRxProcessMgmtPacket is used to dispatch management frames +* to corresponding modules +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSWRfb the RFB to receive rx data +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessMgmtPacket(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + UINT_8 ucSubtype; +#if CFG_SUPPORT_802_11W + BOOLEAN fgMfgDrop = FALSE; +#endif + ASSERT(prAdapter); + ASSERT(prSwRfb); + + nicRxFillRFB(prAdapter, prSwRfb); + + ucSubtype = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FC_SUBTYPE) >> OFFSET_OF_FC_SUBTYPE; + +#if 0 /* CFG_RX_PKTS_DUMP */ + { + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2TxFrameCtrl; + + prHifRxHdr = prSwRfb->prHifRxHdr; + u2TxFrameCtrl = (*(PUINT_8) (prSwRfb->pvHeader) & MASK_FRAME_TYPE); + /* if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_MANAGEMENT)) { */ + /* if (u2TxFrameCtrl == MAC_FRAME_BEACON || */ + /* u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { */ + + DBGLOG(RX, INFO, "QM RX MGT: net %u sta idx %u wlan idx %u ssn %u ptype %u subtype %u 11 %u\n", + (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), prHifRxHdr->ucStaRecIdx, + prSwRfb->ucWlanIdx, (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr),/* The new SN of the frame */ + prSwRfb->ucPacketType, ucSubtype, HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); + + /* DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prSwRfb->pvHeader, prSwRfb->u2PacketLen); */ + /* } */ + /* } */ + } +#endif + + if ((prAdapter->fgTestMode == FALSE) && (prAdapter->prGlueInfo->fgIsRegistered == TRUE)) { +#if CFG_MGMT_FRAME_HANDLING +#if CFG_SUPPORT_802_11W + fgMfgDrop = rsnCheckRxMgmt(prAdapter, prSwRfb, ucSubtype); + if (fgMfgDrop) { +#if DBG + LOG_FUNC("QM RX MGT: Drop Unprotected Mgmt frame!!!\n"); +#endif + nicRxReturnRFB(prAdapter, prSwRfb); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + return; + } +#endif + if (apfnProcessRxMgtFrame[ucSubtype]) { + switch (apfnProcessRxMgtFrame[ucSubtype] (prAdapter, prSwRfb)) { + case WLAN_STATUS_PENDING: + return; + case WLAN_STATUS_SUCCESS: + case WLAN_STATUS_FAILURE: + break; + + default: + DBGLOG(RX, WARN, + "Unexpected MMPDU(0x%02X) returned with abnormal status\n", ucSubtype); + break; + } + } +#endif + } + + nicRxReturnRFB(prAdapter, prSwRfb); +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +static VOID nicRxCheckWakeupReason(P_SW_RFB_T prSwRfb) +{ + PUINT_8 pvHeader = NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_16 u2PktLen = 0; + UINT_32 u4HeaderOffset; + + if (!prSwRfb) + return; + prHifRxHdr = prSwRfb->prHifRxHdr; + if (!prHifRxHdr) + return; + + switch (prSwRfb->ucPacketType) { + case HIF_RX_PKT_TYPE_DATA: + { + UINT_16 u2Temp = 0; + + if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { + DBGLOG(RX, INFO, "BAR frame[SSN:%d, TID:%d] wakeup host\n", + (UINT_16)HIF_RX_HDR_GET_SN(prHifRxHdr), (UINT_8)HIF_RX_HDR_GET_TID(prHifRxHdr)); + break; + } + u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + u2PktLen = (UINT_16)(prHifRxHdr->u2PacketLen - (HIF_RX_HDR_SIZE + u4HeaderOffset)); + if (!pvHeader) { + DBGLOG(RX, ERROR, "data packet but pvHeader is NULL!\n"); + break; + } + u2Temp = (pvHeader[ETH_TYPE_LEN_OFFSET] << 8) | (pvHeader[ETH_TYPE_LEN_OFFSET + 1]); + + switch (u2Temp) { + case ETH_P_IPV4: + u2Temp = *(UINT_16 *) &pvHeader[ETH_HLEN + 4]; + DBGLOG(RX, INFO, "IP Packet from:%d.%d.%d.%d, IP ID 0x%04x wakeup host\n", + pvHeader[ETH_HLEN + 12], pvHeader[ETH_HLEN + 13], + pvHeader[ETH_HLEN + 14], pvHeader[ETH_HLEN + 15], u2Temp); + break; + case ETH_P_ARP: + { + PUINT_8 pucEthBody = &pvHeader[ETH_HLEN]; + UINT_16 u2OpCode = (pucEthBody[6] << 8) | pucEthBody[7]; + + if (u2OpCode == ARP_PRO_REQ) + DBGLOG(RX, INFO, "Arp Req From IP: %d.%d.%d.%d wakeup host\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + else if (u2OpCode == ARP_PRO_RSP) + DBGLOG(RX, INFO, "Arp Rsp from IP: %d.%d.%d.%d wakeup host\n", + pucEthBody[14], pucEthBody[15], pucEthBody[16], pucEthBody[17]); + break; + } + case ETH_P_1X: + case ETH_P_PRE_1X: +#if CFG_SUPPORT_WAPI + case ETH_WPI_1X: +#endif + case ETH_P_AARP: + case ETH_P_IPV6: + case ETH_P_IPX: + case 0x8100: /* VLAN */ + case 0x890d: /* TDLS */ + DBGLOG(RX, INFO, "Data Packet, EthType 0x%04x wakeup host\n", u2Temp); + break; + default: + DBGLOG(RX, WARN, "maybe abnormal data packet, EthType 0x%04x wakeup host, dump it\n", + u2Temp); + DBGLOG_MEM8(RX, INFO, pvHeader, u2PktLen > 50 ? 50:u2PacketLen); + break; + } + break; + } + case HIF_RX_PKT_TYPE_EVENT: + { + P_WIFI_EVENT_T prEvent = (P_WIFI_EVENT_T) prSwRfb->pucRecvBuff; + + DBGLOG(RX, INFO, "Event 0x%02x wakeup host\n", prEvent->ucEID); + break; + } + case HIF_RX_PKT_TYPE_MANAGEMENT: + { + UINT_8 ucSubtype; + P_WLAN_MAC_MGMT_HEADER_T prWlanMgmtHeader; + + u4HeaderOffset = (UINT_32)(prHifRxHdr->ucHerderLenOffset & HIF_RX_HDR_HEADER_OFFSET_MASK); + pvHeader = (PUINT_8)prHifRxHdr + HIF_RX_HDR_SIZE + u4HeaderOffset; + if (!pvHeader) { + DBGLOG(RX, ERROR, "Mgmt Frame but pvHeader is NULL!\n"); + break; + } + prWlanMgmtHeader = (P_WLAN_MAC_MGMT_HEADER_T)pvHeader; + ucSubtype = (prWlanMgmtHeader->u2FrameCtrl & MASK_FC_SUBTYPE) >> + OFFSET_OF_FC_SUBTYPE; + DBGLOG(RX, INFO, "MGMT frame subtype: %d SeqCtrl %d wakeup host\n", + ucSubtype, prWlanMgmtHeader->u2SeqCtrl); + break; + } + default: + DBGLOG(RX, WARN, "Unknown Packet %d wakeup host\n", prSwRfb->ucPacketType); + break; + } +} +#endif +/*----------------------------------------------------------------------------*/ +/*! +* @brief nicProcessRFBs is used to process RFBs in the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxProcessRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxProcessRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + prRxCtrl->ucNumIndPacket = 0; + prRxCtrl->ucNumRetainedPacket = 0; + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rReceivedRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb) { +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG + if (kalIsWakeupByWlan(prAdapter)) + nicRxCheckWakeupReason(prSwRfb); +#endif + switch (prSwRfb->ucPacketType) { + case HIF_RX_PKT_TYPE_DATA: + nicRxProcessDataPacket(prAdapter, prSwRfb); + break; + + case HIF_RX_PKT_TYPE_EVENT: + nicRxProcessEventPacket(prAdapter, prSwRfb); + break; + + case HIF_RX_PKT_TYPE_TX_LOOPBACK: +#if (CONF_HIF_LOOPBACK_AUTO == 1) + { + kalDevLoopbkRxHandle(prAdapter, prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + } +#else + DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); +#endif /* CONF_HIF_LOOPBACK_AUTO */ + break; + + case HIF_RX_PKT_TYPE_MANAGEMENT: + nicRxProcessMgmtPacket(prAdapter, prSwRfb); + break; + + default: + RX_INC_CNT(prRxCtrl, RX_TYPE_ERR_DROP_COUNT); + RX_INC_CNT(prRxCtrl, RX_DROP_TOTAL_COUNT); + DBGLOG(RX, ERROR, "ucPacketType = %d\n", prSwRfb->ucPacketType); + nicRxReturnRFB(prAdapter, prSwRfb); /* need to free it */ + break; + } + } else { + break; + } + } while (TRUE); + + if (prRxCtrl->ucNumIndPacket > 0) { + RX_ADD_CNT(prRxCtrl, RX_DATA_INDICATION_COUNT, prRxCtrl->ucNumIndPacket); + RX_ADD_CNT(prRxCtrl, RX_DATA_RETAINED_COUNT, prRxCtrl->ucNumRetainedPacket); + + /* DBGLOG(RX, INFO, ("%d packets indicated, Retained cnt = %d\n", */ + /* prRxCtrl->ucNumIndPacket, prRxCtrl->ucNumRetainedPacket)); */ +#if CFG_NATIVE_802_11 + kalRxIndicatePkts(prAdapter->prGlueInfo, (UINT_32) prRxCtrl->ucNumIndPacket, + (UINT_32) prRxCtrl->ucNumRetainedPacket); +#else + kalRxIndicatePkts(prAdapter->prGlueInfo, prRxCtrl->apvIndPacket, (UINT_32) prRxCtrl->ucNumIndPacket); +#endif + } + +} /* end of nicRxProcessRFBs() */ + +#if !CFG_SDIO_INTR_ENHANCE +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the rx data from data port and setup RFB +* +* @param prAdapter pointer to the Adapter handler +* @param prSWRfb the RFB to receive rx data +* +* @retval WLAN_STATUS_SUCCESS: SUCCESS +* @retval WLAN_STATUS_FAILURE: FAILURE +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxReadBuffer(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0, u4ReadBytes; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOLEAN fgResult = TRUE; + UINT_32 u4RegValue; + UINT_32 rxNum; + + DEBUGFUNC("nicRxReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(pucBuf); + DBGLOG(RX, TRACE, "pucBuf= 0x%x, prHifRxHdr= 0x%x\n", pucBuf, prHifRxHdr); + + do { + /* Read the RFB DW length and packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4RegValue); + if (!fgResult) { + DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); + return WLAN_STATUS_FAILURE; + } + /* 20091021 move the line to get the HIF RX header (for RX0/1) */ + if (u4RegValue == 0) { + DBGLOG(RX, ERROR, "No RX packet\n"); + return WLAN_STATUS_FAILURE; + } + + u4PktLen = u4RegValue & BITS(0, 15); + if (u4PktLen != 0) { + rxNum = 0; + } else { + rxNum = 1; + u4PktLen = (u4RegValue & BITS(16, 31)) >> 16; + } + + DBGLOG(RX, TRACE, "RX%d: u4PktLen = %d\n", rxNum, u4PktLen); + + /* 4 <4> Read Entire RFB and packet, include HW appended DW (Checksum Status) */ + u4ReadBytes = ALIGN_4(u4PktLen) + 4; + HAL_READ_RX_PORT(prAdapter, rxNum, u4ReadBytes, pucBuf, CFG_RX_MAX_PKT_SIZE); + + /* 20091021 move the line to get the HIF RX header */ + /* u4PktLen = (UINT_32)prHifRxHdr->u2PacketLen; */ + if (u4PktLen != (UINT_32) prHifRxHdr->u2PacketLen) { + DBGLOG(RX, ERROR, "Read u4PktLen = %d, prHifRxHdr->u2PacketLen: %d\n", + u4PktLen, prHifRxHdr->u2PacketLen); +#if DBG + dumpMemory8((PUINT_8) prHifRxHdr, + (prHifRxHdr->u2PacketLen > 4096) ? 4096 : prHifRxHdr->u2PacketLen); +#endif + ASSERT(0); + } + /* u4PktLen is byte unit, not inlude HW appended DW */ + + prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + DBGLOG(RX, TRACE, "ucPacketType = %d\n", prSwRfb->ucPacketType); + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + /* fgResult will be updated in MACRO */ + if (!fgResult) + return WLAN_STATUS_FAILURE; + + DBGLOG(RX, TRACE, "Dump RX buffer, length = 0x%x\n", u4ReadBytes); + DBGLOG_MEM8(RX, TRACE, pucBuf, u4ReadBytes); + } while (FALSE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + P_HIF_RX_HEADER_T prHifRxHdr; + + UINT_32 u4HwAppendDW; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxReceiveRFBs"); + + ASSERT(prAdapter); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + /* need to consider */ + if (nicRxReadBuffer(prAdapter, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "halRxFillRFB failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + prHifRxHdr = prSwRfb->prHifRxHdr; + u4HwAppendDW = *((PUINT_32) ((ULONG) prHifRxHdr + (UINT_32) (ALIGN_4(prHifRxHdr->u2PacketLen)))); + DBGLOG(RX, TRACE, "u4HwAppendDW = 0x%x\n", u4HwAppendDW); + DBGLOG(RX, TRACE, "u2PacketLen = 0x%x\n", prHifRxHdr->u2PacketLen); + } while (FALSE); /* while (RX_STATUS_TEST_MORE_FLAG(u4HwAppendDW)); */ + + return; + +} /* end of nicReceiveRFBs() */ + +#else +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port, fill RFB +* and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* @param u4DataPort Specify which port to read +* @param u2RxLength Specify to the the rx packet length in Byte. +* @param prSwRfb the RFB to receive rx data. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS +nicRxEnhanceReadBuffer(IN P_ADAPTER_T prAdapter, + IN UINT_32 u4DataPort, IN UINT_16 u2RxLength, IN OUT P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucBuf; + P_HIF_RX_HEADER_T prHifRxHdr; + UINT_32 u4PktLen = 0; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + BOOLEAN fgResult = TRUE; + + DEBUGFUNC("nicRxEnhanceReadBuffer"); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + pucBuf = prSwRfb->pucRecvBuff; + ASSERT(pucBuf); + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + /* DBGLOG(RX, TRACE, ("u2RxLength = %d\n", u2RxLength)); */ + + do { + /* 4 <1> Read RFB frame from MCR_WRDR0, include HW appended DW */ + HAL_READ_RX_PORT(prAdapter, + u4DataPort, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN), pucBuf, CFG_RX_MAX_PKT_SIZE); + + if (!fgResult) { + DBGLOG(RX, ERROR, "Read RX Packet Lentgh Error\n"); + break; + } + + u4PktLen = (UINT_32) (prHifRxHdr->u2PacketLen); + /* DBGLOG(RX, TRACE, ("u4PktLen = %d\n", u4PktLen)); */ + + prSwRfb->ucPacketType = (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + /* 4 <2> if the RFB dw size or packet size is zero */ + if (u4PktLen == 0) { + DBGLOG(RX, ERROR, "Packet Length = %u\n", u4PktLen); + ASSERT(0); + break; + } + /* 4 <3> if the packet is too large or too small */ + if (u4PktLen > CFG_RX_MAX_PKT_SIZE) { + DBGLOG(RX, TRACE, "Read RX Packet Lentgh Error (%u)\n", u4PktLen); + ASSERT(0); + break; + } + + u4Status = WLAN_STATUS_SUCCESS; + } while (FALSE); + + DBGLOG_MEM8(RX, TRACE, pucBuf, ALIGN_4(u2RxLength + HIF_RX_HW_APPENDED_LEN)); + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_SDIO_CTRL_T prSDIOCtrl; + P_RX_CTRL_T prRxCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 i, rxNum; + UINT_16 u2RxPktNum, u2RxLength = 0, u2Tmp = 0; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOReceiveRFBs"); + + ASSERT(prAdapter); + + prSDIOCtrl = prAdapter->prSDIOCtrl; + ASSERT(prSDIOCtrl); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == 0 ? prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len : prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len); + + if (u2RxPktNum == 0) + continue; + + for (i = 0; i < u2RxPktNum; i++) { + if (rxNum == 0) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2RxLength, &u2Tmp); + } else if (rxNum == 1) { + /* HAL_READ_RX_LENGTH */ + HAL_READ_RX_LENGTH(prAdapter, &u2Tmp, &u2RxLength); + } + + if (!u2RxLength) + break; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (!prSwRfb) { + DBGLOG(RX, TRACE, "No More RFB\n"); + break; + } + ASSERT(prSwRfb); + + if (nicRxEnhanceReadBuffer(prAdapter, rxNum, u2RxLength, prSwRfb) == WLAN_STATUS_FAILURE) { + DBGLOG(RX, TRACE, "nicRxEnhanceRxReadBuffer failed\n"); + nicRxReturnRFB(prAdapter, prSwRfb); + break; + } + /* prSDIOCtrl->au4RxLength[i] = 0; */ + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + } + } + + prSDIOCtrl->rRxInfo.u.u2NumValidRx0Len = 0; + prSDIOCtrl->rRxInfo.u.u2NumValidRx1Len = 0; + +} /* end of nicRxSDIOReceiveRFBs() */ + +#endif /* CFG_SDIO_INTR_ENHANCE */ + +#if CFG_SDIO_RX_AGG +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read frames from the data port for SDIO with Rx aggregation enabled +* I/F, fill RFB and put each frame into the rReceivedRFBList queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxSDIOAggReceiveRFBs(IN P_ADAPTER_T prAdapter) +{ + P_ENHANCE_MODE_DATA_STRUCT_T prEnhDataStr; + P_RX_CTRL_T prRxCtrl; + P_SDIO_CTRL_T prSDIOCtrl; + P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL; + UINT_32 u4RxLength; + UINT_32 i, rxNum; + UINT_32 u4RxAggCount = 0, u4RxAggLength = 0; + UINT_32 u4RxAvailAggLen, u4CurrAvailFreeRfbCnt; + PUINT_8 pucSrcAddr; + P_HIF_RX_HEADER_T prHifRxHdr; + BOOLEAN fgResult = TRUE; + BOOLEAN fgIsRxEnhanceMode; + UINT_16 u2RxPktNum; +#if CFG_SDIO_RX_ENHANCE + UINT_32 u4MaxLoopCount = CFG_MAX_RX_ENHANCE_LOOP_COUNT; +#endif + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicRxSDIOAggReceiveRFBs"); + + ASSERT(prAdapter); + prEnhDataStr = prAdapter->prSDIOCtrl; + prRxCtrl = &prAdapter->rRxCtrl; + prSDIOCtrl = prAdapter->prSDIOCtrl; + +#if CFG_SDIO_RX_ENHANCE + fgIsRxEnhanceMode = TRUE; +#else + fgIsRxEnhanceMode = FALSE; +#endif + + do { +#if CFG_SDIO_RX_ENHANCE + /* to limit maximum loop for RX */ + u4MaxLoopCount--; + if (u4MaxLoopCount == 0) + break; +#endif + + if (prEnhDataStr->rRxInfo.u.u2NumValidRx0Len == 0 && prEnhDataStr->rRxInfo.u.u2NumValidRx1Len == 0) + break; + + for (rxNum = 0; rxNum < 2; rxNum++) { + u2RxPktNum = + (rxNum == + 0 ? prEnhDataStr->rRxInfo.u.u2NumValidRx0Len : prEnhDataStr->rRxInfo.u.u2NumValidRx1Len); + + /* if this assertion happened, it is most likely a F/W bug */ + ASSERT(u2RxPktNum <= 16); + + if (u2RxPktNum > 16) + continue; + + if (u2RxPktNum == 0) + continue; + +#if CFG_HIF_STATISTICS + prRxCtrl->u4TotalRxAccessNum++; + prRxCtrl->u4TotalRxPacketNum += u2RxPktNum; +#endif + + u4CurrAvailFreeRfbCnt = prRxCtrl->rFreeSwRfbList.u4NumElem; + + /* if SwRfb is not enough, abort reading this time */ + if (u4CurrAvailFreeRfbCnt < u2RxPktNum) { +#if CFG_HIF_RX_STARVATION_WARNING + DbgPrint("FreeRfb is not enough: %d available, need %d\n", u4CurrAvailFreeRfbCnt, + u2RxPktNum); + DbgPrint("Queued Count: %d / Dequeud Count: %d\n", prRxCtrl->u4QueuedCnt, + prRxCtrl->u4DequeuedCnt); +#endif + continue; + } +#if CFG_SDIO_RX_ENHANCE + u4RxAvailAggLen = + CFG_RX_COALESCING_BUFFER_SIZE - (sizeof(ENHANCE_MODE_DATA_STRUCT_T) + + 4 /* extra HW padding */); +#else + u4RxAvailAggLen = CFG_RX_COALESCING_BUFFER_SIZE; +#endif + u4RxAggCount = 0; + + for (i = 0; i < u2RxPktNum; i++) { + u4RxLength = (rxNum == 0 ? + (UINT_32) prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + (UINT_32) prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + if (!u4RxLength) { + ASSERT(0); + break; + } + + if (ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN) < u4RxAvailAggLen) { + if (u4RxAggCount < u4CurrAvailFreeRfbCnt) { + u4RxAvailAggLen -= ALIGN_4(u4RxLength + HIF_RX_HW_APPENDED_LEN); + u4RxAggCount++; + } else { + /* no FreeSwRfb for rx packet */ + ASSERT(0); + break; + } + } else { + /* CFG_RX_COALESCING_BUFFER_SIZE is not large enough */ + ASSERT(0); + break; + } + } + + u4RxAggLength = (CFG_RX_COALESCING_BUFFER_SIZE - u4RxAvailAggLen); + /* DBGLOG(RX, INFO, ("u4RxAggCount = %d, u4RxAggLength = %d\n", */ + /* u4RxAggCount, u4RxAggLength)); */ + + HAL_READ_RX_PORT(prAdapter, + rxNum, + u4RxAggLength, prRxCtrl->pucRxCoalescingBufPtr, CFG_RX_COALESCING_BUFFER_SIZE); + if (!fgResult) { + DBGLOG(RX, ERROR, "Read RX Agg Packet Error\n"); + continue; + } + + pucSrcAddr = prRxCtrl->pucRxCoalescingBufPtr; + for (i = 0; i < u4RxAggCount; i++) { + UINT_16 u2PktLength; + + u2PktLength = (rxNum == 0 ? + prEnhDataStr->rRxInfo.u.au2Rx0Len[i] : + prEnhDataStr->rRxInfo.u.au2Rx1Len[i]); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_REMOVE_HEAD(&prRxCtrl->rFreeSwRfbList, prSwRfb, P_SW_RFB_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + ASSERT(prSwRfb); + kalMemCopy(prSwRfb->pucRecvBuff, pucSrcAddr, + ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN)); + + /* record the rx time */ + STATS_RX_ARRIVE_TIME_RECORD(prSwRfb); /* ms */ + + prHifRxHdr = prSwRfb->prHifRxHdr; + ASSERT(prHifRxHdr); + + prSwRfb->ucPacketType = + (UINT_8) (prHifRxHdr->u2PacketType & HIF_RX_HDR_PACKET_TYPE_MASK); + /* DBGLOG(RX, TRACE, ("ucPacketType = %d\n", prSwRfb->ucPacketType)); */ + + prSwRfb->ucStaRecIdx = (UINT_8) (prHifRxHdr->ucStaRecIdx); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + QUEUE_INSERT_TAIL(&prRxCtrl->rReceivedRfbList, &prSwRfb->rQueEntry); + RX_INC_CNT(prRxCtrl, RX_MPDU_TOTAL_COUNT); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + pucSrcAddr += ALIGN_4(u2PktLength + HIF_RX_HW_APPENDED_LEN); + /* prEnhDataStr->au4RxLength[i] = 0; */ + } + +#if CFG_SDIO_RX_ENHANCE + kalMemCopy(prAdapter->prSDIOCtrl, (pucSrcAddr + 4), sizeof(ENHANCE_MODE_DATA_STRUCT_T)); + + /* do the same thing what nicSDIOReadIntStatus() does */ + if ((prSDIOCtrl->u4WHISR & WHISR_TX_DONE_INT) == 0 && + (prSDIOCtrl->rTxInfo.au4WTSR[0] | prSDIOCtrl->rTxInfo.au4WTSR[1])) { + prSDIOCtrl->u4WHISR |= WHISR_TX_DONE_INT; + } + + if ((prSDIOCtrl->u4WHISR & BIT(31)) == 0 && + HAL_GET_MAILBOX_READ_CLEAR(prAdapter) == TRUE && + (prSDIOCtrl->u4RcvMailbox0 != 0 || prSDIOCtrl->u4RcvMailbox1 != 0)) { + prSDIOCtrl->u4WHISR |= BIT(31); + } + + /* dispatch to interrupt handler with RX bits masked */ + nicProcessIST_impl(prAdapter, + prSDIOCtrl->u4WHISR & (~(WHISR_RX0_DONE_INT | WHISR_RX1_DONE_INT))); +#endif + } + +#if !CFG_SDIO_RX_ENHANCE + prEnhDataStr->rRxInfo.u.u2NumValidRx0Len = 0; + prEnhDataStr->rRxInfo.u.u2NumValidRx1Len = 0; +#endif + } while ((prEnhDataStr->rRxInfo.u.u2NumValidRx0Len || prEnhDataStr->rRxInfo.u.u2NumValidRx1Len) + && fgIsRxEnhanceMode); + +} +#endif /* CFG_SDIO_RX_AGG */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Setup a RFB and allocate the os packet to the RFB +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @retval WLAN_STATUS_SUCCESS +* @retval WLAN_STATUS_RESOURCES +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxSetupRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + PVOID pvPacket; + PUINT_8 pucRecvBuff; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (!prSwRfb->pvPacket) { + kalMemZero(prSwRfb, sizeof(SW_RFB_T)); + pvPacket = kalPacketAlloc(prAdapter->prGlueInfo, CFG_RX_MAX_PKT_SIZE, &pucRecvBuff); + if (pvPacket == NULL) + return WLAN_STATUS_RESOURCES; + + prSwRfb->pvPacket = pvPacket; + prSwRfb->pucRecvBuff = (PVOID) pucRecvBuff; + } else { + kalMemZero(((PUINT_8) prSwRfb + OFFSET_OF(SW_RFB_T, prHifRxHdr)), + (sizeof(SW_RFB_T) - OFFSET_OF(SW_RFB_T, prHifRxHdr))); + } + + prSwRfb->prHifRxHdr = (P_HIF_RX_HEADER_T) (prSwRfb->pucRecvBuff); + + return WLAN_STATUS_SUCCESS; + +} /* end of nicRxSetupRFB() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to put a RFB back onto the "RFB with Buffer" list +* or "RFB without buffer" list according to pvPacket. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prSwRfb Pointer to the RFB +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxReturnRFB(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_RX_CTRL_T prRxCtrl; + P_QUE_ENTRY_T prQueEntry; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prSwRfb); + prRxCtrl = &prAdapter->rRxCtrl; + prQueEntry = &prSwRfb->rQueEntry; + + ASSERT(prQueEntry); + + /* The processing on this RFB is done, so put it back on the tail of + our list */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); + + if (prSwRfb->pvPacket) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rFreeSwRfbList, prQueEntry); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(&prRxCtrl->rIndicatedRfbList, prQueEntry); + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_RX_QUE); +} /* end of nicRxReturnRFB() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process rx interrupt. When the rx +* Interrupt is asserted, it means there are frames in queue. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessRxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + prGlueInfo->IsrRxCnt++; +#if CFG_SDIO_INTR_ENHANCE +#if CFG_SDIO_RX_AGG + nicRxSDIOAggReceiveRFBs(prAdapter); +#else + nicRxSDIOReceiveRFBs(prAdapter); +#endif +#else + nicRxReceiveRFBs(prAdapter); +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicRxProcessRFBs(prAdapter); + + return; + +} /* end of nicProcessRxInterrupt() */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* @brief Used to update IP/TCP/UDP checksum statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param aeCSUM The array of checksum result. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxUpdateCSUMStatistics(IN P_ADAPTER_T prAdapter, IN const ENUM_CSUM_RESULT_T aeCSUM[]) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + ASSERT(aeCSUM); + + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS) || + (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_SUCCESS_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) || (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_FAILED)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_IP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L3_PKT_COUNT); + } else { + ASSERT(0); + } + + if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) { + /* count success num */ + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_TCP_FAILED_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_SUCCESS_COUNT); + } else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UDP_FAILED_COUNT); + } else if ((aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_NONE) && (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_NONE)) { + RX_INC_CNT(prRxCtrl, RX_CSUM_UNKNOWN_L4_PKT_COUNT); + } else { + ASSERT(0); + } + +} /* end of nicRxUpdateCSUMStatistics() */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current status of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatus(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + + SPRINTF(pucCurrBuf, ("\n\nRX CTRL STATUS:")); + SPRINTF(pucCurrBuf, ("\n===============")); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/i BUF LIST :%9u", prRxCtrl->rFreeSwRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nFREE RFB w/o BUF LIST :%9u", prRxCtrl->rIndicatedRfbList.u4NumElem)); + SPRINTF(pucCurrBuf, ("\nRECEIVED RFB LIST :%9u", prRxCtrl->rReceivedRfbList.u4NumElem)); + + SPRINTF(pucCurrBuf, ("\n\n")); + + /* *pu4Count = (UINT_32)((UINT_32)pucCurrBuf - (UINT_32)pucBuffer); */ + +} /* end of nicRxQueryStatus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Clear RX related counters +* +* @param prAdapter Pointer of Adapter Data Structure +* +* @return - (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxClearStatistics(IN P_ADAPTER_T prAdapter) +{ + P_RX_CTRL_T prRxCtrl; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + RX_RESET_ALL_CNTS(prRxCtrl); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to query current statistics of RX Module. +* +* @param prAdapter Pointer to the Adapter structure. +* @param pucBuffer Pointer to the message buffer. +* @param pu4Count Pointer to the buffer of message length count. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxQueryStatistics(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucBuffer, OUT PUINT_32 pu4Count) +{ + P_RX_CTRL_T prRxCtrl; + PUINT_8 pucCurrBuf = pucBuffer; + + ASSERT(prAdapter); + prRxCtrl = &prAdapter->rRxCtrl; + ASSERT(prRxCtrl); + + /* if (pucBuffer) {} */ /* For Windows, we'll print directly instead of sprintf() */ + ASSERT(pu4Count); + +#define SPRINTF_RX_COUNTER(eCounter) \ + SPRINTF(pucCurrBuf, ("%-30s : %u\n", #eCounter, (UINT_32)prRxCtrl->au8Statistics[eCounter])) + + SPRINTF_RX_COUNTER(RX_MPDU_TOTAL_COUNT); + SPRINTF_RX_COUNTER(RX_SIZE_ERR_DROP_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_INDICATION_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETURNED_COUNT); + SPRINTF_RX_COUNTER(RX_DATA_RETAINED_COUNT); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD || CFG_TCP_IP_CHKSUM_OFFLOAD_NDIS_60 + SPRINTF_RX_COUNTER(RX_CSUM_TCP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_FAILED_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_TCP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UDP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_IP_SUCCESS_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L4_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_CSUM_UNKNOWN_L3_PKT_COUNT); + SPRINTF_RX_COUNTER(RX_IP_V6_PKT_CCOUNT); +#endif + + /* *pu4Count = (UINT_32)(pucCurrBuf - pucBuffer); */ + + nicRxClearStatistics(prAdapter); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Read the Response data from data port +* +* @param prAdapter pointer to the Adapter handler +* @param pucRspBuffer pointer to the Response buffer +* +* @retval WLAN_STATUS_SUCCESS: Response packet has been read +* @retval WLAN_STATUS_FAILURE: Read Response packet timeout or error occurred +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +nicRxWaitResponse(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucPortIdx, OUT PUINT_8 pucRspBuffer, IN UINT_32 u4MaxRespBufferLen, OUT PUINT_32 pu4Length) +{ + UINT_32 u4Value = 0, u4PktLen = 0; + UINT_32 i = 0; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + BOOLEAN fgResult = TRUE; + UINT_32 u4Time, u4Current; + + DEBUGFUNC("nicRxWaitResponse"); + + ASSERT(prAdapter); + ASSERT(pucRspBuffer); + ASSERT(ucPortIdx < 2); + + u4Time = kalGetTimeTick(); + + do { + /* Read the packet length */ + HAL_MCR_RD(prAdapter, MCR_WRPLR, &u4Value); + + if (!fgResult) { + DBGLOG(RX, ERROR, "Read Response Packet Error\n"); + return WLAN_STATUS_FAILURE; + } + + if (ucPortIdx == 0) + u4PktLen = u4Value & 0xFFFF; + else + u4PktLen = (u4Value >> 16) & 0xFFFF; + +/* DBGLOG(RX, TRACE, ("i = %d, u4PktLen = %d\n", i, u4PktLen)); */ + + if (u4PktLen == 0) { + /* timeout exceeding check */ + u4Current = kalGetTimeTick(); + + if ((u4Current > u4Time) && ((u4Current - u4Time) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "RX_RESPONSE_TIMEOUT1 %u %d %u\n", u4PktLen, i, u4Current); + return WLAN_STATUS_FAILURE; + } else if (u4Current < u4Time && ((u4Current + (0xFFFFFFFF - u4Time)) > RX_RESPONSE_TIMEOUT)) { + DBGLOG(RX, ERROR, "RX_RESPONSE_TIMEOUT2 %u %d %u\n", u4PktLen, i, u4Current); + return WLAN_STATUS_FAILURE; + } + + /* Response packet is not ready */ + kalUdelay(50); + + i++; + continue; + } + if (u4PktLen > u4MaxRespBufferLen) { + /* + TO: buffer is not enough but we still need to read all data from HIF to avoid + HIF crazy. + */ + DBGLOG(RX, ERROR, + "Not enough Event Buffer: required length = 0x%x, available buffer length = %d\n", + u4PktLen, u4MaxRespBufferLen); + DBGLOG(RX, ERROR, "i = %d, u4PktLen = %u\n", i, u4PktLen); + return WLAN_STATUS_FAILURE; + } + HAL_PORT_RD(prAdapter, + ucPortIdx == 0 ? MCR_WRDR0 : MCR_WRDR1, u4PktLen, pucRspBuffer, u4MaxRespBufferLen); + + /* fgResult will be updated in MACRO */ + if (!fgResult) { + DBGLOG(RX, ERROR, "Read Response Packet Error\n"); + return WLAN_STATUS_FAILURE; + } + + DBGLOG(RX, TRACE, "Dump Response buffer, length = 0x%x\n", u4PktLen); + DBGLOG_MEM8(RX, TRACE, pucRspBuffer, u4PktLen); + + *pu4Length = u4PktLen; + break; + } while (TRUE); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to enable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxEnablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxEnablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Set filter to disable Promiscuous Mode +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicRxDisablePromiscuousMode(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + +} /* end of nicRxDisablePromiscuousMode() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in reordering module +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxFlush(IN P_ADAPTER_T prAdapter) +{ + P_SW_RFB_T prSwRfb; + + ASSERT(prAdapter); + + prSwRfb = qmFlushRxQueues(prAdapter); + if (prSwRfb != NULL) { + do { + P_SW_RFB_T prNextSwRfb; + + /* save next first */ + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + + /* free */ + nicRxReturnRFB(prAdapter, prSwRfb); + + prSwRfb = prNextSwRfb; + } while (prSwRfb); + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief +* +* @param +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicRxProcessActionFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb) +{ + P_WLAN_ACTION_FRAME prActFrame; + + ASSERT(prAdapter); + ASSERT(prSwRfb); + + if (prSwRfb->u2PacketLen < sizeof(WLAN_ACTION_FRAME) - 1) + return WLAN_STATUS_INVALID_PACKET; + prActFrame = (P_WLAN_ACTION_FRAME) prSwRfb->pvHeader; + DBGLOG(RX, INFO, "Category %u\n", prActFrame->ucCategory); + + switch (prActFrame->ucCategory) { + case CATEGORY_PUBLIC_ACTION: + if (HIF_RX_HDR_GET_NETWORK_IDX(prSwRfb->prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) + aisFuncValidateRxActionFrame(prAdapter, prSwRfb); +#if CFG_ENABLE_WIFI_DIRECT + else if (prAdapter->fgIsP2PRegistered) { + rlmProcessPublicAction(prAdapter, prSwRfb); + + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); + + } +#endif + break; + + case CATEGORY_HT_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + rlmProcessHtAction(prAdapter, prSwRfb); +#endif + break; + case CATEGORY_VENDOR_SPECIFIC_ACTION: +#if CFG_ENABLE_WIFI_DIRECT + if (prAdapter->fgIsP2PRegistered) + p2pFuncValidateRxActionFrame(prAdapter, prSwRfb); +#endif + break; +#if CFG_SUPPORT_802_11W + case CATEGORY_SA_QUERT_ACTION: + { + P_HIF_RX_HEADER_T prHifRxHdr; + + prHifRxHdr = prSwRfb->prHifRxHdr; + + if ((HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr) == NETWORK_TYPE_AIS_INDEX) + && prAdapter->rWifiVar.rAisSpecificBssInfo.fgMgmtProtection /* Use MFP */) { + if (!(prHifRxHdr->ucReserved & CONTROL_FLAG_UC_MGMT_NO_ENC)) { + /* MFP test plan 5.3.3.4 */ + rsnSaQueryAction(prAdapter, prSwRfb); + } else { + DBGLOG(RSN, TRACE, "Un-Protected SA Query, do nothing\n"); + } + } + } + break; +#endif +#if CFG_SUPPORT_802_11V + case CATEGORY_WNM_ACTION: + { + wnmWNMAction(prAdapter, prSwRfb); + } + break; +#endif + +#if CFG_SUPPORT_DFS /* Add by Enlai */ + case CATEGORY_SPEC_MGT: + { + if (prAdapter->fgEnable5GBand == TRUE) + rlmProcessSpecMgtAction(prAdapter, prSwRfb); + } + break; +#endif + +#if (CFG_SUPPORT_TDLS == 1) + case 12: /* shall not be here */ + /* + A received TDLS Action frame with the Type field set to Management shall + be discarded. Note that the TDLS Discovery Response frame is not a TDLS + frame but a Public Action frame. + */ + break; +#endif /* CFG_SUPPORT_TDLS */ + + default: + break; + } /* end of switch case */ + + return WLAN_STATUS_SUCCESS; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c new file mode 100644 index 0000000000000..024bd95076037 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/nic_tx.c @@ -0,0 +1,2350 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#1 +*/ + +/*! \file nic_tx.c + \brief Functions that provide TX operation in NIC Layer. + + This file provides TX functions which are responsible for both Hardware and + Software Resource Management and keep their Synchronization. +*/ + +/* +** Log: nic_tx.c + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add log counter for tx + * + * 11 09 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for beacon timeout and sta aging timeout. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 05 17 2011 cp.wu + * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss + * disconnection + * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame + * dropping cases for TC4 path + * remove unused variables. + * + * 04 12 2011 cp.wu + * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame + * dropping cases for TC4 path + * 1. add nicTxGetResource() API for QM to make decisions. + * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case. + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 02 16 2011 cp.wu + * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking available count + * and modify behavior + * 1. add new API: nicTxGetFreeCmdCount() + * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation + * needs such information + * fill mac header length information for 802.1x frames. + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system + * scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being + * loaded + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 10 18 2010 cp.wu + * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore + * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion + * 2. shorten polling count for shorter response time + * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 09 29 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue. + * + * 09 27 2010 wh.su + * NULL + * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error + * + * 09 24 2010 wh.su + * NULL + * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra + * bytes padding. + * + * 09 01 2010 cp.wu + * NULL + * HIFSYS Clock Source Workaround + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 08 30 2010 cp.wu + * NULL + * eliminate klockwork errors + * + * 08 20 2010 wh.su + * NULL + * adding the eapol callback setting. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 05 2010 yuche.tsai + * NULL + * . + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 13 2010 cp.wu + * + * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets + * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending + * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network + * operation + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 24 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 22 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) add command warpper for STA-REC/BSS-INFO sync. + * 2) enhance command packet sending procedure for non-oid part + * 3) add command packet definitions for STA-REC/BSS-INFO sync. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add checking for TX descriptor poll. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * TX descriptors are now allocated once for reducing allocation overhead + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change zero-padding for TX port access to HAL. + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 15 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * . + * + * 06 14 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * fill extra information for revised HIF_TX_HEADER. + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 10 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change to enqueue TX frame infinitely. + * + * 06 09 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add TX_PACKET_MGMT to indicate the frame is coming from management modules + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Tag the packet for QoS on Tx path + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove driver-land statistics. + * + * 03 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * + * 03 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK + * * * * * + * +* 03 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code clean: removing unused variables and structure definitions + * + * 03 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread. + * * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds + * + * 03 02 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add mutex to avoid multiple access to qmTxQueue simultaneously. + * + * 02 26 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * avoid referring to NDIS-specific data structure directly from non-glue layer. + * + * 02 24 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add Ethernet destination address information in packet info for TX + * + * 02 10 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c] + * * * * * * 2) firmware image length is now retrieved via NdisFileOpen + * * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore + * * * * * * 4) nicRxWaitResponse() revised + * * * * * * 5) another set of TQ counter default value is added for fw-download state + * * * * * * 6) Wi-Fi load address is now retrieved from registry too + * + * 02 09 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address + * * * * * * * * * 2. follow MSDN defined behavior when associates to another AP + * * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes + * + * 02 08 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * prepare for implementing fw download logic + * + * 01 27 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. eliminate improper variable in rHifInfo + * * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged + * * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode + * * * * * * * * * 4. correct some HAL implementation + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism + * + * 01 13 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo + * + * 12 30 2009 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) According to CMD/EVENT documentation v0.8, + * * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used, + * * * * * * * * * * and result is retrieved by get ATInfo instead + * * * * * * * * * * 2) add 4 counter for recording aggregation statistics +** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752 +** remove unused API +** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752 +** correct assertion criterion +** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752 +** correct trivial mistake +** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752 +** + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data +** + add more assertion for packet size check +** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752 +** nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort +** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752 +** add 2 assertion for size check +** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752 +** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T +** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752 +** use TC4 instead of TC5 for command packet +** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752 +** add flush for reset +** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752 +** fill prMsduInfo->ucUserPriority +** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752 +** fill u2SeqNo +** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752 +** integration with SD1's data path API +** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752 +** nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList +** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752 +** add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, +** WIFI_CMD_T will be created inside oid handler +** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752 +** use TxAccquireResource instead of accessing TCQ directly. +** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752 +** add nicTxMsduInfoList () implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752 +** add nicTxAdjustTcq() implementation +** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752 +** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure +** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752 +** add SD1_SD3_DATAPATH_INTEGRATION data path handling +** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084 +** modify TX hdr format, fix tx retransmission issue +** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084 +** modify TX SW data structure +** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084 +** modify HAL part +** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084 +** update for new HW design +** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725 +** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461 +** Assign SeqNum to CMD Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461 +** Add debug message +** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461 +** Fix Query Command need resp issue +** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461 +** Move OS dependent code to kalQueryTxOOBData() +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461 +** Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461 +** Update nicTxCmd() for moving wait RESP function call to wlanSendCommand() +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461 +** Move the CMD_INFO_T related function to cmd_buf.c +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426 +** Update OOB query for TX packet +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426 +** Support PKGUIO +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461 +** Add virtual OOB for HIF LOOPBACK SW PRETEST +** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461 +** Add function for SDIO_TX_ENHANCE +** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461 +** Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test. +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461 +** Add code for TX Data & Cmd Packet +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461 +** Fix LINT warning +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461 +** Update TX PATH API +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426 +** Init for develop +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will initial all variables in regard to SW TX Queues and +* all free lists of MSDU_INFO_T and SW_TFCB_T. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxInitialize(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + PUINT_8 pucMemHandle; + P_MSDU_INFO_T prMsduInfo; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxInitialize"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + /* 4 <1> Initialization of Traffic Class Queue Parameters */ + nicTxResetResource(prAdapter); + +#if CFG_SDIO_TX_AGG + prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached; +#endif /* CFG_SDIO_TX_AGG */ + + /* allocate MSDU_INFO_T and link it into rFreeMsduInfoList */ + QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList); + + pucMemHandle = prTxCtrl->pucTxCached; + for (i = 0; i < CFG_TX_MAX_PKT_NUM; i++) { + prMsduInfo = (P_MSDU_INFO_T) pucMemHandle; + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + + pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T)); + } + + ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM); + /* Check if the memory allocation consist with this initialization function */ + ASSERT((UINT_32) (pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize); + + QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue); + prTxCtrl->i4TxMgmtPendingNum = 0; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum = 0; + prTxCtrl->u4TotalTxPacketNum = 0; +#endif + + prTxCtrl->i4PendingFwdFrameCount = 0; + + qmInit(prAdapter); + + TX_RESET_ALL_CNTS(prTxCtrl); + +} /* end of nicTxInitialize() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will check if has enough TC Buffer for incoming +* packet and then update the value after promise to provide the resources. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] ucTC Specify the resource of TC +* +* \retval WLAN_STATUS_SUCCESS Resource is available and been assigned. +* \retval WLAN_STATUS_RESOURCES Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 u4CurrTick = 0; +WLAN_STATUS nicTxAcquireResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC, IN BOOLEAN pfgIsSecOrMgmt) +{ +#define TC4_NO_RESOURCE_DELAY_MS 5 /* exponential of 5s */ + + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES; + P_QUE_MGT_T prQM; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + prQM = &prAdapter->rQM; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + +/* DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", + ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); */ + do { + if (pfgIsSecOrMgmt && (ucTC == TC4_INDEX)) { + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] < 2) { + DBGLOG(TX, EVENT, " aucFreeBufferCount = %d\n", + prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) + u4CurrTick = 0; + + break; + } + } + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) { + + if (ucTC == TC4_INDEX) + u4CurrTick = 0; + /* get a available TX entry */ + prTxCtrl->rTc.aucFreeBufferCount[ucTC]--; + + prQM->au4ResourceUsedCounter[ucTC]++; + + DBGLOG(TX, EVENT, "Acquire: TC = %d aucFreeBufferCount = %d\n", + ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]); + + u4Status = WLAN_STATUS_SUCCESS; + } + } while (FALSE); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + if (ucTC == TC4_INDEX) { + if (u4CurrTick == 0) + u4CurrTick = kalGetTimeTick(); + if (CHECK_FOR_TIMEOUT(kalGetTimeTick(), u4CurrTick, + SEC_TO_SYSTIME(TC4_NO_RESOURCE_DELAY_MS))) { + wlanDumpTcResAndTxedCmd(NULL, 0); + cmdBufDumpCmdQueue(&prAdapter->rPendingCmdQueue, "waiting response CMD queue"); + glDumpConnSysCpuInfo(prAdapter->prGlueInfo); + kalSendAeeWarning("[TC4 no resource delay 5s!]", __func__); + glDoChipReset(); + u4CurrTick = 0; + } + } + return u4Status; + +} /* end of nicTxAcquireResourceAndTFCBs() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will do polling if FW has return the resource. +* Used when driver start up before enable interrupt. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Resource is available. +* @retval WLAN_STATUS_FAILURE Resource is not available. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxPollingResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + P_TX_CTRL_T prTxCtrl; + WLAN_STATUS u4Status = WLAN_STATUS_FAILURE; + INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT; + UINT_32 au4WTSR[2]; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + if (ucTC >= TC_NUM) + return WLAN_STATUS_FAILURE; + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) + return WLAN_STATUS_SUCCESS; + + while (i-- > 0) { + HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR); + + if (kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE || fgIsBusAccessFailed == TRUE) { + u4Status = WLAN_STATUS_FAILURE; + break; + } else if (nicTxReleaseResource(prAdapter, (PUINT_8) au4WTSR)) { + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) { + u4Status = WLAN_STATUS_SUCCESS; + break; + } + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + + } else { + kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC); + } + } + + if (i <= 0 && ucTC == TC4_INDEX) { + DBGLOG(TX, ERROR, "polling Tx resource for Tc4 timeout\n"); + glDumpConnSysCpuInfo(prAdapter->prGlueInfo); + } +#if DBG + { + INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i + 1); + + if (i4Times) { + DBGLOG(TX, TRACE, "Polling MCR_WTSR delay %d times, %d msec\n", + i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)); + } + } +#endif /* DBG */ + + return u4Status; + +} /* end of nicTxPollingResource() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will release TC Buffer count according to +* the given TX_STATUS COUNTER after TX Done. +* +* \param[in] prAdapter Pointer to the Adapter structure. +* \param[in] u4TxStatusCnt Value of TX STATUS +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxReleaseResource(IN P_ADAPTER_T prAdapter, IN unsigned char *aucTxRlsCnt) +{ + PUINT_32 pu4Tmp = (PUINT_32) aucTxRlsCnt; + P_TX_CTRL_T prTxCtrl; + BOOLEAN bStatus = FALSE; + UINT_32 i; + + KAL_SPIN_LOCK_DECLARATION(); + + P_QUE_MGT_T prQM = &prAdapter->rQM; + prTxCtrl = &prAdapter->rTxCtrl; + + if (pu4Tmp[0] | pu4Tmp[1]) { + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + for (i = 0; i < TC_NUM; i++) + prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i]; + for (i = 0; i < TC_NUM; i++) + prQM->au4QmTcResourceBackCounter[i] += aucTxRlsCnt[i]; + if (aucTxRlsCnt[TC4_INDEX] != 0) + wlanTraceReleaseTcRes(prAdapter, aucTxRlsCnt, prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX]); + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); +#if 0 + for (i = 0; i < TC_NUM; i++) { + DBGLOG(TX, TRACE, "aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n", + i, prTxCtrl->rTc.aucFreeBufferCount[i], i, + prTxCtrl->rTc.aucMaxNumOfBuffer[i]); + } + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]); + DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]); +#endif + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]); + ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]); + bStatus = TRUE; + } + + return bStatus; +} /* end of nicTxReleaseResource() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset TC Buffer Count to initialized value +* +* \param[in] prAdapter Pointer to the Adapter structure. +* +* @return WLAN_STATUS_SUCCESS +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxResetResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + DEBUGFUNC("nicTxResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Driver maintain a variable that is synchronous with the usage of individual +* TC Buffer Count. This function will return the value for other component +* which needs this information for making decisions +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucTC Specify the resource of TC +* +* @retval UINT_8 The number of corresponding TC number +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 nicTxGetResource(IN P_ADAPTER_T prAdapter, IN UINT_8 ucTC) +{ + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + ASSERT(prTxCtrl); + + if (ucTC >= TC_NUM) + return 0; + else + return prTxCtrl->rTc.aucFreeBufferCount[ucTC]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll aggregate frame(PACKET_INFO_T) +* corresponding to HIF TX port +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoListHead a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxMsduInfoList(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + QUE_T qDataPort0, qDataPort1; + WLAN_STATUS status; + BOOLEAN pfgIsSecOrMgmt = FALSE; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prMsduInfo = prMsduInfoListHead; + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + /* Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1 */ + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); +#if DBG && 0 + LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prMsduInfo->ucTC, + prMsduInfo->ucNetworkType, + prMsduInfo->ucMacHeaderLength, + prMsduInfo->u2FrameLength, + prMsduInfo->ucPacketType, prMsduInfo->fgIs802_1x, prMsduInfo->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prMsduInfo->aucEthDestAddr); +#endif + + /* double-check available TX resouce (need to sync with CONNSYS FW) */ + /* caller must guarantee that the TX resource is enough in the func; OR assert here */ + switch (prMsduInfo->ucTC) { + case TC0_INDEX: + case TC1_INDEX: + case TC2_INDEX: + case TC3_INDEX: + case TC5_INDEX: /* Broadcast/multicast data packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, FALSE); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + case TC4_INDEX: /* Command or 802.1x packets */ + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + + if ((prMsduInfo->fgIs802_1x == TRUE) || + (prMsduInfo->fgIs802_11 == TRUE)) + pfgIsSecOrMgmt = TRUE; + + status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC, pfgIsSecOrMgmt); + ASSERT(status == WLAN_STATUS_SUCCESS) + + break; + + default: + ASSERT(0); + break; + } + + prMsduInfo = prNextMsduInfo; + } + + /* send packets to HIF port0 or port1 here */ + if (qDataPort0.u4NumElem > 0) + nicTxMsduQueue(prAdapter, 0, &qDataPort0); + + if (qDataPort1.u4NumElem > 0) + nicTxMsduQueue(prAdapter, 1, &qDataPort1); + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + +#if CFG_PRINT_RTP_PROFILE +PKT_PROFILE_T rPrevRoundLastPkt; + +BOOLEAN +nicTxLifetimePrintCheckRTP(IN P_MSDU_INFO_T prPrevProfileMsduInfo, + IN P_PKT_PROFILE_T prPrevRoundLastPkt, + IN P_PKT_PROFILE_T prPktProfile, + IN OUT PBOOLEAN pfgGotFirst, IN UINT_32 u4MaxDeltaTime, IN UINT_8 ucSnToBePrinted) +{ + BOOLEAN fgPrintCurPkt = FALSE; + + if (u4MaxDeltaTime) { + /* 4 1. check delta between current round first pkt and prevous round last pkt */ + if (!*pfgGotFirst) { + *pfgGotFirst = TRUE; + + if (prPrevRoundLastPkt->fgIsValid) { + if (CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) { + PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR"); + fgPrintCurPkt = TRUE; + } + } + } + /* 4 2. check delta between current pkt and previous pkt */ + if (prPrevProfileMsduInfo) { + if (CHK_PROFILES_DELTA(prPktProfile, &prPrevProfileMsduInfo->rPktProfile, u4MaxDeltaTime)) { + PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P"); + fgPrintCurPkt = TRUE; + } + } + /* 4 3. check delta of current pkt lifetime */ + if (CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) + fgPrintCurPkt = TRUE; + } + /* 4 4. print every X RTP packets */ +#if CFG_SUPPORT_WFD + if ((ucSnToBePrinted != 0) && (prPktProfile->u2RtpSn % ucSnToBePrinted) == 0) + fgPrintCurPkt = TRUE; +#endif + + return fgPrintCurPkt; +} + +BOOLEAN +nicTxLifetimePrintCheckSnOrder(IN P_MSDU_INFO_T prPrevProfileMsduInfo, + IN P_PKT_PROFILE_T prPrevRoundLastPkt, + IN P_PKT_PROFILE_T prPktProfile, IN OUT PBOOLEAN pfgGotFirst, IN UINT_8 ucLayer) +{ + BOOLEAN fgPrintCurPkt = FALSE; + P_PKT_PROFILE_T prTarPktProfile = NULL; + UINT_16 u2PredictSn = 0; + UINT_16 u2CurrentSn = 0; + UINT_8 aucNote[8]; + + /* 4 1. Get the target packet profile to compare */ + + /* 4 1.1 check SN between current round first pkt and prevous round last pkt */ + if ((!*pfgGotFirst) && (prPrevRoundLastPkt->fgIsValid)) { + *pfgGotFirst = TRUE; + prTarPktProfile = prPrevRoundLastPkt; + kalMemCopy(aucNote, "PR\0", 3); + } + /* 4 1.2 check SN between current pkt and previous pkt */ + else if (prPrevProfileMsduInfo) { + prTarPktProfile = &prPrevProfileMsduInfo->rPktProfile; + kalMemCopy(aucNote, "P\0", 2); + } + + if (!prTarPktProfile) + return FALSE; + /* 4 2. Check IP or RTP SN */ + switch (ucLayer) { + /* Check IP SN */ + case 0: + u2PredictSn = prTarPktProfile->u2IpSn + 1; + u2CurrentSn = prPktProfile->u2IpSn; + break; + /* Check RTP SN */ + case 1: + default: + u2PredictSn = prTarPktProfile->u2RtpSn + 1; + u2CurrentSn = prPktProfile->u2RtpSn; + break; + + } + /* 4 */ + /* 4 3. Compare SN */ + if (u2CurrentSn != u2PredictSn) { + PRINT_PKT_PROFILE(prTarPktProfile, aucNote); + fgPrintCurPkt = TRUE; + } + + return fgPrintCurPkt; +} +#endif + +VOID nicTxReturnMsduInfoProfiling(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + P_PKT_PROFILE_T prPktProfile; + UINT_16 u2MagicCode = 0; + + UINT_8 ucDebugtMode = 0; +#if CFG_PRINT_RTP_PROFILE + P_MSDU_INFO_T prPrevProfileMsduInfo = NULL; + P_PKT_PROFILE_T prPrevRoundLastPkt = &rPrevRoundLastPkt; + + BOOLEAN fgPrintCurPkt = FALSE; + BOOLEAN fgGotFirst = FALSE; + UINT_8 ucSnToBePrinted = 0; + + UINT_32 u4MaxDeltaTime = 50; /* in ms */ +#endif + +#if CFG_ENABLE_PER_STA_STATISTICS + UINT_32 u4PktPrintPeriod = 0; +#endif + +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + if (prAdapter->fgIsP2PRegistered) { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + u2MagicCode = prWfdCfgSettings->u2WfdMaximumTp; + ucDebugtMode = prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting.ucWfdDebugMode; + /* if(prWfdCfgSettings->ucWfdEnable && (prWfdCfgSettings->u4WfdFlag & BIT(0))) { */ + /* u2MagicCode = 0xE040; */ + /* } */ + } +#endif + +#if CFG_PRINT_RTP_PROFILE + if ((u2MagicCode >= 0xF000)) { + ucSnToBePrinted = (UINT_8) (u2MagicCode & BITS(0, 7)); + u4MaxDeltaTime = (UINT_8) (((u2MagicCode & BITS(8, 11)) >> 8) * 10); + } else { + ucSnToBePrinted = 0; + u4MaxDeltaTime = 0; + } + +#endif + +#if CFG_ENABLE_PER_STA_STATISTICS + if ((u2MagicCode >= 0xE000) && (u2MagicCode < 0xF000)) + u4PktPrintPeriod = (UINT_32) ((u2MagicCode & BITS(0, 7)) * 32); + else + u4PktPrintPeriod = 0; +#endif + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + prPktProfile = &prMsduInfo->rPktProfile; + + if (prPktProfile->fgIsValid) { + + prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick(); + if (ucDebugtMode > 1) { + +#if CFG_PRINT_RTP_PROFILE +#if CFG_PRINT_RTP_SN_SKIP + fgPrintCurPkt = nicTxLifetimePrintCheckSnOrder(prPrevProfileMsduInfo, + prPrevRoundLastPkt, + prPktProfile, &fgGotFirst, 0); +#else + fgPrintCurPkt = nicTxLifetimePrintCheckRTP(prPrevProfileMsduInfo, + prPrevRoundLastPkt, + prPktProfile, + &fgGotFirst, + u4MaxDeltaTime, ucSnToBePrinted); +#endif + + /* Print current pkt profile */ + if (fgPrintCurPkt && ucDebugtMode > 1) + PRINT_PKT_PROFILE(prPktProfile, "C"); + + prPrevProfileMsduInfo = prMsduInfo; + fgPrintCurPkt = FALSE; +#endif + } +#if CFG_ENABLE_PER_STA_STATISTICS + { + P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + UINT_32 u4DeltaTime; + UINT_32 u4DeltaHifTime; +#if 0 + P_QUE_MGT_T prQM = &prAdapter->rQM; +#endif + UINT_8 ucNetIndex; + + if (prStaRec) { + ucNetIndex = prStaRec->ucNetTypeIndex; + u4DeltaTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rHardXmitArrivalTimestamp); + u4DeltaHifTime = (UINT_32) (prPktProfile->rHifTxDoneTimestamp - + prPktProfile->rDequeueTimestamp); + prStaRec->u4TotalTxPktsNumber++; + + prStaRec->u4TotalTxPktsTime += u4DeltaTime; + prStaRec->u4TotalTxPktsHifTime += u4DeltaHifTime; + + if (u4DeltaTime > prStaRec->u4MaxTxPktsTime) + prStaRec->u4MaxTxPktsTime = u4DeltaTime; + + if (u4DeltaHifTime > prStaRec->u4MaxTxPktsHifTime) + prStaRec->u4MaxTxPktsHifTime = u4DeltaHifTime; + + + if (u4DeltaTime >= NIC_TX_TIME_THRESHOLD) + prStaRec->u4ThresholdCounter++; +#if 0 + if (u4PktPrintPeriod && (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) { + + DBGLOG(TX, TRACE, "[%u]N[%4u]A[%5u]M[%4u]T[%4u]E[%4u]\n", + prStaRec->ucIndex, + prStaRec->u4TotalTxPktsNumber, + prStaRec->u4TotalTxPktsTime / prStaRec->u4TotalTxPktsNumber, + prStaRec->u4MaxTxPktsTime, + prStaRec->u4ThresholdCounter, + prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX]); + + prStaRec->u4TotalTxPktsNumber = 0; + prStaRec->u4TotalTxPktsTime = 0; + prStaRec->u4MaxTxPktsTime = 0; + prStaRec->u4ThresholdCounter = 0; + prQM->au4QmTcResourceEmptyCounter[ucNetIndex][TC2_INDEX] = 0; + } +#endif + } + + } +#endif + } + + prMsduInfo = prNextMsduInfo; + }; + +#if CFG_PRINT_RTP_PROFILE + /* 4 4. record the lifetime of current round last pkt */ + if (prPrevProfileMsduInfo) { + prPktProfile = &prPrevProfileMsduInfo->rPktProfile; + prPrevRoundLastPkt->u2IpSn = prPktProfile->u2IpSn; + prPrevRoundLastPkt->u2RtpSn = prPktProfile->u2RtpSn; + prPrevRoundLastPkt->rHardXmitArrivalTimestamp = prPktProfile->rHardXmitArrivalTimestamp; + prPrevRoundLastPkt->rEnqueueTimestamp = prPktProfile->rEnqueueTimestamp; + prPrevRoundLastPkt->rDequeueTimestamp = prPktProfile->rDequeueTimestamp; + prPrevRoundLastPkt->rHifTxDoneTimestamp = prPktProfile->rHifTxDoneTimestamp; + prPrevRoundLastPkt->ucTcxFreeCount = prPktProfile->ucTcxFreeCount; + prPrevRoundLastPkt->fgIsPrinted = prPktProfile->fgIsPrinted; + prPrevRoundLastPkt->fgIsValid = TRUE; + } +#endif + + nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead); + +} + +VOID nicTxLifetimeRecordEn(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* Enable packet lifetime profiling */ + prPktProfile->fgIsValid = TRUE; + + /* Packet arrival time at kernel Hard Xmit */ + prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket); + + /* Packet enqueue time */ + prPktProfile->rEnqueueTimestamp = (OS_SYSTIME) kalGetTimeTick(); + +} + +#if CFG_PRINT_RTP_PROFILE +/* + in: + data RTP packet pointer + size RTP size + return + 0:audio 1: video, -1:none +*/ +UINT8 checkRtpAV(PUINT_8 data, UINT_32 size) +{ + PUINT_8 buf = data + 12; + + while (buf + 188 <= data + size) { + int pid = ((buf[1] << 8) & 0x1F00) | (buf[2] & 0xFF); + + if (pid == 0 || pid == 0x100 || pid == 0x1000) + buf += 188; + else if (pid == 0x1100) + return 0; + else if (pid == 0x1011) + return 1; + } + return -1; +} + +VOID +nicTxLifetimeCheckRTP(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prPacket, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) +{ + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + UINT_16 u2EtherTypeLen; + PUINT_8 aucLookAheadBuf = NULL; + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* UINT_8 ucRtpHdrOffset = 28; */ + UINT_8 ucRtpSnOffset = 30; + /* UINT_32 u4RtpSrcPort = 15550; */ + P_TX_CTRL_T prTxCtrl; +#if CFG_SUPPORT_WFD + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_WFD_DBG_CFG_SETTINGS_T prWfdDbgSettings = (P_WFD_DBG_CFG_SETTINGS_T) NULL; + + BOOLEAN fgEnProfiling = FALSE; + + if (prAdapter->fgIsP2PRegistered) { + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + prWfdDbgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdDebugSetting; +#if CFG_PRINT_RTP_SN_SKIP + if (ucNetworkType == NETWORK_TYPE_P2P_INDEX) { + fgEnProfiling = TRUE; + } else +#endif + if (((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000) || + (prWfdDbgSettings->ucWfdDebugMode > 0)) && (ucNetworkType == NETWORK_TYPE_P2P_INDEX)) { + fgEnProfiling = TRUE; + } + } + + if (fgEnProfiling == FALSE) { + /* prPktProfile->fgIsValid = FALSE; */ + return; + } +#endif + + prTxCtrl = &prAdapter->rTxCtrl; + /* prPktProfile->fgIsValid = FALSE; */ + + aucLookAheadBuf = prSkb->data; + + u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + + if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_16 u2tmpIpSN = 0; + UINT_8 ucIpVersion; + + ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion == IPVERSION) { + if (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) { + + /* if(checkRtpAV(&pucIpHdr[ucRtpHdrOffset], + (u4PacketLen - ETH_HLEN - ucRtpHdrOffset)) == 0) { */ + + if (prPktProfile->fgIsValid == FALSE) + nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); + + prPktProfile->fgIsPrinted = FALSE; + + prPktProfile->ucTcxFreeCount = prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX]; + + /* RTP SN */ + prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1]; + + /* IP SN */ + prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 | + pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1]; + u2tmpIpSN = prPktProfile->u2IpSn; + if (prWfdDbgSettings->ucWfdDebugMode == 1) { + if ((u2tmpIpSN & (prWfdDbgSettings->u2WfdSNShowPeiroid)) == 0) + DBGLOG(TX, TRACE, + "RtpSn=%d IPId=%d j=%lu\n", prPktProfile->u2RtpSn, + prPktProfile->u2IpSn, jiffies); + } + /* } */ + } + } + } + +} +#endif +#if CFG_ENABLE_PER_STA_STATISTICS +VOID +nicTxLifetimeCheckByAC(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket, IN UINT_8 ucPriorityParam) +{ + switch (ucPriorityParam) { + /* BK */ + /* case 1: */ + /* case 2: */ + + /* BE */ + /* case 0: */ + /* case 3: */ + + /* VI */ + case 4: + case 5: + + /* VO */ + case 6: + case 7: + nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket); + break; + default: + break; + } +} + +#endif + +VOID +nicTxLifetimeCheck(IN P_ADAPTER_T prAdapter, + IN P_MSDU_INFO_T prMsduInfo, + IN P_NATIVE_PACKET prPacket, + IN UINT_8 ucPriorityParam, IN UINT_32 u4PacketLen, IN UINT_8 ucNetworkType) +{ + P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile; + + /* Reset packet profile */ + prPktProfile->fgIsValid = FALSE; + +#if CFG_ENABLE_PER_STA_STATISTICS + nicTxLifetimeCheckByAC(prAdapter, prMsduInfo, prPacket, ucPriorityParam); +#endif + +#if CFG_PRINT_RTP_PROFILE + nicTxLifetimeCheckRTP(prAdapter, prMsduInfo, prPacket, u4PacketLen, ucNetworkType); +#endif + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief In this function, we'll write frame(PACKET_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param ucPortIdx Port Number +* @param prQue a link list of P_MSDU_INFO_T +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxMsduQueue(IN P_ADAPTER_T prAdapter, UINT_8 ucPortIdx, P_QUE_T prQue) +{ + P_MSDU_INFO_T prMsduInfo, prNextMsduInfo; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_16 u2OverallBufferLength; + UINT_8 ucEtherTypeOffsetInWord; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 u4TxHdrSize; + UINT_32 u4ValidBufSize; + UINT_32 u4TotalLength; + P_TX_CTRL_T prTxCtrl; + QUE_T rFreeQueue; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + UINT_8 ucChksumFlag; +#endif + + ASSERT(prAdapter); + ASSERT(ucPortIdx < 2); + ASSERT(prQue); + + prTxCtrl = &prAdapter->rTxCtrl; + u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize; + +#if CFG_HIF_STATISTICS + prTxCtrl->u4TotalTxAccessNum++; + prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem; +#endif + + QUEUE_INITIALIZE(&rFreeQueue); + + if (prQue->u4NumElem > 0) { + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_HEAD(prQue); + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + u4TotalLength = 0; + + while (prMsduInfo) { + +#if (CFG_SUPPORT_TDLS_DBG == 1) + { + struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(TX, TRACE, " %d\n", u2Identifier); + } + } +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetProfilingFinish(prAdapter, prMsduInfo); +#endif + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prMsduInfo->prPacket; + + ASSERT(prNativePacket); + + u4TxHdrSize = TX_HDR_SIZE; + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + /* init TX header */ + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + if (prMsduInfo->fgIs802_11) { + ucEtherTypeOffsetInWord = + (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + } else { + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + } + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if (prAdapter->u4CSUMFlags & + (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP)) { + kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag); + + if (ucChksumFlag & TX_CS_IP_GEN) + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_IP_CSUM; + + if (ucChksumFlag & TX_CS_TCP_UDP_GEN) + rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8) HIF_TX_HDR_TCP_CSUM; + } + } +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << + HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = + (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & + HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & + HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & + HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if (prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if (prMsduInfo->fgNeedTxDoneStatus == TRUE) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_NEED_TX_DONE_STATUS; + + if (prMsduInfo->fgIsBIP) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + + if (prMsduInfo->fgIsBasicRate) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + if (prMsduInfo->rPktProfile.fgIsValid) + prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick(); +#endif + + /* record the queue time in driver */ + STATS_TX_TIME_TO_HIF(prMsduInfo, &rHwTxHeader); + +#if CFG_SDIO_TX_AGG + /* attach to coalescing buffer */ + kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize); + u4TotalLength += u4TxHdrSize; + + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TotalLength); + else if (prMsduInfo->eSrc == TX_PACKET_MGMT) + kalMemCopy(pucOutputBuf + u4TotalLength, prNativePacket, prMsduInfo->u2FrameLength); + else + ASSERT(0); + + u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength); + +#else + kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize); + + /* Copy Frame Body */ + if (prMsduInfo->eSrc == TX_PACKET_OS || prMsduInfo->eSrc == TX_PACKET_FORWARDING) + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + u4TxHdrSize); + else if (prMsduInfo->eSrc == TX_PACKET_MGMT) + kalMemCopy(pucOutputBuf + u4TxHdrSize, prNativePacket, prMsduInfo->u2FrameLength); + else + ASSERT(0); + + ASSERT(u2OverallBufferLength <= u4ValidBufSize); + + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); + + /* send immediately */ +#endif + prNextMsduInfo = (P_MSDU_INFO_T) + QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry); + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + KAL_SPIN_LOCK_DECLARATION(); + DBGLOG(TX, TRACE, "Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } else { + /* only free MSDU when it is not a MGMT frame */ + QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T) prMsduInfo); + + if (prMsduInfo->eSrc == TX_PACKET_OS) + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_SUCCESS); + else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + prMsduInfo = prNextMsduInfo; + } + +#if CFG_SDIO_TX_AGG + ASSERT(u4TotalLength <= u4ValidBufSize); + +#if CFG_DBG_GPIO_PINS + { + /* Start port write */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH); + } +#endif + + /* send coalescing buffer */ + HAL_WRITE_TX_PORT(prAdapter, ucPortIdx, u4TotalLength, (PUINT_8) pucOutputBuf, u4ValidBufSize); +#endif + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE +#if CFG_SUPPORT_WFD && CFG_PRINT_RTP_PROFILE && !CFG_ENABLE_PER_STA_STATISTICS + do { + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + + prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings; + + if ((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000)) { + /* Enable profiling */ + nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); + } else { + /* Skip profiling */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); + } + } while (FALSE); +#else + nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); +#endif +#else + /* return */ + nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rFreeQueue)); +#endif + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_WIFI_CMD_T prWifiCmd; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_8 ucPortIdx; + HIF_TX_HEADER_T rHwTxHeader; + P_NATIVE_PACKET prNativePacket; + UINT_8 ucEtherTypeOffsetInWord; + P_MSDU_INFO_T prMsduInfo; + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + + /* <1> Assign Data Port */ + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } else { + /* Broadcast/multicast data frames, 1x frames, command packets, MMPDU */ + ucPortIdx = 1; + } + wlanTraceTxCmd(prCmdInfo); + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + /* <2> Compose HIF_TX_HEADER */ + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + prNativePacket = prCmdInfo->prPacket; + + ASSERT(prNativePacket); + + u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE) + & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1; + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET); + + rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK; + + rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = + (((UINT_8) (prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & + HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK); + + rHwTxHeader.u2SeqNo = 0; + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_TX_DONE_STATUS; + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE /* | HIF_TX_HDR_RTS */; + + /* <2.3> Copy HIF TX HEADER */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + /* <3> Copy Frame Body Copy */ + kalCopyFrame(prAdapter->prGlueInfo, prNativePacket, pucOutputBuf + TX_HDR_SIZE); + } else if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = (P_MSDU_INFO_T) prCmdInfo->prPacket; + + ASSERT(prMsduInfo->fgIs802_11 == TRUE); + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + /* <2> Compose HIF_TX_HEADER */ + kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader)); + + u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) & + (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength; + rHwTxHeader.u2TxByteCount_UserPriority |= + ((UINT_16) prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET); + + ucEtherTypeOffsetInWord = (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1; + + rHwTxHeader.ucEtherTypeOffset = ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK; + + rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET; + rHwTxHeader.ucResource_PktType_CSflags |= + (UINT_8) (((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) & + (HIF_TX_HDR_PACKET_TYPE_MASK)); + + rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH; + rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex; + rHwTxHeader.ucForwardingType_SessionID_Reserved = + (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET) + | ((prMsduInfo->fgIsBurstEnd) ? HIF_TX_HDR_BURST_END_MASK : 0); + + rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK); + rHwTxHeader.ucPktFormtId_Flags = (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK) + | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK) + | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK) + | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & + HIF_TX_HDR_FLAG_802_11_FORMAT_MASK); + + rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN; + + if (prMsduInfo->pfTxDoneHandler) { + rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum; + rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK; + } else { + rHwTxHeader.ucPacketSeqNo = 0; + rHwTxHeader.ucAck_BIP_BasicRate = 0; + } + + if (prMsduInfo->fgIsBIP) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP; + + if (prMsduInfo->fgIsBasicRate) + rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE; + /* <2.3> Copy HIF TX HEADER */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE); + + /* <3> Copy Frame Body */ + kalMemCopy(pucOutputBuf + TX_HDR_SIZE, prMsduInfo->prPacket, prMsduInfo->u2FrameLength); + + /* <4> Management Frame Post-Processing */ + GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + if (prMsduInfo->pfTxDoneHandler == NULL) { + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + + DBGLOG(TX, TRACE, "Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + } + } else { + prWifiCmd = (P_WIFI_CMD_T) prCmdInfo->pucInfoBuffer; + + /* <2> Compose the Header of Transmit Data Structure for CMD Packet */ + u2OverallBufferLength = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength; + prWifiCmd->ucEtherTypeOffset = 0; + prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET) + | (UINT_8) ((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK)); + + /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + if ((prCmdInfo->ucCID == CMD_ID_SCAN_REQ) || + (prCmdInfo->ucCID == CMD_ID_SCAN_CANCEL) || + (prCmdInfo->ucCID == CMD_ID_SCAN_REQ_V2)) + DBGLOG(TX, INFO, "ucCmdSeqNum =%d, ucCID =%d\n", prCmdInfo->ucCmdSeqNum, prCmdInfo->ucCID); + } + + /* <4> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, + (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); + + return WLAN_STATUS_SUCCESS; +} /* end of nicTxCmd() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function will clean up all the pending frames in internal SW Queues +* by return the pending TX packet to the system. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxRelease(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + + nicTxFlush(prAdapter); + + /* free MSDU_INFO_T from rTxMgmtMsduInfoList */ + do { + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST); + + if (prMsduInfo) { + /* the packet must be mgmt frame with tx done callback */ + ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT); + + /* invoke done handler */ + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT); + + cnmMgtPktFree(prAdapter, prMsduInfo); + } else { + break; + } + } while (TRUE); + +} /* end of nicTxRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Process the TX Done interrupt and pull in more pending frames in SW +* Queues for transmission. +* +* @param prAdapter Pointer to the Adapter structure. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicProcessTxInterrupt(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; +#if CFG_SDIO_INTR_ENHANCE + P_SDIO_CTRL_T prSDIOCtrl; +#else + UINT_32 au4TxCount[2]; +#endif /* CFG_SDIO_INTR_ENHANCE */ + + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + prGlueInfo->IsrTxCnt++; + + /* Get the TX STATUS */ +#if CFG_SDIO_INTR_ENHANCE + + prSDIOCtrl = prAdapter->prSDIOCtrl; +#if DBG + /* dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T)); */ +#endif + + nicTxReleaseResource(prAdapter, (PUINT_8) &prSDIOCtrl->rTxInfo); + kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo)); + +#else + + HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]); + HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]); + DBGLOG(EMU, TRACE, "MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]); + + nicTxReleaseResource(prAdapter, (PUINT_8) au4TxCount); + +#endif /* CFG_SDIO_INTR_ENHANCE */ + + nicTxAdjustTcq(prAdapter); + + /* Indicate Service Thread */ + if (kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0 || wlanGetTxPendingFrameCount(prAdapter) > 0) + kalSetEvent(prAdapter->prGlueInfo); + +} /* end of nicProcessTxInterrupt() */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function frees packet of P_MSDU_INFO_T linked-list +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxFreeMsduInfoPacket(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_NATIVE_PACKET prNativePacket; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prMsduInfoListHead); + + prTxCtrl = &prAdapter->rTxCtrl; + + while (prMsduInfo) { + prNativePacket = prMsduInfo->prPacket; + + if (prMsduInfo->eSrc == TX_PACKET_OS) { + kalSendComplete(prAdapter->prGlueInfo, prNativePacket, WLAN_STATUS_FAILURE); + } else if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + P_MSDU_INFO_T prTempMsduInfo = prMsduInfo; + + if (prMsduInfo->pfTxDoneHandler) + prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER); + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + cnmMgtPktFree(prAdapter, prTempMsduInfo); + continue; + } else if (prMsduInfo->eSrc == TX_PACKET_FORWARDING) { + GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount); + } + + prMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfoList a link list of P_MSDU_INFO_T +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID nicTxReturnMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + switch (prMsduInfo->eSrc) { + case TX_PACKET_FORWARDING: + wlanReturnPacket(prAdapter, prMsduInfo->prPacket); + break; + case TX_PACKET_OS: + case TX_PACKET_OS_OID: + case TX_PACKET_MGMT: + default: + break; + } + + /* Reset MSDU_INFO fields */ + kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T)); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T) prMsduInfo); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST); + prMsduInfo = prNextMsduInfo; + }; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function fills packet information to P_MSDU_INFO_T +* +* @param prAdapter Pointer to the Adapter structure. +* @param prMsduInfo P_MSDU_INFO_T +* @param prPacket P_NATIVE_PACKET +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN nicTxFillMsduInfo(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo, IN P_NATIVE_PACKET prPacket) +{ + P_GLUE_INFO_T prGlueInfo; + UINT_8 ucPriorityParam; + UINT_8 ucMacHeaderLen; + UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN]; + BOOLEAN fgIs1x = FALSE; + BOOLEAN fgIsPAL = FALSE; + UINT_32 u4PacketLen; + ULONG u4SysTime; + UINT_8 ucNetworkType; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + + ASSERT(prAdapter); + + prGlueInfo = prAdapter->prGlueInfo; + ASSERT(prGlueInfo); + + if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo, + prPacket, + &ucPriorityParam, + &u4PacketLen, + aucEthDestAddr, + &fgIs1x, &fgIsPAL, &ucNetworkType, + NULL) == FALSE) { + return FALSE; + } +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + nicTxLifetimeCheck(prAdapter, prMsduInfo, prPacket, ucPriorityParam, u4PacketLen, ucNetworkType); +#endif + + /* Save the value of Priority Parameter */ + GLUE_SET_PKT_TID(prPacket, ucPriorityParam); + + if (fgIs1x) + GLUE_SET_PKT_FLAG_1X(prPacket); + + if (fgIsPAL) + GLUE_SET_PKT_FLAG_PAL(prPacket); + + ucMacHeaderLen = ETH_HLEN; + + /* Save the value of Header Length */ + GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen); + + /* Save the value of Frame Length */ + GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16) u4PacketLen); + + /* Save the value of Arrival Time */ + u4SysTime = (OS_SYSTIME) kalGetTimeTick(); + GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime); + + prMsduInfo->prPacket = prPacket; + prMsduInfo->fgIs802_1x = fgIs1x; + prMsduInfo->fgIs802_11 = FALSE; + prMsduInfo->ucNetworkType = ucNetworkType; + prMsduInfo->ucUserPriority = ucPriorityParam; + prMsduInfo->ucMacHeaderLength = ucMacHeaderLen; + prMsduInfo->u2FrameLength = (UINT_16) u4PacketLen; + COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr); + + if (prSkb->len > ETH_HLEN) + STATS_TX_PKT_CALLBACK(prSkb->data, prMsduInfo); + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function update TCQ values by passing current status to txAdjustTcQuotas +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Updated successfully +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxAdjustTcq(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4Num; + TX_TCQ_ADJUST_T rTcqAdjust; + P_TX_CTRL_T prTxCtrl; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + for (u4Num = 0; u4Num < TC_NUM; u4Num++) { + prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num]; + prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num]; + } + + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief this function flushes all packets queued in STA/AC queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Flushed successfully +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS nicTxFlush(IN P_ADAPTER_T prAdapter) +{ + P_MSDU_INFO_T prMsduInfo; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + + /* ask Per STA/AC queue to be fllushed and return all queued packets */ + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prMsduInfo = qmFlushTxQueues(prAdapter); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + if (prMsduInfo != NULL) { + nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo); + nicTxReturnMsduInfo(prAdapter, prMsduInfo); + } + + return WLAN_STATUS_SUCCESS; +} + +#if CFG_ENABLE_FW_DOWNLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll write Command(CMD_INFO_T) into HIF. +* However this function is used for INIT_CMD. +* +* In order to avoid further maintenance issues, these 2 functions are separated +* +* @param prAdapter Pointer to the Adapter structure. +* @param prPacketInfo Pointer of CMD_INFO_T +* @param ucTC Specify the resource of TC +* +* @retval WLAN_STATUS_SUCCESS Bus access ok. +* @retval WLAN_STATUS_FAILURE Bus access fail. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitCmd(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN UINT_8 ucTC) +{ + P_INIT_HIF_TX_HEADER_T prInitTxHeader; + UINT_16 u2OverallBufferLength; + PUINT_8 pucOutputBuf = (PUINT_8) NULL; /* Pointer to Transmit Data Structure Frame */ + UINT_32 ucPortIdx; + P_TX_CTRL_T prTxCtrl; + + ASSERT(prAdapter); + ASSERT(prCmdInfo); + ASSERT(ucTC == TC0_INDEX); + + prTxCtrl = &prAdapter->rTxCtrl; + pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr; + prInitTxHeader = (P_INIT_HIF_TX_HEADER_T) prCmdInfo->pucInfoBuffer; + + /* <1> Compose the Header of Transmit Data Structure for CMD Packet */ + u2OverallBufferLength = + TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen) & (UINT_16) HIF_TX_HDR_TX_BYTE_COUNT_MASK); + + prInitTxHeader->u2TxByteCount = u2OverallBufferLength; + prInitTxHeader->ucEtherTypeOffset = 0; + prInitTxHeader->ucCSflags = 0; + + /* <2> Assign Data Port */ + if (ucTC != TC4_INDEX) { + ucPortIdx = 0; + } else { /* Broadcast/multicast data packets */ + ucPortIdx = 1; + } + + /* <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached) */ + kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID) prCmdInfo->pucInfoBuffer, prCmdInfo->u2InfoBufLen); + + ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize); + + /* <4> Write frame to data port */ + HAL_WRITE_TX_PORT(prAdapter, + ucPortIdx, + (UINT_32) u2OverallBufferLength, + (PUINT_8) pucOutputBuf, (UINT_32) prAdapter->u4CoalescingBufCachedSize); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief In this function, we'll reset TX resource counter to initial value used +* in F/W download state +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxInitResetResource(IN P_ADAPTER_T prAdapter) +{ + P_TX_CTRL_T prTxCtrl; + + DEBUGFUNC("nicTxInitResetResource"); + + ASSERT(prAdapter); + prTxCtrl = &prAdapter->rTxCtrl; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4; + + prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5; + + return WLAN_STATUS_SUCCESS; + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function enqueues MSDU_INFO_T into queue management, +* or command queue +* +* @param prAdapter Pointer to the Adapter structure. +* prMsduInfo Pointer to MSDU +* +* @retval WLAN_STATUS_SUCCESS Reset is done successfully. +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS nicTxEnqueueMsdu(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_TX_CTRL_T prTxCtrl; + P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead; + QUE_T qDataPort0, qDataPort1; + P_CMD_INFO_T prCmdInfo; + WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS; + + KAL_SPIN_LOCK_DECLARATION(); + + ASSERT(prAdapter); + ASSERT(prMsduInfo); + + prTxCtrl = &prAdapter->rTxCtrl; + ASSERT(prTxCtrl); + + QUEUE_INITIALIZE(&qDataPort0); + QUEUE_INITIALIZE(&qDataPort1); + + /* check how many management frame are being queued */ + while (prMsduInfo) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo); + + QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prMsduInfo) = NULL; + + if (prMsduInfo->eSrc == TX_PACKET_MGMT) { + /* MMPDU: force stick to TC4 */ + prMsduInfo->ucTC = TC4_INDEX; + + QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T) prMsduInfo); + } else { + QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T) prMsduInfo); + } + + prMsduInfo = prNextMsduInfo; + } + + if (qDataPort0.u4NumElem) { + /* send to QM: queue the packet to different TX queue by policy */ + KAL_SPIN_LOCK_DECLARATION(); + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort0)); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE); + + /* post-process for "dropped" packets */ + if (prRetMsduInfo != NULL) { /* unable to enqueue */ + nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo); + nicTxReturnMsduInfo(prAdapter, prRetMsduInfo); + } + } + + if (qDataPort1.u4NumElem) { + prMsduInfoHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&qDataPort1); + + if (qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) { + /* not enough descriptors for sending */ + u4Status = WLAN_STATUS_FAILURE; + + /* free all MSDUs */ + while (prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + if (prMsduInfoHead->pfTxDoneHandler != NULL) { + prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, + TX_RESULT_DROPPED_IN_DRIVER); + } + + cnmMgtPktFree(prAdapter, prMsduInfoHead); + + prMsduInfoHead = prNextMsduInfo; + } + } else { + /* send to command queue */ + while (prMsduInfoHead) { + prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry); + + KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T); + KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE); + + if (prCmdInfo) { + GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum); + + kalMemZero(prCmdInfo, sizeof(CMD_INFO_T)); + + prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME; + prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength; + prCmdInfo->pucInfoBuffer = NULL; + prCmdInfo->prPacket = (P_NATIVE_PACKET) prMsduInfoHead; + prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex; + prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType; + prCmdInfo->pfCmdDoneHandler = NULL; + prCmdInfo->pfCmdTimeoutHandler = NULL; + prCmdInfo->fgIsOid = FALSE; + prCmdInfo->fgSetQuery = TRUE; + prCmdInfo->fgNeedResp = FALSE; + + kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T) prCmdInfo); + } else { + /* Cmd free count is larger than expected, but allocation fail. */ + ASSERT(0); + + u4Status = WLAN_STATUS_FAILURE; + cnmMgtPktFree(prAdapter, prMsduInfoHead); + } + + prMsduInfoHead = prNextMsduInfo; + } + } + } + + /* indicate service thread for sending */ + if (prTxCtrl->i4TxMgmtPendingNum > 0 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) + kalSetEvent(prAdapter->prGlueInfo); + + return u4Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief this function returns available count in command queue +* +* @param prAdapter Pointer to the Adapter structure. +* +* @retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 nicTxGetFreeCmdCount(IN P_ADAPTER_T prAdapter) +{ + ASSERT(prAdapter); + + return prAdapter->rFreeCmdList.u4NumElem; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c new file mode 100644 index 0000000000000..38e4569bc04f9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/p2p_nic.c @@ -0,0 +1,192 @@ +/* +** Id: @(#) p2p_nic.c@@ +*/ + +/*! \file p2p_nic.c + \brief Wi-Fi Direct Functions that provide operation in NIC's (Network Interface Card) point of view. + + This file includes functions which unite multiple hal(Hardware) operations + and also take the responsibility of Software Resource Management in order + to keep the synchronization with Hardware Manipulation. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief When Probe Rsp & Beacon frame is received and decide a P2P device, +* this function will be invoked to buffer scan result +* +* @param prAdapter Pointer to the Adapter structure. +* @param prEventScanResult Pointer of EVENT_SCAN_RESULT_T. +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +nicRxAddP2pDevice(IN P_ADAPTER_T prAdapter, + IN P_EVENT_P2P_DEV_DISCOVER_RESULT_T prP2pResult, IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELength) +{ + P_P2P_INFO_T prP2pInfo = (P_P2P_INFO_T) NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; + UINT_32 u4Idx = 0; + BOOLEAN bUpdate = FALSE; + + PUINT_8 pucIeBuf = (PUINT_8) NULL; + UINT_16 u2IELength = 0; + UINT_8 zeroMac[] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; + + ASSERT(prAdapter); + + prP2pInfo = prAdapter->prP2pInfo; + + for (u4Idx = 0; u4Idx < prP2pInfo->u4DeviceNum; u4Idx++) { + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + if (EQUAL_MAC_ADDR(prTargetResult->aucDeviceAddr, prP2pResult->aucDeviceAddr)) { + bUpdate = TRUE; + + /* Backup OLD buffer result. */ + pucIeBuf = prTargetResult->pucIeBuf; + u2IELength = prTargetResult->u2IELength; + + /* Update Device Info. */ + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* See if new IE length is longer or not. */ + if ((u2RxIELength > u2IELength) && (u2IELength != 0)) { + /* Buffer is not enough. */ + u2RxIELength = u2IELength; + } else if ((u2IELength == 0) && (u2RxIELength != 0)) { + /* RX new IE buf. */ + ASSERT(pucIeBuf == NULL); + pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2RxIELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } + + /* Step to next buffer address. */ + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength); + } + + /* Restore buffer pointer. */ + prTargetResult->pucIeBuf = pucIeBuf; + + if (pucRxIEBuf) { + /* If new received IE is available. + * Replace the old one & update new IE length. + */ + kalMemCopy(pucIeBuf, pucRxIEBuf, u2RxIELength); + prTargetResult->u2IELength = u2RxIELength; + } else { + /* There is no new IE information, keep the old one. */ + prTargetResult->u2IELength = u2IELength; + } + } + } + + if (!bUpdate) { + /* We would flush the whole scan result after each scan request is issued. + * If P2P device is too many, it may over the scan list. + */ + if ((u4Idx < CFG_MAX_NUM_BSS_LIST) && (UNEQUAL_MAC_ADDR(zeroMac, prP2pResult->aucDeviceAddr))) { + /* whsu:XXX */ + prTargetResult = &prP2pInfo->arP2pDiscoverResult[u4Idx]; + + /* zero */ + kalMemZero(prTargetResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* then buffer */ + kalMemCopy(prTargetResult, (PVOID) prP2pResult, sizeof(EVENT_P2P_DEV_DISCOVER_RESULT_T)); + + /* printk("DVC FND %d %pM, %pM\n", + prP2pInfo->u4DeviceNum, + prP2pResult->aucDeviceAddr, + prTargetResult->aucDeviceAddr); */ + + if (u2RxIELength) { + prTargetResult->pucIeBuf = prP2pInfo->pucCurrIePtr; + + if (((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2RxIELength) > + (ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN]) { + /* Common Buffer is no enough. */ + u2IELength = + (UINT_16) ((ULONG)&prP2pInfo->aucCommIePool[CFG_MAX_COMMON_IE_BUF_LEN] - + (ULONG) prP2pInfo->pucCurrIePtr); + } else { + u2IELength = u2RxIELength; + } + + prP2pInfo->pucCurrIePtr = + (PUINT_8) ((ULONG) prP2pInfo->pucCurrIePtr + (ULONG) u2IELength); + + kalMemCopy((PVOID) prTargetResult->pucIeBuf, (PVOID) pucRxIEBuf, (UINT_32) u2IELength); + prTargetResult->u2IELength = u2IELength; + } else { + prTargetResult->pucIeBuf = NULL; + prTargetResult->u2IELength = 0; + } + + prP2pInfo->u4DeviceNum++; + + } else { + /* TODO: Fixme to replace an old one. (?) */ + ASSERT(FALSE); + } + } +} /* nicRxAddP2pDevice */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c new file mode 100644 index 0000000000000..dd00859d46082 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/nic/que_mgt.c @@ -0,0 +1,5038 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1 +*/ + +/*! \file "que_mgt.c" + \brief TX/RX queues management + + The main tasks of queue management include TC-based HIF TX flow control, + adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save + forwarding control, RX packet reordering, and RX BA agreement management. +*/ + +/* +** Log: que_mgt.c +** +** 04 11 2013 yuche.tsai +** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. +** Drop the probe response packet when absent. +** +** 04 09 2013 yuche.tsai +** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. +** Fix CMD buffer short issue. +** +** 04 09 2013 yuche.tsai +** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop. +** Fix CMD buffer short issue. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 02 23 2012 eddie.chen + * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule + * Change the enqueue policy when ACM = 1. + * + * 11 22 2011 yuche.tsai + * NULL + * Code refine, remove one #if 0 code. + * + * 11 19 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog for tx + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 18 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Fix xlog format to hex format + * + * 11 17 2011 tsaiyuan.hsu + * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3. + * avoid deactivating staRec when changing state from 3 to 3. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug msg for xlog. + * + * 11 11 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters of bb and ar for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Use short name for xlog. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 10 2011 chinglan.wang + * NULL + * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP. + * + * 11 09 2011 chinglan.wang + * NULL + * [WiFi direct]Can't make P2P connect via PBC. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 01 2011 chinglan.wang + * NULL + * Modify the Wi-Fi method of the flush TX queue when disconnect the AP. + * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to + * the AP.. + * + * 10 25 2011 wh.su + * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check + * un-expect + * let the Rx BA accept even the sta not valid. + * + * 09 28 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * enlarge window size only by 4. + * + * 09 01 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * set rx window size as twice buffer size. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue. + * + * 08 03 2011 tsaiyuan.hsu + * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX + * force window size at least 16. + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device + * issue. + * Fix GO send deauth frame issue. + * + * 07 26 2011 eddie.chen + * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter + * API for query the RX reorder queued packets counter. + * + * 07 07 2011 eddie.chen + * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. + * Add setEvent when free quota is updated. + * + * 07 05 2011 eddie.chen + * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS. + * Send 1x when peer STA is in PS. + * + * 05 31 2011 eddie.chen + * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931 + * Fix the QM quota in MT5931. + * + * 05 11 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Fix dest type when GO packet copying. + * + * 05 09 2011 yuche.tsai + * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved) + * Deauthentication frame is not bound to network active status. + * + * 05 09 2011 eddie.chen + * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet + * Check free number before copying broadcast packet. + * + * 04 14 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Check the SW RFB free. Fix the compile warning.. + * + * 04 12 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix the sta index in processing security frame + * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4 + * Add debug message. + * + * 04 11 2011 yuche.tsai + * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue. + * Fix kernel panic issue when MMPDU of P2P is pending in driver. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 03 28 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Fix Klockwork warning. + * + * 03 28 2011 eddie.chen + * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW + * Fix wmm parameters in beacon for BOW. + * + * 03 15 2011 eddie.chen + * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter + * Add sw debug counter for QM. + * + * 02 23 2011 eddie.chen + * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap + * Fix parsing WMM INFO and bmp delivery bitmap definition. + * + * 02 17 2011 eddie.chen + * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel + * 1) Change GetFrameAction decision when BSS is absent. + * 2) Check channel and resource in processing ProbeRequest + * + * 02 08 2011 eddie.chen + * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode + * Add event STA agint timeout + * + * 01 27 2011 tsaiyuan.hsu + * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support + * add roaming fsm + * 1. not support 11r, only use strength of signal to determine roaming. + * 2. not enable CFG_SUPPORT_ROAMING until completion of full test. + * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw + * 4. assume that change of link quality in smooth way. + * + * 01 25 2011 yuche.tsai + * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record. + * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Remove comments. + * + * 01 24 2011 eddie.chen + * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets + * Add destination decision in AP mode. + * + * 01 14 2011 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326] + * [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!! + * Allow 802.1x can be send even the net is not active due the drver / fw sync issue. + * + * 01 13 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * Fix typo and compile error. + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * Fix WMM parameter condition for STA + * + * 01 12 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + * 1) Check Bss if support QoS before adding WMMIE + * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control + * + * 01 12 2011 george.huang + * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability + * Update MQM for WMM IE generation method + * + * 01 11 2011 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add per STA flow control when STA is in PS mode + * + * 01 03 2011 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * update prStaRec->fgIsUapsdSupported flag. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * Add WMM parameter for broadcast. + * + * 12 29 2010 eddie.chen + * [WCXRP00000322] Add WMM IE in beacon, +Add per station flow control when STA is in PS + + * 1) PS flow control event + * + * 2) WMM IE in beacon, assoc resp, probe resp + * + * 12 23 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * 1. update WMM IE parsing, with ASSOC REQ handling + * 2. extend U-APSD parameter passing from driver to FW + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * use the #14 and modify the add code for check MMPDU. + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * only MMPDU not check the netActive flag. + * + * 10 14 2010 wh.su + * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out + * not check the netActive flag for mgmt . + * + * 10 04 2010 cp.wu + * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by + * ENUM_NETWORK_TYPE_INDEX_T only + * remove ENUM_NETWORK_TYPE_T definitions + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 08 30 2010 yarco.yang + * NULL + * Fixed klockwork error message + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 10 2010 yarco.yang + * NULL + * Code refine + * + * 08 06 2010 yarco.yang + * NULL + * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action + * + * 07 26 2010 cp.wu + * + * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet + * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found + * + * 07 20 2010 yarco.yang + * + * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake + * + * 07 16 2010 yarco.yang + * + * 1. Support BSS Absence/Presence Event + * 2. Support STA change PS mode Event + * 3. Support BMC forwarding for AP mode. + * + * 07 14 2010 yarco.yang + * + * 1. Remove CFG_MQM_MIGRATION + * 2. Add CMD_UPDATE_WMM_PARMS command + * + * 07 13 2010 yarco.yang + * + * [WPD00003849] + * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing + * + * 07 09 2010 yarco.yang + * + * [MT6620 and MT5931] SW Migration: Add ADDBA support + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 07 08 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * . + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Use fgInUse instead of fgIsValid for De-queue judgement + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * For MMPDU, STA_REC will be decided by caller module + * + * 07 06 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Add MGMT Packet type for HIF_TX_HEADER + * + * 06 29 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * replace g_rQM with Adpater->rQM + * + * 06 25 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * add API in que_mgt to retrieve sta-rec index for security frames. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Support CFG_MQM_MIGRATION flag + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Refined the debug msg + * + * 03 30 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * comment out one assertion which refer to undefined data member. + * + * 03 30 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled adaptive TC resource control + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port + * +* 03 17 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST) + * + * 03 11 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed buffer leak when processing BAR frames + * + * 03 02 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5 + * + * 03 01 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Fixed STA_REC index determination bug (fgIsValid shall be checked) + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Refined function qmDetermineStaRecIndex() for BMCAST packets + * + * 02 25 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled multi-STA TX path with fairness + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled dynamically activating and deactivating STA_RECs + * + * 02 24 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Added code for dynamic activating and deactivating STA_RECs. + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the 802.1x path + * + * 01 13 2010 tehuang.liu + * [WPD00001943]Create WiFi test driver framework on WinXP + * Enabled the Burst_End Indication mechanism +** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468 +** Fixed casting for qmAddRxBaEntry() +** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752 +** remove SD1_SD3.. flag +** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468 +** Added RX buffer reordering functions +** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468 +** Modified Flush Queue function to let queues be reinitialized +** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468 +** Added flushing per-Type queues code +** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468 +** Added Debug msgs and fixed incorrect assert +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468 +** Bug fixing (qmDequeueTxPackets local variable initialization) +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752 +** correct and surpress PREfast warning +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468 +** Used SD1_SD3_DATAPATH_INTEGRATION +** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468 +** Initial version +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM]; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if ARP_MONITER_ENABLE +static UINT_16 arpMoniter; +static UINT_8 apIp[4]; +#endif +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static inline VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); + +static inline VOID +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, + IN UINT_8 ucTC, IN UINT_8 ucCurrentAvailableQuota, IN UINT_8 ucTotalQuota); + +static inline VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for TX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInit(IN P_ADAPTER_T prAdapter) +{ + UINT_32 u4QueArrayIdx; + UINT_32 i; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmInit()\n"); */ +#if CFG_SUPPORT_QOS + prAdapter->rWifiVar.fgSupportQoS = TRUE; +#else + prAdapter->rWifiVar.fgSupportQoS = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_RX + prAdapter->rWifiVar.fgSupportAmpduRx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduRx = FALSE; +#endif + +#if CFG_SUPPORT_AMPDU_TX + prAdapter->rWifiVar.fgSupportAmpduTx = TRUE; +#else + prAdapter->rWifiVar.fgSupportAmpduTx = FALSE; +#endif + +#if CFG_SUPPORT_TSPEC + prAdapter->rWifiVar.fgSupportTspec = TRUE; +#else + prAdapter->rWifiVar.fgSupportTspec = FALSE; +#endif + +#if CFG_SUPPORT_UAPSD + prAdapter->rWifiVar.fgSupportUAPSD = TRUE; +#else + prAdapter->rWifiVar.fgSupportUAPSD = FALSE; +#endif + +#if CFG_SUPPORT_UL_PSMP + prAdapter->rWifiVar.fgSupportULPSMP = TRUE; +#else + prAdapter->rWifiVar.fgSupportULPSMP = FALSE; +#endif + +#if CFG_SUPPORT_RX_SGI + prAdapter->rWifiVar.u8SupportRxSgi20 = 0; + prAdapter->rWifiVar.u8SupportRxSgi40 = 0; +#else + prAdapter->rWifiVar.u8SupportRxSgi20 = 2; + prAdapter->rWifiVar.u8SupportRxSgi40 = 2; +#endif + +#if CFG_SUPPORT_RX_HT_GF + prAdapter->rWifiVar.u8SupportRxGf = 0; +#else + prAdapter->rWifiVar.u8SupportRxGf = 2; +#endif + + /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */ + for (u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++) + QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx])); + + /* 4 <3> Initialize the RX BA table and RX queues */ + /* Initialize the RX Reordering Parameters and Queues */ + for (u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++) { + prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE; + QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue)); + prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF; + prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF; + + prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE; + + } + prQM->ucRxBaCount = 0; + + kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout)); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* 4 <4> Initialize TC resource control variables */ + for (i = 0; i < TC_NUM; i++) + prQM->au4AverageQueLen[i] = 0; + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + prQM->u4TxNumOfVi = 0; + prQM->u4TxNumOfVo = 0; + +/* ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); */ + + /* 1 20 1 1 4 1 */ + prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0; + prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1; + prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2; + prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3; + prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1) */ + prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5; + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC0 = %d\n", NIC_TX_BUFF_COUNT_TC0); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC1 = %d\n", NIC_TX_BUFF_COUNT_TC1); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC2 = %d\n", NIC_TX_BUFF_COUNT_TC2); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC3 = %d\n", NIC_TX_BUFF_COUNT_TC3); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC4 = %d\n", NIC_TX_BUFF_COUNT_TC4); + DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC5 = %d\n", NIC_TX_BUFF_COUNT_TC5); + + /* 1 1 1 1 2 1 */ + prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE; + prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE; + prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE; + prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE; + prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1) */ + prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE; + + /* 4 4 6 6 2 4 */ + prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE; + prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE; + prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE; + prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE; + prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE; + prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE; + + prQM->fgTcResourcePostAnnealing = FALSE; + + ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64); +#endif + +#if QM_TEST_MODE + prQM->u4PktCount = 0; + +#if QM_TEST_FAIR_FORWARDING + + prQM->u4CurrentStaRecIndexToEnqueue = 0; + { + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + P_STA_RECORD_T prStaRec; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + prStaRec = &prAdapter->arStaRec[1]; + ASSERT(prStaRec); + + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + prStaRec->fgIsAp = TRUE; + COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr); + + } + +#endif + +#endif + +#if QM_FORWARDING_FAIRNESS + { + UINT_32 i; + + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) { + prQM->au4ForwardCount[i] = 0; + prQM->au4HeadStaRecIndex[i] = 0; + } + } +#endif + +#if QM_TC_RESOURCE_EMPTY_COUNTER + kalMemZero(prQM->au4QmTcResourceEmptyCounter, sizeof(prQM->au4QmTcResourceEmptyCounter)); +#endif + +} + +#if QM_TEST_MODE +VOID qmTestCases(IN P_ADAPTER_T prAdapter) +{ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DbgPrint("QM: ** TEST MODE **\n"); + + if (QM_TEST_STA_REC_DETERMINATION) { + if (prAdapter->arStaRec[0].fgIsValid) { + prAdapter->arStaRec[0].fgIsValid = FALSE; + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + } else { + prAdapter->arStaRec[0].fgIsValid = TRUE; + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + } + } + + if (QM_TEST_STA_REC_DEACTIVATION) { + /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */ + + if (prAdapter->arStaRec[0].fgIsValid) { + + DbgPrint("QM: (Test) Deactivate STA_REC[0]\n"); + qmDeactivateStaRec(prAdapter, 0); + } else { + + UINT_8 aucMacAddr[MAC_ADDR_LEN]; + + /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */ + aucMacAddr[0] = 0x11; + aucMacAddr[1] = 0x22; + aucMacAddr[2] = 0xAA; + aucMacAddr[3] = 0xBB; + aucMacAddr[4] = 0xCC; + aucMacAddr[5] = 0xDD; + + DbgPrint("QM: (Test) Activate STA_REC[0]\n"); + qmActivateStaRec(prAdapter, /* Adapter pointer */ + 0, /* STA_REC index from FW */ + TRUE, /* fgIsQoS */ + NETWORK_TYPE_AIS_INDEX, /* Network type */ + TRUE, /* fgIsAp */ + aucMacAddr /* MAC address */ + ); + } + } + + if (QM_TEST_FAIR_FORWARDING) { + if (prAdapter->arStaRec[1].fgIsValid) { + prQM->u4CurrentStaRecIndexToEnqueue++; + prQM->u4CurrentStaRecIndexToEnqueue %= 2; + DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM->u4CurrentStaRecIndexToEnqueue); + } + } + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Activate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* \param[in] fgIsQoS Set to TRUE if this is a QoS STA +* \param[in] pucMacAddr The MAC address of the STA +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec) +{ + + /* 4 <1> Deactivate first */ + ASSERT(prStaRec); + + if (prStaRec->fgIsValid) { /* The STA_REC has been activated */ + DBGLOG(QM, WARN, "QM: (WARNING) Activating a STA_REC which has been activated\n"); + DBGLOG(QM, WARN, "QM: (WARNING) Deactivating a STA_REC before re-activating\n"); + /* To flush TX/RX queues and del RX BA agreements */ + qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); + } + /* 4 <2> Activate the STA_REC */ + /* Init the STA_REC */ + prStaRec->fgIsValid = TRUE; + prStaRec->fgIsInPS = FALSE; + prStaRec->ucPsSessionID = 0xFF; + prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE; + + /* Done in qmInit() or qmDeactivateStaRec() */ +#if 0 + /* At the beginning, no RX BA agreements have been established */ + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) + (prStaRec->aprRxReorderParamRefTbl)[i] = NULL; +#endif + + DBGLOG(QM, TRACE, "QM: +STA[%u]\n", (UINT_32) prStaRec->ucIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the STA_REC +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) +{ + P_STA_RECORD_T prStaRec; + UINT_32 i; + P_MSDU_INFO_T prFlushedTxPacketList = NULL; + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* 4<1> Flush TX queues */ + prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx); + + if (prFlushedTxPacketList) + wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList); + /* 4 <2> Flush RX queues and delete RX BA agreements */ + for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) { + /* Delete the RX BA entry with TID = i */ + qmDelRxBaEntry(prAdapter, (UINT_8) u4StaRecIdx, (UINT_8) i, FALSE); + } + + /* 4 <3> Deactivate the STA_REC */ + prStaRec->fgIsValid = FALSE; + prStaRec->fgIsInPS = FALSE; + + /* To reduce printk for IOT sta to connect all the time, */ + /* DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Deactivate a STA_REC +* +* \param[in] prAdapter Pointer to the Adapter instance +* \param[in] u4StaRecIdx The index of the network +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + + P_QUE_MGT_T prQM; + P_QUE_T prQue; + QUE_T rNeedToFreeQue; + QUE_T rTempQue; + P_QUE_T prNeedToFreeQue; + P_QUE_T prTempQue; + P_MSDU_INFO_T prMsduInfo; + + prQM = &prAdapter->rQM; + prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + + QUEUE_INITIALIZE(&rNeedToFreeQue); + QUEUE_INITIALIZE(&rTempQue); + + prNeedToFreeQue = &rNeedToFreeQue; + prTempQue = &rTempQue; + + QUEUE_MOVE_ALL(prTempQue, prQue); + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + while (prMsduInfo) { + + if (prMsduInfo->ucNetworkType == eNetworkTypeIdx) { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo); + } else { + /* QUEUE_INSERT_TAIL */ + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo); + } + + QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T); + } + if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) + wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush all TX queues +* +* \param[in] (none) +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_8 ucStaArrayIdx; + UINT_8 ucQueArrayIdx; + + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + + P_QUE_MGT_T prQM = &prAdapter->rQM; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n"); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + /* Concatenate all MSDU_INFOs in per-STA queues */ + for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) { + + /* Always check each STA_REC when flushing packets no matter it is inactive or active */ +#if 0 + if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid) + continue; /* Continue to check the next STA_REC */ +#endif + + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prAdapter-> + arStaRec[ucStaArrayIdx].arTxQueue + [ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]); + } + } + + /* Flush per-Type queues */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) { + + if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))) + continue; /* Continue to check the next TX queue of the same STA */ + + if (!prMsduInfoListHead) { + + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]); + + } + + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL); + } + + return prMsduInfoListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush TX packets for a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* +* \return The flushed packets (in a list of MSDU_INFOs) +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx) +{ + UINT_8 ucQueArrayIdx; + P_MSDU_INFO_T prMsduInfoListHead; + P_MSDU_INFO_T prMsduInfoListTail; + P_STA_RECORD_T prStaRec; + + /* To reduce printk for IOT sta to connect all the time, */ + /* DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); */ + + ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD); + + prMsduInfoListHead = NULL; + prMsduInfoListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */ + for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) { + if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))) + continue; + + if (!prMsduInfoListHead) { + /* The first MSDU_INFO is found */ + prMsduInfoListHead = (P_MSDU_INFO_T) + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]); + prMsduInfoListTail = (P_MSDU_INFO_T) + QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, + QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx])); + + prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); + } + + QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]); + + } + +#if 0 + if (prMsduInfoListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx)); + } else { + prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx); + } +#endif + + return prMsduInfoListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets +* +* \param[in] (none) +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i; + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + prSwRfbListHead = prSwRfbListTail = NULL; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n"); + + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) { + if (!prSwRfbListHead) { + + /* The first MSDU_INFO is found */ + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } else { + /* Concatenate the MSDU_INFO list with the existing list */ + QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail, + QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue))); + + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue)); + } + + QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue)); + + } else { + continue; + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Flush RX packets with respect to a particular STA +* +* \param[in] u4StaRecIdx STA_REC index +* \param[in] u4Tid TID +* +* \return The flushed packets (in a list of SW_RFBs) +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid) +{ + /* UINT_32 i; */ + P_SW_RFB_T prSwRfbListHead; + P_SW_RFB_T prSwRfbListTail; + P_RX_BA_ENTRY_T prReorderQueParm; + P_STA_RECORD_T prStaRec; + + DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx); + + prSwRfbListHead = prSwRfbListTail = NULL; + + prStaRec = &prAdapter->arStaRec[u4StaRecIdx]; + ASSERT(prStaRec); + + /* No matter whether this is an activated STA_REC, do flush */ +#if 0 + if (!prStaRec->fgIsValid) + return NULL; +#endif + + /* Obtain the RX BA Entry pointer */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]); + + /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */ + if (prReorderQueParm) { + + if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) { + + prSwRfbListHead = (P_SW_RFB_T) + QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue)); + prSwRfbListTail = (P_SW_RFB_T) + QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue)); + + QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue)); + + } + } + + if (prSwRfbListTail) { + /* Terminate the MSDU_INFO list with a NULL pointer */ + QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL); + } + return prSwRfbListHead; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enqueue TX packets +* +* \param[in] prMsduInfoListHead Pointer to the list of TX packets +* +* \return The freed packets, which are not enqueued +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead) +{ + P_MSDU_INFO_T prMsduInfoReleaseList; + P_MSDU_INFO_T prCurrentMsduInfo; + P_MSDU_INFO_T prNextMsduInfo; + + P_STA_RECORD_T prStaRec; + QUE_T rNotEnqueuedQue; + P_QUE_T prTxQue = &rNotEnqueuedQue; + + UINT_8 ucPacketType; + UINT_8 ucTC; + P_QUE_MGT_T prQM = &prAdapter->rQM; + UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */ , 1 /*na */ , 0 /*VItoBE */ , 4 /*VOtoVI */ }; + + DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n"); + + ASSERT(prMsduInfoListHead); + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + { + /* UINT_32 i; */ + /* 4 <0> Update TC resource control related variables */ + /* Keep track of the queue length */ + if (--prQM->u4TimeToUpdateQueLen == 0) { /* -- only here */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN; + qmUpdateAverageTxQueLen(prAdapter); + } + } +#endif + + /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */ + prStaRec = NULL; + prMsduInfoReleaseList = NULL; + prCurrentMsduInfo = NULL; + QUEUE_INITIALIZE(&rNotEnqueuedQue); + prNextMsduInfo = prMsduInfoListHead; + + do { + P_BSS_INFO_T prBssInfo; + BOOLEAN fgCheckACMAgain; + ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX; + + prCurrentMsduInfo = prNextMsduInfo; + prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo); + ucTC = TC1_INDEX; + + /* 4 <1> Lookup the STA_REC index */ + /* The ucStaRecIndex will be set in this function */ + qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo); + ucPacketType = HIF_TX_PACKET_TYPE_DATA; + + STATS_ENV_REPORT_DETECT(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + + DBGLOG(QM, LOUD, "***** ucStaRecIndex = %d *****\n", prCurrentMsduInfo->ucStaRecIndex); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]); + +#if (CONF_HIF_LOOPBACK_AUTO == 0) + if (IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) { +#else + /* force to send the loopback test packet */ + if (1) { + SET_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType); + prCurrentMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + ucPacketType = HIF_TX_PKT_TYPE_HIF_LOOPBACK; +#endif /* End of CONF_HIF_LOOPBACK_AUTO */ + + switch (prCurrentMsduInfo->ucStaRecIndex) { + case STA_REC_INDEX_BMCAST: + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucTC = TC5_INDEX; +#if 0 + if (prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX + && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT) { + if (LINK_IS_EMPTY + (&prAdapter->rWifiVar. + arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) { + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_AP_BORADCAST_DROP); + } + } +#endif + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23); + break; + + case STA_REC_INDEX_NOT_FOUND: + ucTC = TC5_INDEX; + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + + /* if the packet is the forward type. the packet should be freed */ + DBGLOG(QM, TRACE, "Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"); + /* prTxQue = &rNotEnqueuedQue; */ + } + prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC]; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24); + + break; + + default: + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex); + + if (!prStaRec) { + DBGLOG(QM, ERROR, "prStaRec is NULL\n"); + break; + } + ASSERT(prStaRec->fgIsValid); + + if (prCurrentMsduInfo->ucUserPriority < 8) { + QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15); + /* QM_DBG_CNT_15 *//* QM_DBG_CNT_16 *//* QM_DBG_CNT_17 *//* QM_DBG_CNT_18 */ + /* QM_DBG_CNT_19 *//* QM_DBG_CNT_20 *//* QM_DBG_CNT_21 *//* QM_DBG_CNT_22 */ + } + + eAci = WMM_AC_BE_INDEX; + do { + fgCheckACMAgain = FALSE; + if (!prStaRec->fgIsQoS) { + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + break; + } + + switch (prCurrentMsduInfo->ucUserPriority) { + case 1: + case 2: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0]; + ucTC = TC0_INDEX; + eAci = WMM_AC_BK_INDEX; + break; + case 0: + case 3: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + break; + case 4: + case 5: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2]; + ucTC = TC2_INDEX; + eAci = WMM_AC_VI_INDEX; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->u4TxNumOfVi++; +#endif + break; + case 6: + case 7: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3]; + ucTC = TC3_INDEX; + eAci = WMM_AC_VO_INDEX; +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + prQM->u4TxNumOfVo++; +#endif + break; + default: + prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1]; + ucTC = TC1_INDEX; + eAci = WMM_AC_BE_INDEX; + ASSERT(0); + break; + } + if (prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci + != WMM_AC_BK_INDEX) { + prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci]; + fgCheckACMAgain = TRUE; + } + } while (fgCheckACMAgain); + + /* LOG_FUNC ("QoS %u UP %u TC %u", */ + /* prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); */ + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + /* + In TDLS or AP mode, peer maybe enter "sleep mode". + + If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode, + we need to wait 60 * u4TimeToAdjustTcResource = 180 packets + u4TimeToAdjustTcResource = 3, + then we will adjust TC resouce for VI or VO. + + But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7, + we will to wait about 12 seconds to collect 180 packets. + but the test time is only 20 seconds. + */ + if ((prQM->u4TxNumOfVi == 10) || (prQM->u4TxNumOfVo == 10)) { + /* force to do TC resouce update */ + prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN; + prQM->u4TimeToAdjustTcResource = 1; + } +#endif +#if ARP_MONITER_ENABLE + if (IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS) + qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo); +#endif + + break; /*default */ + } /* switch (prCurrentMsduInfo->ucStaRecIndex) */ + + if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) { + if (prTxQue->u4NumElem > 32) { + DBGLOG(QM, WARN, + "Drop the Packet for full Tx queue (forwarding) Bss %u\n", + prCurrentMsduInfo->ucNetworkType); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP); + } + } + + } else { + + DBGLOG(QM, WARN, "Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType); + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31); + prTxQue = &rNotEnqueuedQue; + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + } + + /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */ + + /* TODO: Fill MSDU_INFO according to the network type, + * EtherType, and STA status (for PS forwarding control). + */ + + /* Note that the Network Type Index and STA_REC index are determined in + * qmDetermineStaRecIndex(prCurrentMsduInfo). + */ + QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(prCurrentMsduInfo, /* MSDU_INFO ptr */ + ucTC, /* TC tag */ + ucPacketType, /* Packet Type */ + 0, /* Format ID */ + prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */ + prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */ + 0, /* PAL LLH */ + 0, /* ACL SN */ + PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */ + 0 /* PS Session ID */ + ); + + /* 4 <4> Enqueue the packet to different AC queue (max 5 AC queues) */ + QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo); + + if (prTxQue != &rNotEnqueuedQue) { + prQM->u4EnqeueuCounter++; + prQM->au4ResourceWantedCounter[ucTC]++; + } + if (prStaRec) + prStaRec->u4EnqeueuCounter++; + +#if QM_TC_RESOURCE_EMPTY_COUNTER + { + P_TX_CTRL_T prTxCtrl = &prAdapter->rTxCtrl; + + if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] == 0) { + prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]++; + /* + DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n", + ucTC, + prCurrentMsduInfo->ucNetworkType, + prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC])); + */ + } + + } +#endif + +#if QM_TEST_MODE + if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) { + prQM->u4PktCount = 0; + qmTestCases(prAdapter); + } +#endif + + DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem); + } while (prNextMsduInfo); + + if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) { + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL); + prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue); + } + + return prMsduInfoReleaseList; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Determine the STA_REC index for a packet +* +* \param[in] prMsduInfo Pointer to the packet +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_32 i; + + P_STA_RECORD_T prTempStaRec; + /* P_QUE_MGT_T prQM = &prAdapter->rQM; */ + + prTempStaRec = NULL; + + ASSERT(prMsduInfo); + + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) { + /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP. + * FW shall take care of this. The host driver is not able to distinguish these cases. */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST; + DBGLOG(QM, LOUD, "TX with DA = BMCAST\n"); + return; + } +#if (CFG_SUPPORT_TDLS == 1) + /* Check if the peer is TDLS one */ + if (TdlsexStaRecIdxGet(prAdapter, prMsduInfo) == TDLS_STATUS_SUCCESS) + return; /* find a TDLS record */ +#endif /* CFG_SUPPORT_TDLS */ + + /* 4 <2> Check if an AP STA is present */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + + if ((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + + /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsValid) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) { + prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex; + return; + } + } + } + + /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ + prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND; + DBGLOG(QM, LOUD, "QM: TX with STA_REC_INDEX_NOT_FOUND\n"); + +#if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING) + prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a STA_REC for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter, + OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucCurrentQuota, IN UINT_8 ucTotalQuota) +{ + +#if QM_FORWARDING_FAIRNESS + UINT_32 i; /* Loop for */ + + PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */ + PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */ + + P_STA_RECORD_T prStaRec; /* The current focused STA */ + P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */ + P_QUE_T prCurrQueue; /* The current TX queue to dequeue */ + P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */ + + UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */ + UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */ + UINT_32 u4Resource; /* The TX resource amount */ + + BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */ + P_QUE_MGT_T prQM = &prAdapter->rQM; + + PUINT_8 pucFreeQuota = NULL; +#if CFG_ENABLE_WIFI_DIRECT + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; + /*NFC Beam + Indication */ +#endif + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); + + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); + + if (!ucCurrentQuota) { + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + DBGLOG(TX, LOUD, "@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", ucTC, ucCurrentQuota); + return; + } + + u4Resource = ucCurrentQuota; + + /* 4 <1> Determine the head STA */ + /* The head STA shall be an active STA */ + + pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]); + pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]); + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Init Head STA = %u Resource = %u\n", + ucTC, *pu4HeadStaRecIndex, u4Resource); + + /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD + 1; i++) { + prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)]; + ASSERT(prStaRec); + + /* Only Data frame (1x was not included) will be queued in */ + if (prStaRec->fgIsValid) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + /* Determine how many packets the head STA is allowed to send in a round */ + + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25); + u4MaxForwardCount = ucTotalQuota; +#if CFG_ENABLE_WIFI_DIRECT + + pucFreeQuota = NULL; + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ + /* u4MaxForwardCount = ucTotalQuota; */ + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ + /* aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD */) { + + if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } /* fgIsInPS */ +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + + /*NFC Beam + Indication */ + + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) { + if ((prChnlReqInfo->NFC_BEAM != 1) && + (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } else { + if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + /* Determine whether the head STA can continue to forward packets in this round */ + if ((*pu4HeadStaRecForwardCount) < u4MaxForwardCount) + break; + + } /* prStaRec->fgIsValid */ + else { + /* The current Head STA has been deactivated, so search for a new head STA */ + prStaRec = NULL; + prBssInfo = NULL; + (*pu4HeadStaRecIndex)++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + + /* Reset the forwarding count before searching (since this is for a new selected STA) */ + (*pu4HeadStaRecForwardCount) = 0; + } + } /* i < CFG_NUM_OF_STA_RECORD + 1 */ + + /* All STA_RECs are inactive, so exit */ + if (!prStaRec) { + /* Under concurrent, it is possible that there is no candidcated STA. */ + /* DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); */ + return; + } + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Round Head STA = %u\n", ucTC, *pu4HeadStaRecIndex); + + /* 4 <2> Dequeue packets from the head STA */ + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + prDequeuedPkt = NULL; + fgChangeHeadSta = FALSE; + +#if (CFG_SUPPORT_TDLS == 1) + if (pucFreeQuota != NULL) + TdlsexTxQuotaCheck(prAdapter->prGlueInfo, prStaRec, *pucFreeQuota); +#endif /* CFG_SUPPORT_TDLS */ + + while (prCurrQueue) { + +#if QM_DEBUG_COUNTER + + if (ucTC <= TC4_INDEX) { + if (QUEUE_IS_EMPTY(prCurrQueue)) { + QM_DBG_CNT_INC(prQM, ucTC); + /* QM_DBG_CNT_00 *//* QM_DBG_CNT_01 *//* QM_DBG_CNT_02 */ + /* QM_DBG_CNT_03 *//* QM_DBG_CNT_04 */ + } + if (u4Resource == 0) { + QM_DBG_CNT_INC(prQM, ucTC + 5); + /* QM_DBG_CNT_05 *//* QM_DBG_CNT_06 *//* QM_DBG_CNT_07 */ + /* QM_DBG_CNT_08 *//* QM_DBG_CNT_09 */ + } + if (((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { + QM_DBG_CNT_INC(prQM, ucTC + 10); + /* QM_DBG_CNT_10 *//* QM_DBG_CNT_11 *//* QM_DBG_CNT_12 */ + /* QM_DBG_CNT_13 *//* QM_DBG_CNT_14 */ + } + } +#endif + + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) { + fgChangeHeadSta = TRUE; + break; + } else if (u4Resource == 0) { +#if (CFG_SUPPORT_STATISTICS == 1) + prStaRec->u4NumOfNoTxQuota++; +#endif /* CFG_SUPPORT_STATISTICS */ + break; + } + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + if (prDequeuedPkt != NULL) { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(QM, LOUD, " %d\n", u2Identifier); + } + } +#endif +#if DBG && 0 + LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) { + /* XXX: check all queues for STA */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + } + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + u4Resource--; + (*pu4HeadStaRecForwardCount)++; + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + if ((pucFreeQuota) && (*pucFreeQuota > 0)) + *pucFreeQuota = *pucFreeQuota - 1; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->ucBssFreeQuota > 0) + prBssInfo->ucBssFreeQuota--; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + + if (*pu4HeadStaRecForwardCount) { + DBGLOG(QM, LOUD, + "TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC, *pu4HeadStaRecIndex, + (*pu4HeadStaRecForwardCount)); + } +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (prDequeuedPkt) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + + /* 4 <3> Dequeue from the other STAs if there is residual TX resource */ + + /* Check all of the STAs to continue forwarding packets (including the head STA) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + /* Break in case no reasource is available */ + if (u4Resource == 0) { + prQM->au4DequeueNoTcResourceCounter[ucTC]++; + break; + } + + /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */ + prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD]; + ASSERT(prStaRec); + + if (prStaRec->fgIsValid) { + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + + DBGLOG(QM, LOUD, "(Fairness) TID = %u Sharing STA = %u Resource = %u\n", + ucTC, prStaRec->ucIndex, u4Resource); + + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + u4ForwardCount = 0; + u4MaxForwardCount = ucTotalQuota; + +#if CFG_ENABLE_WIFI_DIRECT + pucFreeQuota = NULL; + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */ + /* u4MaxForwardCount = ucTotalQuota; */ + /* Per STA flow control when STA in PS mode */ + /* The PHASE 1: only update from ucFreeQuota (now) */ + /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */ + /* aucFreeQuotaPerQueue[] */ + /* NOTE: other method to set u4Resource */ + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD */) { + + if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) { + u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery; + } else { + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } else { + ASSERT(prStaRec->ucFreeQuotaForDelivery == 0); + u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery; + pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery; + } + + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ +#if CFG_ENABLE_WIFI_DIRECT + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota) + u4MaxForwardCount = prBssInfo->ucBssFreeQuota; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + } /* prStaRec->fgIsValid */ + else { + prBssInfo = NULL; + /* Invalid STA, so check the next STA */ + continue; + } + + while (prCurrQueue) { + /* Three cases to break: (1) No resource (2) No packets (3) Fairness */ + if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)) + break; + + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + +#if DBG && 0 + DBGLOG(QM, LOUD, "Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, + prCurrQueue->u4NumElem, + prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, + prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, + prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11)); + + DBGLOG(QM, LOUD, "Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + + ASSERT(prDequeuedPkt->ucTC == ucTC); + + if (!QUEUE_IS_EMPTY(prCurrQueue)) + /* more data field ? */ + prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED; + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + if (prStaRec) + prStaRec->u4DeqeueuCounter++; + prQM->u4DequeueCounter++; + u4Resource--; + u4ForwardCount++; + +#if CFG_ENABLE_WIFI_DIRECT + /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */ + if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) { + ASSERT(pucFreeQuota); + ASSERT(*pucFreeQuota > 0); + if (*pucFreeQuota > 0) + *pucFreeQuota = *pucFreeQuota - 1; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + +#if CFG_ENABLE_WIFI_DIRECT + ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex); + if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) { + if (prBssInfo->ucBssFreeQuota > 0) + prBssInfo->ucBssFreeQuota--; + } +#endif /* CFG_ENABLE_WIFI_DIRECT */ + + } + +#if QM_BURST_END_INFO_ENABLED + /* Let FW know which packet is the last one dequeued from the STA */ + if (u4ForwardCount) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + } + + if (fgChangeHeadSta) { + (*pu4HeadStaRecIndex)++; + (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD; + (*pu4HeadStaRecForwardCount) = 0; + DBGLOG(QM, LOUD, "(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n", + ucTC, (*pu4HeadStaRecIndex), u4Resource); + } + +/***************************************************************************************/ +#else + UINT_8 ucStaRecIndex; + P_STA_RECORD_T prStaRec; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC); + + if (ucCurrentQuota == 0) + return; + /* 4 <1> Determine the queue index and the head STA */ + + /* The head STA */ + ucStaRecIndex = 0; /* TODO: Get the current head STA */ + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + /* The queue to pull out packets */ + ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX); + prCurrQueue = &prStaRec->arTxQueue[ucTC]; + + ucPktCount = ucCurrentQuota; + prDequeuedPkt = NULL; + + /* 4 <2> Dequeue packets for the head STA */ + while (TRUE) { + if (!(prStaRec->fgIsValid) || ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) { + break; + + } else { + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + /* DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); */ + ASSERT(prDequeuedPkt->ucTC == ucTC); + + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + ucPktCount--; + } + } + + /* DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); */ + +#if QM_BURST_END_INFO_ENABLED + if (prDequeuedPkt) + prDequeuedPkt->fgIsBurstEnd = TRUE; +#endif + + /* 4 <3> Update scheduling info */ + /* TODO */ + + /* 4 <4> Utilize the remainaing TX opportunities for non-head STAs */ + /* TODO */ +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets from a per-Type-based Queue for a particular TC +* +* \param[out] prQue The queue to put the dequeued packets +* \param[in] ucTC The TC index (Shall always be TC5_INDEX) +* \param[in] ucMaxNum The maximum amount of dequeued packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID +qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum) +{ + /* UINT_8 ucQueIndex; */ + /* UINT_8 ucStaRecIndex; */ + P_BSS_INFO_T prBssInfo; + P_BSS_INFO_T parBssInfo; + P_QUE_T prCurrQueue; + UINT_8 ucPktCount; + P_MSDU_INFO_T prDequeuedPkt; + P_MSDU_INFO_T prBurstEndPkt; + QUE_T rMergeQue; + P_QUE_T prMergeQue; + P_QUE_MGT_T prQM; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum); + + /* TC5: Broadcast/Multicast data packets */ + ASSERT(ucTC == TC5_INDEX); + + if (ucMaxNum == 0) + return; + + prQM = &prAdapter->rQM; + /* 4 <1> Determine the queue */ + + prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST]; + ucPktCount = ucMaxNum; + prDequeuedPkt = NULL; + prBurstEndPkt = NULL; + + parBssInfo = prAdapter->rWifiVar.arBssInfo; + + QUEUE_INITIALIZE(&rMergeQue); + prMergeQue = &rMergeQue; + + /* 4 <2> Dequeue packets */ + while (TRUE) { + if (ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) + break; + + QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T); + ASSERT(prDequeuedPkt->ucTC == ucTC); + + ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM); + + prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType]; + + if (IS_BSS_ACTIVE(prBssInfo)) { + if (!prBssInfo->fgIsNetAbsent) { + QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt); + prQM->u4DequeueCounter++; + prBurstEndPkt = prDequeuedPkt; + ucPktCount--; + QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26); +#if DBG && 0 + LOG_FUNC + ("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n", + prDequeuedPkt->ucTC, prCurrQueue->u4NumElem, prDequeuedPkt->ucNetworkType, + prDequeuedPkt->ucMacHeaderLength, prDequeuedPkt->u2FrameLength, + prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, + prDequeuedPkt->fgIs802_11); + + LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr); + +#if LINUX + { + struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket; + + dumpMemory8((PUINT_8) prSkb->data, prSkb->len); + } +#endif + +#endif + } else { + QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt); + } + } else { + QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL); + wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt); + } + } + + if (QUEUE_IS_NOT_EMPTY(prMergeQue)) { + QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue); + QUEUE_MOVE_ALL(prCurrQueue, prMergeQue); + if (QUEUE_GET_TAIL(prCurrQueue)) + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL); + } +#if QM_BURST_END_INFO_ENABLED + if (prBurstEndPkt) + prBurstEndPkt->fgIsBurstEnd = TRUE; +#endif +} /* qmDequeueTxPacketsFromPerTypeQueues */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dequeue TX packets to send to HIF TX +* +* \param[in] prTcqStatus Info about the maximum amount of dequeued packets +* +* \return The list of dequeued TX packets +*/ +/*----------------------------------------------------------------------------*/ +P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ + + INT32 i; + P_MSDU_INFO_T prReturnedPacketListHead; + QUE_T rReturnedQue; + + DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n"); + + QUEUE_INITIALIZE(&rReturnedQue); + + prReturnedPacketListHead = NULL; + + /* dequeue packets from different AC queue based on available aucFreeBufferCount */ + /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */ + for (i = TC4_INDEX; i >= TC0_INDEX; i--) { + DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%d]\n", i); + + /* + in the function, we will re-calculate the ucFreeQuota. + If any packet with any priority for the station will be sent, ucFreeQuota -- + + Note1: ucFreeQuota will be decrease only when station is in power save mode. + In active mode, we will sent the packet to the air directly. + + if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) { + ASSERT(pucFreeQuota); + ASSERT(*pucFreeQuota>0); + if ((pucFreeQuota) && (*pucFreeQuota>0)) { + *pucFreeQuota = *pucFreeQuota - 1; + } + } + + Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw + i.e. default prStaRec->ucFreeQuota = 10 + + Note3: In qmUpdateFreeQuota(), we will adjust + ucFreeQuotaForNonDelivery = ucFreeQuota>>1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + */ + qmDequeueTxPacketsFromPerStaQueues(prAdapter, + &rReturnedQue, + (UINT_8) i, + prTcqStatus->aucFreeBufferCount[i], /* maximum dequeue number */ + prTcqStatus->aucMaxNumOfBuffer[i]); + + /* The aggregate number of dequeued packets */ + DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem); + } + + /* TC5 (BMCAST or STA-NOT-FOUND packets) */ + qmDequeueTxPacketsFromPerTypeQueues(prAdapter, + &rReturnedQue, TC5_INDEX, prTcqStatus->aucFreeBufferCount[TC5_INDEX] + ); + + DBGLOG(QM, LOUD, "Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem); + + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) { + prReturnedPacketListHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rReturnedQue); + QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); + } + + return prReturnedPacketListHead; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Adjust the TC quotas according to traffic demands +* +* \param[out] prTcqAdjust The resulting adjustment +* \param[in] prTcqStatus Info about the current TC quotas and counters +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus) +{ +#if QM_ADAPTIVE_TC_RESOURCE_CTRL + UINT_32 i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Must reset */ + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + + /* 4 <1> If TC resource is not just adjusted, exit directly */ + if (!prQM->fgTcResourcePostAnnealing) + return; + /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */ + else { + INT_32 i4TotalExtraQuota = 0; + INT_32 ai4ExtraQuota[TC_NUM]; + BOOLEAN fgResourceRedistributed = TRUE; + + /* Obtain the free-to-distribute resource */ + for (i = 0; i < TC_NUM; i++) { + ai4ExtraQuota[i] = + (INT_32) prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i]; + + if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */ + + if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]) { + /* + we have residunt TC resources for the TC: + EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5 + ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10 + + so ai4ExtraQuota[] = aucFreeBufferCount[] = 10 + because we available TC resources actually is 10, not 20 + */ + ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i]; + + /* + FALSE means we can re-do TC resource adjustment in tx done + at next time, maybe more tx done is finished + */ + fgResourceRedistributed = FALSE; + } + + /* accumulate current all available TC resources */ + i4TotalExtraQuota += ai4ExtraQuota[i]; + + /* deduce unused TC resources for the TC */ + prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); + } + } + + /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */ + for (i = 0; i < TC_NUM; i++) { + if (ai4ExtraQuota[i] < 0) { + + /* The TC needs extra resources */ + if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) { + /* the number of needed extra resources is larger than total available */ + ai4ExtraQuota[i] = (-i4TotalExtraQuota); + + /* wait for next tx done to do adjustment */ + fgResourceRedistributed = FALSE; + } + + /* decrease the total available */ + i4TotalExtraQuota += ai4ExtraQuota[i]; + + /* mark to increase TC resources for the TC */ + prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]); + } + } + + /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */ + + /* + if fgResourceRedistributed == TRUE, it means we will adjust at this time so + we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE). + */ + prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed); + +#if QM_PRINT_TC_RESOURCE_CTRL + DBGLOG(QM, LOUD, "QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n", + prTcqStatus->aucFreeBufferCount[0], + prTcqStatus->aucFreeBufferCount[1], + prTcqStatus->aucFreeBufferCount[2], + prTcqStatus->aucFreeBufferCount[3], + prTcqStatus->aucFreeBufferCount[4], prTcqStatus->aucFreeBufferCount[5] + )); +#endif + } + +#else + UINT_32 i; + + for (i = 0; i < TC_NUM; i++) + prTcqAdjust->acVariation[i] = 0; + +#endif +} + +#if QM_ADAPTIVE_TC_RESOURCE_CTRL +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update the average TX queue length for the TC resource control mechanism +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter) +{ + INT_32 u4CurrQueLen, i, k; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */ + /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */ + for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++) { + u4CurrQueLen = 0; + + for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++) { + prStaRec = &prAdapter->arStaRec[k]; + ASSERT(prStaRec); + + /* If the STA is activated, get the queue length */ + if (prStaRec->fgIsValid && + (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent) + ) { + + u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem); + } + } + + if (prQM->au4AverageQueLen[i] == 0) { + prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); /* *8 */ + } else { + /* len => len - len/8 = 7/8 * len + new len */ + prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[i] += (u4CurrQueLen); + } + + } + + /* Update the queue length for TC5 (BMCAST) */ + u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem; + + if (prQM->au4AverageQueLen[TC_NUM - 1] == 0) { + prQM->au4AverageQueLen[TC_NUM - 1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); + } else { + prQM->au4AverageQueLen[TC_NUM - 1] -= + (prQM->au4AverageQueLen[TC_NUM - 1] >> QM_QUE_LEN_MOVING_AVE_FACTOR); + prQM->au4AverageQueLen[TC_NUM - 1] += (u4CurrQueLen); + } + + /* 4 <2> Adjust TC resource assignment every 3 times */ + /* Check whether it is time to adjust the TC resource assignment */ + if (--prQM->u4TimeToAdjustTcResource == 0) { /* u4TimeToAdjustTcResource = 3 */ + + /* The last assignment has not been completely applied */ + if (prQM->fgTcResourcePostAnnealing) { + /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */ + + /* wait for next time to do qmReassignTcResource */ + prQM->u4TimeToAdjustTcResource = 1; + } else { /* The last assignment has been applied */ + prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC; + qmReassignTcResource(prAdapter); + } + } + + /* Debug */ +#if QM_PRINT_TC_RESOURCE_CTRL + for (i = 0; i < TC_NUM; i++) { + if (QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100) { + DBGLOG(QM, LOUD, "QM: QueLen [%u %u %u %u %u %u]\n", + QM_GET_TX_QUEUE_LEN(prAdapter, 0), + QM_GET_TX_QUEUE_LEN(prAdapter, 1), + QM_GET_TX_QUEUE_LEN(prAdapter, 2), + QM_GET_TX_QUEUE_LEN(prAdapter, 3), + QM_GET_TX_QUEUE_LEN(prAdapter, 4), QM_GET_TX_QUEUE_LEN(prAdapter, 5) + )); + break; + } + } +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Assign TX resource for each TC according to TX queue length and current assignment +* +* \param (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter) +{ + INT_32 i4TotalResourceDemand = 0; + UINT_32 u4ResidualResource = 0; + UINT_32 i; + INT_32 ai4PerTcResourceDemand[TC_NUM]; + UINT_32 u4ShareCount = 0; + UINT_32 u4Share = 0; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to + * start the TC-quota adjusting procedure, which will be invoked upon every TX Done + */ + /* tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq() + * -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing */ + + /* 4 <1> Determine the demands */ + /* Determine the amount of extra resource to fulfill all of the demands */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4, which is not adjustable */ + if (i == TC4_INDEX) + continue; + + /* + Define: extra_demand = average que_length (includes all station records) + + min_reserved_quota - + current available TC resources + + extra_demand means we need extra TC resources to transmit; other TCs can + borrow their resources to us? + */ + ai4PerTcResourceDemand[i] = + ((UINT_32) (QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]); + + /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */ + if (QM_GET_TX_QUEUE_LEN(prAdapter, i)) + ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; /* 0 */ + + /* + accumulate all needed extra TC resources + maybe someone need + resource, maybe someone need - resource + */ + i4TotalResourceDemand += ai4PerTcResourceDemand[i]; + } + + /* 4 <2> Case 1: Demand <= Total Resource */ + if (i4TotalResourceDemand <= 0) { + /* 4 <2.1> Satisfy every TC */ + /* total TC resources are enough, no extra TC resources is needed */ + + /* adjust used TC resources to average TC resources + min reserve TC resources */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + /* + the number of resources that one TC releases can be used for + other TCs + + EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5 + TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5 + => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5 + TC1 au4CurrentTcResource[1] = 5 + (+5) = 10 + */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + } + + /* 4 <2.2> Share the residual resource evenly */ + u4ShareCount = (TC_NUM - 1); /* 5, excluding TC4 */ + + /* + EX: i4TotalResourceDemand = -10 + means we have 10 available resources can be used. + */ + u4ResidualResource = (UINT_32) (-i4TotalResourceDemand); + u4Share = (u4ResidualResource / u4ShareCount); + + /* share available TC resources to all TCs averagely */ + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + /* allocate residual average resources to the TC */ + prQM->au4CurrentTcResource[i] += u4Share; + + /* Every TC is fully satisfied so no need extra resources */ + ai4PerTcResourceDemand[i] = 0; + + /* decrease the allocated resources */ + u4ResidualResource -= u4Share; + } + + /* if still have available resources, we decide to give them to VO (TC3) queue */ + /* 4 <2.3> Allocate the left resource to TC3 (VO) */ + prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource); + + } + /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */ + else { + /* + u4ResidualResource means we at least need to keep + QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources + + in 6628, u4ResidualResource = 26, max 28 + */ + u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE; + + /* 4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand) */ + for (i = 0; i < TC_NUM; i++) { + + if (i == TC4_INDEX) + continue; /* Skip TC4 (not adjustable) */ + + /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */ + + /* + ai4PerTcResourceDemand[i] = + ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + prQM->au4MinReservedTcResource[i] - + prQM->au4CurrentTcResource[i]); + + so au4CurrentTcResource + ai4PerTcResourceDemand = + + ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + + prQM->au4MinReservedTcResource[i] = + + current average queue len + min TC resources + */ + if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < + prQM->au4GuaranteedTcResource[i]) { + + /* avg queue len + min reserve still smaller than guarantee so enough */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + + /* accumulate available TC resources from the TC */ + u4ResidualResource += + (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + ai4PerTcResourceDemand[i] = 0; + } + + /* The demand can not be fulfilled with the guaranteed resource amount */ + else { + + /* means even we use all guarantee resources for the TC is still not enough */ + + /* + guarantee number is always for the TC so extra resource number cannot + include the guarantee number. + + EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5 + ai4PerTcResourceDemand = 6 + + ai4PerTcResourceDemand -= (10 - 5) ==> 1 + only need extra 1 TC resouce is enough. + */ + ai4PerTcResourceDemand[i] -= + (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]); + + /* update current avg TC resource to guarantee number */ + prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i]; + + /* count how many TC queues need to get extra resources */ + u4ShareCount++; + } + } + + /* 4 <3.2> Allocate the residual resource */ + do { + /* If there is no resource left, exit directly */ + if (u4ResidualResource == 0) + break; + + /* This shall not happen */ + if (u4ShareCount == 0) { + prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource; + DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n"); + break; + } + + /* Share the residual resource evenly */ + u4Share = (u4ResidualResource / u4ShareCount); + + if (u4Share) { + for (i = 0; i < TC_NUM; i++) { + /* Skip TC4 (not adjustable) */ + if (i == TC4_INDEX) + continue; + + if (ai4PerTcResourceDemand[i] == 0) + continue; + + if (ai4PerTcResourceDemand[i] - u4Share) { + /* still not enough but we just can give it u4Share resources */ + prQM->au4CurrentTcResource[i] += u4Share; + u4ResidualResource -= u4Share; + ai4PerTcResourceDemand[i] -= u4Share; + } else { + /* enough */ + prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i]; + u4ResidualResource -= ai4PerTcResourceDemand[i]; + ai4PerTcResourceDemand[i] = 0; + } + } + } + + if (u4ResidualResource == 0) + break; + /* By priority, allocate the left resource that is not divisible by u4Share */ + + if (ai4PerTcResourceDemand[TC3_INDEX]) { /* VO */ + prQM->au4CurrentTcResource[TC3_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC2_INDEX]) { /* VI */ + prQM->au4CurrentTcResource[TC2_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC5_INDEX]) { /* BMCAST */ + prQM->au4CurrentTcResource[TC5_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC1_INDEX]) { /* BE */ + prQM->au4CurrentTcResource[TC1_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + if (ai4PerTcResourceDemand[TC0_INDEX]) { /* BK */ + prQM->au4CurrentTcResource[TC0_INDEX]++; + if (--u4ResidualResource == 0) + break; + } + + /* Allocate the left resource */ + prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource; + + } while (FALSE); + } + + /* mark the flag that we can start to do TC resource adjustment after TX done handle */ + prQM->fgTcResourcePostAnnealing = TRUE; + +#if QM_PRINT_TC_RESOURCE_CTRL + /* Debug print */ + DBGLOG(QM, LOUD, "QM: TC Rsc %u %u %u %u %u %u\n", + prQM->au4CurrentTcResource[0], + prQM->au4CurrentTcResource[1], + prQM->au4CurrentTcResource[2], + prQM->au4CurrentTcResource[3], prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5] + )); +#endif + +} + +#endif + +/*----------------------------------------------------------------------------*/ +/* RX-Related Queue Management */ +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief Init Queue Management for RX +* +* \param[in] (none) +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter) +{ + /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle RX packets (buffer reordering) +* +* \param[in] prSwRfbListHead The list of RX packets +* +* \return The list of packets which are not buffered for reordering +*/ +/*----------------------------------------------------------------------------*/ +P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead) +{ + +#if CFG_RX_REORDERING_ENABLED + /* UINT_32 i; */ + P_SW_RFB_T prCurrSwRfb; + P_SW_RFB_T prNextSwRfb; + P_HIF_RX_HEADER_T prHifRxHdr; + QUE_T rReturnedQue; + PUINT_8 pucEthDestAddr; + BOOLEAN fgIsBMC; + + /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ + + DEBUGFUNC("qmHandleRxPackets"); + + ASSERT(prSwRfbListHead); + + QUEUE_INITIALIZE(&rReturnedQue); + prNextSwRfb = prSwRfbListHead; + + do { + prCurrSwRfb = prNextSwRfb; + prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb); + + prHifRxHdr = prCurrSwRfb->prHifRxHdr; /* TODO: (Tehuang) Use macro to obtain the pointer */ + + /* TODO: (Tehuang) Check if relaying */ + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST; + + /* Decide the Destination */ +#if CFG_RX_PKTS_DUMP + if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) { + DBGLOG(SW4, INFO, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n", + (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr), + prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx, + (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */ + (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr), + prCurrSwRfb->ucPacketType, + (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)); + + DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen); + } +#endif + + fgIsBMC = FALSE; + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { + + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */ + /* */ + + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode)) + fgIsBMC = TRUE; + + if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem > + (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)) { + + if (!IS_BSS_ACTIVE(prBssInfo)) { + DBGLOG(QM, WARN, "Mark NULL the Packet for inactive Bss %u\n", ucNetTypeIdx); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + if (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) { + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) && + bssGetClientByAddress(prBssInfo, pucEthDestAddr)) + prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD; + /* TODO : need to check the dst mac is valid */ + /* If src mac is invalid, the packet will be freed in fw */ + } /* OP_MODE_ACCESS_POINT */ +#if CFG_SUPPORT_HOTSPOT_2_0 + else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) && + hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) { + DBGLOG(QM, WARN, + "Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } +#endif + } else { + /* Dont not occupy other SW RFB */ + DBGLOG(QM, WARN, "Mark NULL the Packet for less Free Sw Rfb\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + + } +#if CFG_SUPPORT_WAPI + if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) { + PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader; + UINT_16 u2Etype = 0; + + u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]); + + /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode. + if we received any WPI(0x88b4) packet that is encrypted, drop here. */ + if (u2Etype == ETH_WPI_1X && HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr) != 0) { + DBGLOG(QM, INFO, "drop wpi packet with sec mode\n"); + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + continue; + } + } +#endif + /* BAR frame */ + if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL; + qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue); + } + /* Reordering is not required for this packet, return it without buffering */ + else if (!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC) { +#if 0 + if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) { + UINT_8 ucNetTypeIdx; + P_BSS_INFO_T prBssInfo; + + pucEthDestAddr = prCurrSwRfb->pvHeader; + ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]); + + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) + && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)) { + prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD; + } + } +#endif + QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb); + } + /* Reordering is required for this packet */ + else { + /* If this packet should dropped or indicated to the host immediately, + * it should be enqueued into the rReturnedQue with specific flags. If + * this packet should be buffered for reordering, it should be enqueued + * into the reordering queue in the STA_REC rather than into the + * rReturnedQue. + */ + qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue); + + } + } while (prNextSwRfb); + + /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */ + /* The returned list of SW_RFBs must end with a NULL pointer */ + if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) + QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(&rReturnedQue), NULL); + + return (P_SW_RFB_T) QUEUE_GET_HEAD(&rReturnedQue); + +#else + + /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */ + return prSwRfbListHead; + +#endif + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reorder the received packet +* +* \param[in] prSwRfb The RX packet to process +* \param[out] prReturnedQue The queue for indicating packets +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) +{ + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SeqNo; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + /* P_SW_RFB_T prReorderedSwRfb; */ + BOOLEAN fgIsBaTimeout; + + DEBUGFUNC("qmProcessPktWithReordering"); + + if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { + ASSERT(FALSE); + return; + } + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */ + prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); + /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ + + /* Incorrect STA_REC index */ + if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); + /* ASSERT(0); */ + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for an invalid STA_REC\n"); + /* ASSERT(0); */ + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + DBGLOG(QM, WARN, "Reordering for a NULL ReorderQueParm\n"); + /* ASSERT(0); */ + return; + } + + /* Start to reorder packets */ + u4SeqNo = (UINT_32) (prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); + + /* Debug */ + /* DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ + + /* Case 1: Fall within */ + if /* 0 - start - sn - end - 4095 */ + (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd)) + /* 0 - end - start - sn - 4095 */ + || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo)) + /* 0 - sn - end - start - 4095 */ + || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))) { + + qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* Let the first received packet pass the reorder check */ + DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); + + prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; + } +#endif + + if (qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue, &fgIsBaTimeout) == FALSE) + STATS_RX_REORDER_HOLE_INC(prStaRec); /* record hole count */ + STATS_RX_REORDER_HOLE_TIMEOUT_INC(prStaRec, fgIsBaTimeout); + } + /* Case 2: Fall ahead */ + else if + /* 0 - start - end - sn - (start+2048) - 4095 */ + (((u4WinStart < u4WinEnd) + && (u4WinEnd < u4SeqNo) + && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - sn - (start+2048) - start - end - 4095 */ + || ((u4SeqNo < u4WinStart) + && (u4WinStart < u4WinEnd) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT))) + /* 0 - end - sn - (start+2048) - start - 4095 */ + || ((u4WinEnd < u4SeqNo) + && (u4SeqNo < u4WinStart) + && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))) { + +#if QM_RX_WIN_SSN_AUTO_ADVANCING + if (prReorderQueParm->fgIsWaitingForPktWithSsn) + prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE; +#endif + + qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue); + + /* Advance the window after inserting a new tail */ + prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo; + prReorderQueParm->u2WinStart = + (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1) + % MAX_SEQ_NO_COUNT); + + qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); + + STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec); + + } + /* Case 3: Fall behind */ + else { + +#if QM_RX_WIN_SSN_AUTO_ADVANCING +#if QM_RX_INIT_FALL_BEHIND_PASS + if (prReorderQueParm->fgIsWaitingForPktWithSsn) { + /* ?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + /* DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ + return; + } +#endif +#endif + + STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec); + /* An erroneous packet */ + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + /* DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */ + return; + } + + return; + +} + +VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue) +{ + + P_STA_RECORD_T prStaRec; + P_HIF_RX_HEADER_T prHifRxHdr; + P_RX_BA_ENTRY_T prReorderQueParm; + + UINT_32 u4SSN; + UINT_32 u4WinStart; + UINT_32 u4WinEnd; + P_QUE_T prReorderQue; + /* P_SW_RFB_T prReorderedSwRfb; */ + + if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) { + ASSERT(FALSE); + return; + } + + prHifRxHdr = prSwRfb->prHifRxHdr; + prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx; + prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */ + prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr)); + + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + + /* Incorrect STA_REC index */ + if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx); + /* ASSERT(0); */ + return; + } + + /* Check whether the STA_REC is activated */ + prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]); + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + DbgPrint("QM: (Warning) BAR for an invalid STA_REC\n"); + /* ASSERT(0); */ + return; + } +#endif + + /* Check whether the BA agreement exists */ + prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]); + if (!prReorderQueParm) { + /* TODO: (Tehuang) Handle the Host-FW sync issue. */ + DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL ReorderQueParm\n"); + /* ASSERT(0); */ + return; + } + + u4SSN = (UINT_32) (prSwRfb->u2SSN); + prReorderQue = &(prReorderQueParm->rReOrderQue); + u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart); + u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd); + + if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) { + prReorderQueParm->u2WinStart = (UINT_16) u4SSN; + prReorderQueParm->u2WinEnd = + ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT; + DBGLOG(QM, TRACE, + "QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, + prReorderQueParm->u2WinEnd); + qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue); + } else { + DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd); + } +} + +VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + P_SW_RFB_T prExaminedQueuedSwRfb; + P_QUE_T prReorderQue; + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + + /* There are no packets queued in the Reorder Queue */ + if (prExaminedQueuedSwRfb == NULL) { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; + prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb; + prReorderQue->u4NumElem++; + } + + /* Determine the insert position */ + else { + do { + /* Case 1: Terminate. A duplicate packet */ + if (((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))) { + prSwRfb->eDst = RX_PKT_DESTINATION_NULL; + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb); + return; + } + + /* Case 2: Terminate. The insert point is found */ + else if (qmCompareSnIsLessThan((prSwRfb->u2SSN), (prExaminedQueuedSwRfb->u2SSN))) + break; + + /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */ + else + prExaminedQueuedSwRfb = (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext); + } while (prExaminedQueuedSwRfb); + + /* Update the Reorder Queue Parameters according to the found insert position */ + if (prExaminedQueuedSwRfb == NULL) { + /* The received packet shall be placed at the tail */ + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb); + prReorderQue->prTail = (P_QUE_ENTRY_T) (prSwRfb); + } else { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = (P_QUE_ENTRY_T) prExaminedQueuedSwRfb; + if (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb) == (prReorderQue->prHead)) { + /* The received packet will become the head */ + prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; + } else { + (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T) prSwRfb; + } + ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T) prSwRfb; + } + + prReorderQue->u4NumElem++; + + } + +} + +VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + P_QUE_T prReorderQue; + + ASSERT(prSwRfb); + ASSERT(prReorderQueParm); + ASSERT(prReturnedQue); + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + /* There are no packets queued in the Reorder Queue */ + if (QUEUE_IS_EMPTY(prReorderQue)) { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb; + } else { + ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail; + ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL; + (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb); + } + prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb; + prReorderQue->u4NumElem++; + +} + +BOOLEAN +qmPopOutDueToFallWithin(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead, fgMissing; + OS_SYSTIME rCurrentTime, *prMissTimeout; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + *fgIsTimeout = FALSE; + fgMissing = FALSE; + rCurrentTime = 0; + prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]); + if ((*prMissTimeout)) { + fgMissing = TRUE; + GET_CURRENT_SYSTIME(&rCurrentTime); + } + + /* Check whether any packet can be indicated to the higher layer */ + while (TRUE) { + if (QUEUE_IS_EMPTY(prReorderQue)) + break; + + /* Always examine the head packet */ + prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + } + /* SN > WinStart, break to update WinEnd */ + else { + if ((fgMissing == TRUE) && + CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout), + MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) { + DBGLOG(QM, TRACE, + "QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid, + prReorderedSwRfb->u2SSN); + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + + fgMissing = FALSE; + *fgIsTimeout = TRUE; + } else + break; + } + + /* Dequeue the head packet */ + if (fgDequeuHead) { + + if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + /* DbgPrint("QM: [%d] %d (%d)\n", + prReorderQueParm->ucTid, + prReorderedSwRfb->u2PacketLen, + prReorderedSwRfb->u2SSN); */ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); + } + } + + if (QUEUE_IS_EMPTY(prReorderQue)) + *prMissTimeout = 0; + else { + if (fgMissing == FALSE) + GET_CURRENT_SYSTIME(prMissTimeout); + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + return QUEUE_IS_EMPTY(prReorderQue); +} + +VOID qmPopOutDueToFallAhead(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue) +{ + P_SW_RFB_T prReorderedSwRfb; + P_QUE_T prReorderQue; + BOOLEAN fgDequeuHead; + + prReorderQue = &(prReorderQueParm->rReOrderQue); + + /* Check whether any packet can be indicated to the higher layer */ + while (TRUE) { + if (QUEUE_IS_EMPTY(prReorderQue)) + break; + + /* Always examine the head packet */ + prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue); + fgDequeuHead = FALSE; + + /* SN == WinStart, so the head packet shall be indicated (advance the window) */ + if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) { + + fgDequeuHead = TRUE; + prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT); + } + + /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */ + else if (qmCompareSnIsLessThan((UINT_32) (prReorderedSwRfb->u2SSN), + (UINT_32) (prReorderQueParm->u2WinStart))) + fgDequeuHead = TRUE; + + /* SN > WinStart, break to update WinEnd */ + else + break; + + /* Dequeue the head packet */ + if (fgDequeuHead) { + + if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) { + prReorderQue->prHead = NULL; + prReorderQue->prTail = NULL; + } else { + prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext; + (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL; + } + prReorderQue->u4NumElem--; + /* DbgPrint("QM: [%d] %d (%d)\n", */ + /* prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); */ + QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb); + } + } + + /* After WinStart has been determined, update the WinEnd */ + prReorderQueParm->u2WinEnd = + (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT); + +} + +BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater) +{ + /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */ + if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) /* Shall be <= */ + return FALSE; + + /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */ + else if ((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess) + return TRUE; + + /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */ + /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */ + else if (u4SnLess < u4SnGreater) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle Mailbox RX messages +* +* \param[in] prMailboxRxMsg The received Mailbox message from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg) +{ + /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */ + /* TODO */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle ADD RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_RX_ADDBA_T prEventRxAddBa; + P_STA_RECORD_T prStaRec; + UINT_32 u4Tid; + UINT_32 u4WinSize; + + DBGLOG(QM, INFO, "QM:Event +RxBa\n"); + + prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx); + + if (!prStaRec) { + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"); + return; + } +#if 0 + if (!(prStaRec->fgIsValid)) { + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"); + /* ASSERT(0); */ + /* return; */ + } +#endif + + u4Tid = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_TID_MASK) + >> BA_PARAM_SET_TID_MASK_OFFSET); + + u4WinSize = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK) + >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET); + + if (!qmAddRxBaEntry(prAdapter, + prStaRec->ucIndex, + (UINT_8) u4Tid, + (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), (UINT_16) u4WinSize)) { + + /* FW shall ensure the availabiilty of the free-to-use BA entry */ + DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n"); + ASSERT(0); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle DEL RX BA Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_RX_DELBA_T prEventRxDelBa; + P_STA_RECORD_T prStaRec; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventRxDelBa = (P_EVENT_RX_DELBA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx); + + if (!prStaRec) + /* Invalid STA_REC index, discard the event packet */ + /* ASSERT(0); */ + return; +#if 0 + if (!(prStaRec->fgIsValid)) + /* TODO: (Tehuang) Handle the Host-FW synchronization issue */ + /* ASSERT(0); */ + return; +#endif + + qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE); + +} + +P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIdx, UINT_8 ucTid) +{ + int i; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + /* DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); */ + + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (prQM->arRxBaTable[i].fgIsValid) { + if ((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && (prQM->arRxBaTable[i].ucTid == ucTid)) + return &prQM->arRxBaTable[i]; + } + } + return NULL; +} + +BOOLEAN +qmAddRxBaEntry(IN P_ADAPTER_T prAdapter, + IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize) +{ + int i; + P_RX_BA_ENTRY_T prRxBaEntry = NULL; + P_STA_RECORD_T prStaRec; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); + + if (ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) { + /* Invalid STA_REC index, discard the event packet */ + DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx); + return FALSE; + } + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + + /* if(!(prStaRec->fgIsValid)){ */ + /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */ + /* return FALSE; */ + /* } */ + + /* 4 <1> Delete before adding */ + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid)) + qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */ + /* 4 <2> Add a new BA entry */ + /* No available entry to store the BA agreement info. Retrun FALSE. */ + if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) { + DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount); + return FALSE; + } + /* Find the free-to-use BA entry */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + if (!prQM->arRxBaTable[i].fgIsValid) { + prRxBaEntry = &(prQM->arRxBaTable[i]); + prQM->ucRxBaCount++; + DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); + break; + } + } + /* If a free-to-use entry is found, configure it and associate it with the STA_REC */ + u2WinSize += CFG_RX_BA_INC_SIZE; + if (prRxBaEntry) { + prRxBaEntry->ucStaRecIdx = ucStaRecIdx; + prRxBaEntry->ucTid = ucTid; + prRxBaEntry->u2WinStart = u2WinStart; + prRxBaEntry->u2WinSize = u2WinSize; + prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT); + prRxBaEntry->fgIsValid = TRUE; + prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE; + + g_arMissTimeout[ucStaRecIdx][ucTid] = 0; + + DBGLOG(QM, INFO, "QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n", + ucStaRecIdx, ucTid, + prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize); + + /* Update the BA entry reference table for per-packet lookup */ + prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry; + } else { + /* This shall not happen because FW should keep track of the usage of RX BA entries */ + DBGLOG(QM, ERROR, "QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount); + return FALSE; + } + return TRUE; +} + +VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost) +{ + P_RX_BA_ENTRY_T prRxBaEntry; + P_STA_RECORD_T prStaRec; + P_SW_RFB_T prFlushedPacketList = NULL; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD); + + prStaRec = &prAdapter->arStaRec[ucStaRecIdx]; + ASSERT(prStaRec); + +#if 0 + if (!(prStaRec->fgIsValid)) { + DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA\n"); + return; + } +#endif + + /* Remove the BA entry for the same (STA, TID) tuple if it exists */ + prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid]; + + if (prRxBaEntry) { + + prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid); + + if (prFlushedPacketList) { + + if (fgFlushToHost) { + wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList); + } else { + + P_SW_RFB_T prSwRfb; + P_SW_RFB_T prNextSwRfb; + + prSwRfb = prFlushedPacketList; + + do { + prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb); + nicRxReturnRFB(prAdapter, prSwRfb); + prSwRfb = prNextSwRfb; + } while (prSwRfb); + + } + + } +#if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0)) + /* Update RX BA entry state. Note that RX queue flush is not done here */ + prRxBaEntry->fgIsValid = FALSE; + prQM->ucRxBaCount--; + + /* Debug */ +#if 0 + DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount); +#endif + + /* Update STA RX BA table */ + prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL; +#endif + + DBGLOG(QM, INFO, "QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid); + + } + + /* Debug */ +#if CFG_HIF_RX_STARVATION_WARNING + { + P_RX_CTRL_T prRxCtrl; + + prRxCtrl = &prAdapter->rRxCtrl; + DBGLOG(QM, TRACE, + "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt, + prRxCtrl->u4DequeuedCnt); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_8 ucQosInfo; + UINT_8 ucQosInfoAC; + UINT_8 ucBmpAC; + + DEBUGFUNC("mqmProcessAssocReq"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prStaRec->fgIsQoS = FALSE; + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + pucIEStart = pucIE; + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + /* Determine whether QoS is enabled with the association */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + prStaRec->fgIsWmmSupported = TRUE; + + prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE; + ucQosInfo = prIeWmmInfo->ucQosInfo; + ucQosInfoAC = ucQosInfo & BITS(0, 3); + + prStaRec->fgIsUapsdSupported = ((ucQosInfoAC) ? TRUE : FALSE) & + prAdapter->rWifiVar.fgSupportUAPSD; + + ucBmpAC = 0; + + if (ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) + ucBmpAC |= BIT(ACI_VO); + if (ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) + ucBmpAC |= BIT(ACI_VI); + if (ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) + ucBmpAC |= BIT(ACI_BE); + if (ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) + ucBmpAC |= BIT(ACI_BK); + + prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC; + + prStaRec->ucUapsdSp = + (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5; + break; + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + + break; + + case ELEM_ID_HT_CAP: + /* Some client won't put the WMM IE if client is 802.11n */ + if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + default: + break; + } + } + + DBGLOG(QM, TRACE, "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To process WMM related IEs in ASSOC_RSP +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + PUINT_8 pucIEStart; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + DEBUGFUNC("mqmProcessAssocRsp"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + prStaRec->fgIsQoS = FALSE; + + pucIEStart = pucIE; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n", + prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS); + + /* If the device does not support QoS or if WMM is not supported by the peer, exit. */ + /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */ + if ((!prAdapter->rWifiVar.fgSupportQoS)) + return; + + /* Determine whether QoS is enabled with the association */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + prStaRec->fgIsQoS = TRUE; + break; + + default: + /* Other WMM QoS IEs. Ignore any */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */ + break; + + case ELEM_ID_HT_CAP: + /* Some AP won't put the WMM IE if client is 802.11n */ + if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) + prStaRec->fgIsQoS = TRUE; + break; + default: + break; + } + } + + /* Parse AC parameters and write to HW CRs */ + if ((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) { + mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE); +#if ARP_MONITER_ENABLE + qmResetArpDetect(); +#endif + } + + DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS); + if (prStaRec->fgIsWmmSupported) + nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prSwRfb The received frame +* \param[in] pucIE The pointer to the first IE in the frame +* \param[in] u2IELength The total length of IEs in the frame +* \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs. +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter, + IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride) +{ + P_STA_RECORD_T prStaRec; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + P_BSS_INFO_T prBssInfo; + P_AC_QUE_PARMS_T prAcQueParams; + P_IE_WMM_PARAM_T prIeWmmParam; + ENUM_WMM_ACI_T eAci; + PUINT_8 pucWmmParamSetCount; + + DEBUGFUNC("mqmParseEdcaParameters"); + + ASSERT(prSwRfb); + ASSERT(pucIE); + + prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx); + ASSERT(prStaRec); + if (prStaRec == NULL) + return; + + DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS); + + if ((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)) + return; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + /* Goal: Obtain the EDCA parameters */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) != VENDOR_OUI_TYPE_WMM) || + (kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) + break; + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount); + prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE; + + /* Check the Parameter Set Count to determine whether EDCA parameters */ + /* have been changed */ + if (!fgForceOverride && (*pucWmmParamSetCount + == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT))) + break; /* Ignore the IE without updating HW CRs */ + + /* Update Parameter Set Count */ + *pucWmmParamSetCount = + (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT); + + /* Update EDCA parameters */ + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + prAcQueParams = &prBssInfo->arACQueParms[eAci]; + mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams); + + prAcQueParams->fgIsACMSet = + (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE; + prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN; + + DBGLOG(QM, LOUD, + "eAci:%d, ACM:%d, Aifsn:%d, CWmin:%d, CWmax:%d, TxopLmt:%d\n", + eAci, prAcQueParams->fgIsACMSet, prAcQueParams->u2Aifsn, + prAcQueParams->u2CWmin, prAcQueParams->u2CWmax, + prAcQueParams->u2TxopLimit); + } + break; + default: + /* Other WMM QoS IEs. Ignore */ + break; + } + + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + break; + default: + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE +* +* \param[in] prAdapter Adapter pointer +* \param[in] prIeWmmParam The pointer to the WMM Parameter IE +* \param[in] u4AcOffset The offset specifying the AC queue for parsing +* \param[in] prHwAcParams The parameter structure used to configure the HW CRs +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams) +{ + prAcQueParams->u2Aifsn = *((PUINT_8) (&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4)); + + prAcQueParams->u2CWmax = BIT(((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK) + >> WMM_ECW_WMAX_OFFSET) - 1; + + prAcQueParams->u2CWmin = + BIT((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK) - 1; + + WLAN_GET_FIELD_16(((PUINT_8) (&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)), + &(prAcQueParams->u2TxopLimit)); + + prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To parse WMM/11n related IEs in scan results (only for AP peers) +* +* \param[in] prAdapter Adapter pointer +* \param[in] prScanResult The scan result which shall be parsed to obtain needed info +* \param[out] prStaRec The obtained info is stored in the STA_REC +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +#if (CFG_SUPPORT_TDLS == 1) /* for test purpose */ +BOOLEAN flgTdlsTestExtCapElm = FALSE; +UINT8 aucTdlsTestExtCapElm[7]; +#endif /* CFG_SUPPORT_TDLS */ +VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec) +{ + PUINT_8 pucIE; + UINT_16 u2IELength; + UINT_16 u2Offset; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + DEBUGFUNC("mqmProcessScanResult"); + + ASSERT(prScanResult); + ASSERT(prStaRec); + + /* Reset the flag before parsing */ + prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE; + + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + u2IELength = prScanResult->u2IELength; + pucIE = prScanResult->aucIEBuf; + +#if (CFG_SUPPORT_TDLS == 1) + /* TDLS test purpose */ + if (flgTdlsTestExtCapElm == TRUE) + TdlsexBssExtCapParse(prStaRec, aucTdlsTestExtCapElm); +#endif /* CFG_SUPPORT_TDLS */ + + /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */ + IE_FOR_EACH(pucIE, u2IELength, u2Offset) { + switch (IE_ID(pucIE)) { + case ELEM_ID_EXTENDED_CAP: +#if (CFG_SUPPORT_TDLS == 1) + TdlsexBssExtCapParse(prStaRec, pucIE); +#endif /* CFG_SUPPORT_TDLS */ + break; + + case ELEM_ID_WMM: + if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) && + (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) { + + switch (WMM_IE_OUI_SUBTYPE(pucIE)) { + case VENDOR_OUI_SUBTYPE_WMM_PARAM: + if (IE_LEN(pucIE) != 24) + break; /* WMM Param IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? + TRUE : FALSE); + break; + + case VENDOR_OUI_SUBTYPE_WMM_INFO: + if (IE_LEN(pucIE) != 7) + break; /* WMM Info IE with a wrong length */ + + prStaRec->fgIsWmmSupported = TRUE; + prStaRec->fgIsUapsdSupported = + (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ? + TRUE : FALSE); + break; + + default: + /* A WMM QoS IE that doesn't matter. Ignore it. */ + break; + } + } + /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */ + + break; + + default: + /* A WMM IE that doesn't matter. Ignore it. */ + break; + } + } + DBGLOG(QM, LOUD, "MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n", + prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported); + +} + +UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType) +{ + UINT_32 i; + P_STA_RECORD_T prTempStaRec; + + prTempStaRec = NULL; + + ASSERT(prAdapter); + + /* 4 <1> DA = BMCAST */ + if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)) + return STA_REC_INDEX_BMCAST; + /* 4 <2> Check if an AP STA is present */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if ((prTempStaRec->ucNetTypeIndex == eNetworkType) + && (prTempStaRec->fgIsAp) + && (prTempStaRec->fgIsValid)) { + return prTempStaRec->ucIndex; + } + } + + /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */ + for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) { + prTempStaRec = &(prAdapter->arStaRec[i]); + if (prTempStaRec->fgIsValid) { + if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)) + return prTempStaRec->ucIndex; + } + } + + /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */ + return STA_REC_INDEX_NOT_FOUND; +} + +UINT_32 +mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD, + UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + UINT_32 ucUapsd[] = { + WMM_QOS_INFO_BE_UAPSD, + WMM_QOS_INFO_BK_UAPSD, + WMM_QOS_INFO_VI_UAPSD, + WMM_QOS_INFO_VO_UAPSD + }; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + ASSERT(pOutBuf); + + prIeWmmInfo = (P_IE_WMM_INFO_T) pOutBuf; + + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (fgSupportUAPSD) { + + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (ucBmpDeliveryAC & ucBmpTriggerAC) { + switch (ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, WARN, "MQM: Incorrect SP length\n"); + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + } + } + prIeWmmInfo->ucQosInfo = ucQosInfo; + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Info IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_WMM_INFO_T prIeWmmInfo; + P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo; + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("mqmGenerateWmmInfoIE"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + ASSERT(prStaRec); + + if (prStaRec == NULL) + return; + + if (!prStaRec->fgIsWmmSupported) + return; + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]); + + prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo; + + prIeWmmInfo = (P_IE_WMM_INFO_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + +#if 0 + prIeWmmInfo->ucId = ELEM_ID_WMM; + prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmInfo->aucOui[0] = aucWfaOui[0]; + prIeWmmInfo->aucOui[1] = aucWfaOui[1]; + prIeWmmInfo->aucOui[2] = aucWfaOui[2]; + prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO; + + prIeWmmInfo->ucVersion = VERSION_WMM; + prIeWmmInfo->ucQosInfo = 0; + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ +/* if(prAdapter->rWifiVar.fgSupportUAPSD){ */ + if (prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported) { + + UINT_8 ucQosInfo = 0; + UINT_8 i; + + /* Static U-APSD setting */ + for (i = ACI_BE; i <= ACI_VO; i++) { + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)) + ucQosInfo |= (UINT_8) ucUapsd[i]; + } + + if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) { + switch (prPmProfSetupInfo->ucUapsdSp) { + case WMM_MAX_SP_LENGTH_ALL: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL; + break; + + case WMM_MAX_SP_LENGTH_2: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + + case WMM_MAX_SP_LENGTH_4: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_4; + break; + + case WMM_MAX_SP_LENGTH_6: + ucQosInfo |= WMM_QOS_INFO_MAX_SP_6; + break; + + default: + DBGLOG(QM, INFO, "MQM: Incorrect SP length\n"); + ucQosInfo |= WMM_QOS_INFO_MAX_SP_2; + break; + } + } + prIeWmmInfo->ucQosInfo = ucQosInfo; + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo); +#else + + prMsduInfo->u2FrameLength += mqmGenerateWmmInfoIEByParam((prAdapter->rWifiVar.fgSupportUAPSD + && prStaRec->fgIsUapsdSupported), + prPmProfSetupInfo->ucBmpDeliveryAC, + prPmProfSetupInfo->ucBmpTriggerAC, + prPmProfSetupInfo->ucUapsdSp, (UINT_8 *) prIeWmmInfo); +#endif +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* @brief log2 calculation for CW +* +* @param[in] val value +* +* @return log2(val) +*/ +/*----------------------------------------------------------------------------*/ + +UINT_32 cwlog2(UINT_32 val) +{ + + UINT_32 n; + + n = 0; + + while (val >= 512) { + n += 9; + val = val >> 9; + } + while (val >= 16) { + n += 4; + val >>= 4; + } + while (val >= 2) { + n += 1; + val >>= 1; + } + return n; +} +#endif + +UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter, + P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + ENUM_WMM_ACI_T eAci; + UCHAR *pucAciAifsn, *pucEcw, *pucTxopLimit; + + ASSERT(pOutBuf); + + prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf; + + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (prAdapter->rWifiVar.fgSupportUAPSD) { + if (ucOpMode == OP_MODE_INFRASTRUCTURE) + prIeWmmParam->ucQosInfo = 0xf; + else + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + } + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + /* DBGLOG(QM, LOUD, */ + /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + +#if 0 + *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci] + | + (prBssInfo->arACQueParmsForBcast + [eAci].fgIsACMSet ? + WMM_ACIAIFSN_ACM : 0) + | + (prBssInfo->arACQueParmsForBcast + [eAci].u2Aifsn & + (WMM_ACIAIFSN_AIFSN))); +#else + /* avoid compile warnings in Klockwork tool */ + if (eAci == WMM_AC_BE_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_BE; + pucEcw = &prIeWmmParam->ucEcw_BE; + pucTxopLimit = prIeWmmParam->aucTxopLimit_BE; + } else if (eAci == WMM_AC_BK_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_BG; + pucEcw = &prIeWmmParam->ucEcw_BG; + pucTxopLimit = prIeWmmParam->aucTxopLimit_BG; + } else if (eAci == WMM_AC_VI_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_VI; + pucEcw = &prIeWmmParam->ucEcw_VI; + pucTxopLimit = prIeWmmParam->aucTxopLimit_VI; + } else if (eAci == WMM_AC_VO_INDEX) { + pucAciAifsn = &prIeWmmParam->ucAciAifsn_VO; + pucEcw = &prIeWmmParam->ucEcw_VO; + pucTxopLimit = prIeWmmParam->aucTxopLimit_VO; + } + + *pucAciAifsn = (UINT_8) (aucACI[eAci] + | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM : 0) + | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN))); +#endif + +#if 1 +/* *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 */ + *pucEcw = (UINT_8) (0 | (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK) + | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK) + ); +#else + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 + | + (cwlog2 + ((prBssInfo->arACQueParmsForBcast + [eAci].u2CWmin + + 1)) & WMM_ECW_WMIN_MASK) + | + ((cwlog2 + ((prBssInfo->arACQueParmsForBcast + [eAci].u2CWmax + + 1)) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK) + ); +#endif + +#if 0 + WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) + , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); +#else + WLAN_SET_FIELD_16(pucTxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); +#endif + } + + /* Increment the total IE length for the Element ID and Length fields. */ + return IE_SIZE(prIeWmmParam); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Generate the WMM Param IE +* +* \param[in] prAdapter Adapter pointer +* @param prMsduInfo The TX MMPDU +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + P_IE_WMM_PARAM_T prIeWmmParam; + +#if 0 + UINT_8 aucWfaOui[] = VENDOR_OUI_WFA; + + UINT_8 aucACI[] = { + WMM_ACI_AC_BE, + WMM_ACI_AC_BK, + WMM_ACI_AC_VI, + WMM_ACI_AC_VO + }; + ENUM_WMM_ACI_T eAci; +#endif + + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + + DEBUGFUNC("mqmGenerateWmmParamIE"); + DBGLOG(QM, LOUD, "\n"); + + ASSERT(prMsduInfo); + + /* In case QoS is not turned off, exit directly */ + if (!prAdapter->rWifiVar.fgSupportQoS) + return; + + prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex); + + if (prStaRec) { + if (!prStaRec->fgIsQoS) + return; + } + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]); + + if (!prBssInfo->fgIsQBSS) + return; +/* 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. */ +#if 0 + if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && prBssInfo->eCurrentOPMode != OP_MODE_BOW) + return; +#endif + + prIeWmmParam = (P_IE_WMM_PARAM_T) + ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength); + +#if 0 + prIeWmmParam->ucId = ELEM_ID_WMM; + prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM; + + /* WMM-2.2.1 WMM Information Element Field Values */ + prIeWmmParam->aucOui[0] = aucWfaOui[0]; + prIeWmmParam->aucOui[1] = aucWfaOui[1]; + prIeWmmParam->aucOui[2] = aucWfaOui[2]; + prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM; + prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM; + + prIeWmmParam->ucVersion = VERSION_WMM; + prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT); + + /* UAPSD initial queue configurations (delivery and trigger enabled) */ + if (prAdapter->rWifiVar.fgSupportUAPSD) + prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD; + + /* EDCA parameter */ + + for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) { + + /* DBGLOG(QM, LOUD, */ + /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */ + /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */ + /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */ + + *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci] + | + (prBssInfo->arACQueParmsForBcast + [eAci].fgIsACMSet ? + WMM_ACIAIFSN_ACM : 0) + | + (prBssInfo->arACQueParmsForBcast + [eAci].u2Aifsn & + (WMM_ACIAIFSN_AIFSN))); +#if 1 + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 + | + (((prBssInfo->aucCWminLog2ForBcast + [eAci])) & WMM_ECW_WMIN_MASK) + | + ((((prBssInfo->aucCWmaxLog2ForBcast + [eAci])) << WMM_ECW_WMAX_OFFSET) + & WMM_ECW_WMAX_MASK) + ); +#else + *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0 + | + (cwlog2 + ((prBssInfo->arACQueParmsForBcast + [eAci].u2CWmin + + 1)) & WMM_ECW_WMIN_MASK) + | + ((cwlog2 + ((prBssInfo->arACQueParmsForBcast + [eAci].u2CWmax + + 1)) << WMM_ECW_WMAX_OFFSET) & + WMM_ECW_WMAX_MASK) + ); +#endif + + WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2) + , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit); + + } + + /* Increment the total IE length for the Element ID and Length fields. */ + prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam); +#else + + prMsduInfo->u2FrameLength += mqmGenerateWmmParamIEByParam(prAdapter, + prBssInfo, (UINT_8 *) prIeWmmParam, OP_MODE_ACCESS_POINT); +#endif +} + +ENUM_FRAME_ACTION_T +qmGetFrameAction(IN P_ADAPTER_T prAdapter, + IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType, + IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType) +{ + P_BSS_INFO_T prBssInfo; + P_STA_RECORD_T prStaRec; + P_WLAN_MAC_HEADER_T prWlanFrame; + UINT_16 u2TxFrameCtrl; + + DEBUGFUNC("qmGetFrameAction"); + +#if (NIC_TX_BUFF_COUNT_TC4 > 2) +#define QM_MGMT_QUUEUD_THRESHOLD 2 +#else +#define QM_MGMT_QUUEUD_THRESHOLD 1 +#endif + + DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4)); + DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0); + + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]); + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx); + + /* XXX Check BOW P2P AIS time ot set active */ + if (!IS_BSS_ACTIVE(prBssInfo)) { + if (eFrameType == FRAME_TYPE_MMPDU) { + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ + if (((u2TxFrameCtrl == MAC_FRAME_DEAUTH) + && (prMsduInfo->pfTxDoneHandler == NULL)) + || (u2TxFrameCtrl == MAC_FRAME_ACTION)) /* whsu */ + return FRAME_ACTION_TX_PKT; + } + + DBGLOG(QM, WARN, "Drop packets Action, eFrameType: %d (Bss Index %u).\n", + eFrameType, prBssInfo->ucNetTypeIndex); + TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP); + return FRAME_ACTION_DROP_PKT; + } + + /* TODO Handle disconnect issue */ + + /* P2P probe Request frame */ + do { + if (eFrameType == FRAME_TYPE_MMPDU) { + prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket; + u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */ + + if (u2TxFrameCtrl == MAC_FRAME_BEACON) { + if (prBssInfo->fgIsNetAbsent) + return FRAME_ACTION_DROP_PKT; + } else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) { + if (prBssInfo->fgIsNetAbsent) + return FRAME_ACTION_DROP_PKT; + } else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) { + if (prBssInfo->fgIsNetAbsent) + break; + DBGLOG(P2P, LOUD, "Sending DEAUTH Frame\n"); + return FRAME_ACTION_TX_PKT; + } + /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */ + else if (u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_AUTH + || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ + || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ || u2TxFrameCtrl == MAC_FRAME_ACTION) { + + if ((prStaRec) && (prStaRec->fgIsInPS)) { + if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) + return FRAME_ACTION_TX_PKT; + else + return FRAME_ACTION_QUEUE_PKT; + } + return FRAME_ACTION_TX_PKT; + } + + if (!prStaRec) + return FRAME_ACTION_TX_PKT; + + if (!prStaRec->fgIsInUse) + return FRAME_ACTION_DROP_PKT; + + } /* FRAME_TYPE_MMPDU */ + else if (eFrameType == FRAME_TYPE_802_1X) { + + if (!prStaRec) + return FRAME_ACTION_TX_PKT; + + if (!prStaRec->fgIsInUse) + return FRAME_ACTION_DROP_PKT; + if (prStaRec->fgIsInPS) { + if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD) + return FRAME_ACTION_TX_PKT; + else + return FRAME_ACTION_QUEUE_PKT; + } + + } /* FRAME_TYPE_802_1X */ + else if ((!IS_BSS_ACTIVE(prBssInfo)) + || (!prStaRec) + || (!prStaRec->fgIsInUse)) { + return FRAME_ACTION_DROP_PKT; + } + } while (0); + + if (prBssInfo->fgIsNetAbsent) { + DBGLOG(QM, LOUD, "Queue packets (Absent %u).\n", prBssInfo->ucNetTypeIndex); + return FRAME_ACTION_QUEUE_PKT; + } + + if (prStaRec && prStaRec->fgIsInPS) { + DBGLOG(QM, LOUD, "Queue packets (PS %u).\n", prStaRec->fgIsInPS); + return FRAME_ACTION_QUEUE_PKT; + } + switch (eFrameType) { + case FRAME_TYPE_802_1X: + if (!prStaRec->fgIsValid) + return FRAME_ACTION_QUEUE_PKT; + break; + + case FRAME_TYPE_MMPDU: + break; + + default: + ASSERT(0); + } + + return FRAME_ACTION_TX_PKT; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle BSS change operation Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus; + P_BSS_INFO_T prBssInfo; + BOOLEAN fgIsNetAbsentOld; + + prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) prEvent; + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]); + fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent; + prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent; + prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota; + + /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */ + /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */ + + DBGLOG(QM, INFO, "NAF=%d,%d,%d\n", + prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota); + + if (!prBssInfo->fgIsNetAbsent) { + /* QM_DBG_CNT_27 */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27); + } else { + /* QM_DBG_CNT_28 */ + QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28); + } + /* From Absent to Present */ + if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)) + kalSetEvent(prAdapter->prGlueInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Handle STA change PS mode Event from the FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode; + P_STA_RECORD_T prStaRec; + BOOLEAN fgIsInPSOld; + + /* DbgPrint("QM:Event -RxBa\n"); */ + + prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec) { + + fgIsInPSOld = prStaRec->fgIsInPS; + prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs; + + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota, 0); + + /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */ + /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */ + + DBGLOG(QM, TRACE, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS); + + /* From PS to Awake */ + if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)) + kalSetEvent(prAdapter->prGlueInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota Event from FW +* +* \param[in] prAdapter Adapter pointer +* \param[in] prEvent The event packet from the FW +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent) +{ + P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota; + P_STA_RECORD_T prStaRec; + + prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T) prEvent; + prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx); + ASSERT(prStaRec); + + if (prStaRec) { + if (prStaRec->fgIsInPS) { + qmUpdateFreeQuota(prAdapter, + prStaRec, + prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota, + prEventStaUpdateFreeQuota->aucReserved[0]); + + kalSetEvent(prAdapter->prGlueInfo); + } +#if 0 + DBGLOG(QM, TRACE, + "qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, prEventStaUpdateFreeQuota->ucUpdateMode, + prEventStaUpdateFreeQuota->ucFreeQuota); +#endif + + DBGLOG(QM, TRACE, "UFQ=%d,%d,%d\n", + prEventStaUpdateFreeQuota->ucStaRecIdx, + prEventStaUpdateFreeQuota->ucUpdateMode, prEventStaUpdateFreeQuota->ucFreeQuota); + + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Update STA free quota +* +* \param[in] prStaRec the STA +* \param[in] ucUpdateMode the method to update free quota +* \param[in] ucFreeQuota the value for update +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter, + IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone) +{ + + UINT_8 ucFreeQuotaForNonDelivery; + UINT_8 ucFreeQuotaForDelivery; + BOOLEAN flgIsUpdateForcedToDelivery; + + ASSERT(prStaRec); + DBGLOG(QM, LOUD, "qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n", + prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota); + + if (!prStaRec->fgIsInPS) + return; + + flgIsUpdateForcedToDelivery = FALSE; + + if (ucNumOfTxDone > 0) { + /* + update free quota by + num of tx done + resident free quota (delivery + non-delivery) + */ + UINT_8 ucAvailQuota; + + ucAvailQuota = ucNumOfTxDone + prStaRec->ucFreeQuotaForDelivery + prStaRec->ucFreeQuotaForNonDelivery; + if (ucAvailQuota > ucFreeQuota) /* sanity check */ + ucAvailQuota = ucFreeQuota; + + /* update current free quota */ + ucFreeQuota = ucAvailQuota; + + /* check if the update is from last packet */ + if (ucFreeQuota == (prStaRec->ucFreeQuota + 1)) { + /* just add the extra quota to delivery queue */ + + /* + EX: + 1. TDLS peer enters power save + 2. When the last 2 VI packets are tx done, we will receive 2 update events + 3. 1st update event: ucFreeQuota = 9 + 4. We will correct new quota for delivey and non-delivery to 7:2 + 5. 2rd update event: ucFreeQuota = 10 + 6. We will re-correct new quota for delivery and non-delivery to 5:5 + + But non-delivery queue is not busy. + So in the case, we will have wrong decision, i.e. higher queue always quota 5 + + Solution: skip the 2rd update event and just add the extra quota to delivery. + */ + + flgIsUpdateForcedToDelivery = TRUE; + } + } + + switch (ucUpdateMode) { + case FREE_QUOTA_UPDATE_MODE_INIT: + case FREE_QUOTA_UPDATE_MODE_OVERWRITE: + prStaRec->ucFreeQuota = ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_INCREASE: + prStaRec->ucFreeQuota += ucFreeQuota; + break; + case FREE_QUOTA_UPDATE_MODE_DECREASE: + prStaRec->ucFreeQuota -= ucFreeQuota; + break; + default: + ASSERT(0); + } + + DBGLOG(QM, LOUD, "qmUpdateFreeQuota new ucFreeQuota=%d)\n", prStaRec->ucFreeQuota); + + ucFreeQuota = prStaRec->ucFreeQuota; + + ucFreeQuotaForNonDelivery = 0; + ucFreeQuotaForDelivery = 0; + + if (ucFreeQuota > 0) { + if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported + /* && prAdapter->rWifiVar.fgSupportQoS + && prAdapter->rWifiVar.fgSupportUAPSD */) { + /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */ + + if (flgIsUpdateForcedToDelivery == FALSE) { + if (prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else if (prStaRec->ucFreeQuotaForNonDelivery == 0 + && prStaRec->ucFreeQuotaForDelivery == 0) { + ucFreeQuotaForNonDelivery = ucFreeQuota >> 1; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else if (prStaRec->ucFreeQuotaForNonDelivery > 0) { + /* NonDelivery is not busy */ + if (ucFreeQuota >= 3) { + ucFreeQuotaForNonDelivery = 2; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } else { + ucFreeQuotaForDelivery = ucFreeQuota; + ucFreeQuotaForNonDelivery = 0; + } + } else if (prStaRec->ucFreeQuotaForDelivery > 0) { + /* Delivery is not busy */ + if (ucFreeQuota >= 3) { + ucFreeQuotaForDelivery = 2; + ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery; + } else { + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } + } else { + ucFreeQuotaForNonDelivery = 2; + ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery; + } + } else { + /* no use ? */ + /* !prStaRec->fgIsUapsdSupported */ + ucFreeQuotaForNonDelivery = ucFreeQuota; + ucFreeQuotaForDelivery = 0; + } + } + /* ucFreeQuota > 0 */ + prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery; + prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + if (IS_TDLS_STA(prStaRec)) + DBGLOG(QM, LOUD, " quota %d %d %d\n", + ucFreeQuota, ucFreeQuotaForDelivery, ucFreeQuotaForNonDelivery); +#endif + + DBGLOG(QM, LOUD, "new QuotaForDelivery = %d QuotaForNonDelivery = %d\n", + prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Return the reorder queued RX packets +* +* \param[in] (none) +* +* \return The number of queued RX packets +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter) +{ + UINT_32 i, u4Total; + P_QUE_MGT_T prQM = &prAdapter->rQM; + + u4Total = 0; + /* XXX The summation may impact the performance */ + for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) { + u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem; +#if DBG && 0 + if (QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) + ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0); +#endif + } + ASSERT(u4Total <= (CFG_NUM_OF_QM_RX_PKT_NUM * 2)); + return u4Total; +} + +#if ARP_MONITER_ENABLE +VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo) +{ + struct sk_buff *prSkb = NULL; + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + + prSkb = (struct sk_buff *)prMsduInfo->prPacket; + + if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN)) + return; + + pucData = prSkb->data; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP || (apIp[0] | apIp[1] | apIp[2] | apIp[3]) == 0) + return; + + if (strncmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp))) /* dest ip address */ + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + if (arpOpCode == ARP_PRO_REQ) { + arpMoniter++; + if (arpMoniter > 20) { + DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n"); + aisBssBeaconTimeout(prAdapter); + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); + } + } +} + +VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb) +{ + PUINT_8 pucData = NULL; + UINT_16 u2EtherType = 0; + int arpOpCode = 0; + P_BSS_INFO_T prBssInfo = NULL; + + if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN) + return; + + pucData = (PUINT_8)prSwRfb->pvHeader; + if (!pucData) + return; + u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]); + + if (u2EtherType != ETH_P_ARP) + return; + + arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]); + prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]); + if (arpOpCode == ARP_PRO_RSP) { + arpMoniter = 0; + if (prBssInfo && prBssInfo->prStaRecOfAP && prBssInfo->prStaRecOfAP->aucMacAddr) { + if (EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */ + prBssInfo->prStaRecOfAP->aucMacAddr)) { + strncpy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp)); /* src ip address */ + DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n", + apIp[0], apIp[1], apIp[2], apIp[3]); + } + } + } +} + +VOID qmResetArpDetect(VOID) +{ + arpMoniter = 0; + kalMemZero(apIp, sizeof(apIp)); +} +#endif + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c new file mode 100644 index 0000000000000..6f5c0bcdd90bb --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_bow.c @@ -0,0 +1,1177 @@ +/* +** Id: @(#) gl_bow.c@@ +*/ + +/*! \file gl_bow.c + \brief Main routines of Linux driver interface for 802.11 PAL (BT 3.0 + HS) + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_bow.c + * + * 02 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00235223] [Rose][ICS][Cross Feature][AEE-IPANIC]The device reboot automatically and then the "KE" pops up + * after you turn on the "Airplane mode".(once) + * + * [Root Cause] + * PAL operates BOW char dev poll after BOW char dev is registered. + * + * [Solution] + * Rejects PAL char device operation after BOW is unregistered or when wlan GLUE_FLAG_HALT is set. + * + * This is a workaround for BOW driver robustness, happens only in ICS. + * + * Root cause should be fixed by CR [ALPS00231570] + * + * 02 03 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * [ALPS00118114] [Rose][ICS][Free Test][Bluetooth]The "KE" pops up after you turn on the airplane mode.(5/5) + * + * [Root Cause] + * PAL operates BOW char dev poll after BOW char dev is registered. + * + * [Solution] + * Rejects PAL char device operation after BOW is unregistered. + * + * Happens only in ICS. + * + * Notified PAL owener to reivew MTKBT/PAL closing BOW char dev procedure. + * + * [Side Effect] + * None. + * + * 01 16 2012 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support BOW for 5GHz band. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 25 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Modify ampc0 char device for major number 151 for all MT6575 projects. + * + * 07 28 2011 cp.wu + * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl + * unlocked_ioctl returns as long instead of int. + * + * 07 28 2011 cp.wu + * [WCXRP00000884] [MT6620 Wi-Fi][Driver] Deprecate ioctl interface by unlocked ioctl + * migrate to unlocked ioctl interface + * + * 04 12 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add WMM IE for BOW initiator data. + * + * 04 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link disconnection event procedure for hotspot and change skb length check to 1514 bytes. + * + * 04 09 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Change Link connection event procedure and change skb length check to 1512 bytes. + * + * 03 27 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Support multiple physical link. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * replace alloc_netdev to alloc_netdev_mq for BoW + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 02 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Update net register and BOW for concurrent features. + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 cp.wu + * [WCXRP00000430] [MT6620 Wi-Fi][Firmware][Driver] Create V1.2 branch for MT6620E1 and MT6620E3 + * create V1.2 driver branch based on label MT6620_WIFI_DRIVER_V1_2_110209_1031 + * with BOW and P2P enabled as default + * + * 02 08 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Replace kfifo_get and kfifo_put with kfifo_out and kfifo_in. + * Update BOW get MAC status, remove returning event for AIS network type. + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation + * needs such information + * fill mac header length information for 802.1x frames. + * + * 11 11 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix BoW timer assert issue. + * + * 09 14 2010 chinghwa.yu + * NULL + * Add bowRunEventAAAComplete. + * + * 09 14 2010 cp.wu + * NULL + * correct typo: POLLOUT instead of POLL_OUT + * + * 09 13 2010 cp.wu + * NULL + * add waitq for poll() and read(). + * + * 08 24 2010 chinghwa.yu + * NULL + * Update BOW for the 1st time. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change variable names for multiple physical link to match with coding convention + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * multiple BoW interfaces need to compare with peer address + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * fix kalIndicateBOWEvent. + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler capability + * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include "bss.h" + +#if CFG_ENABLE_BT_OVER_WIFI + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* @FIXME if there is command/event with payload length > 28 */ +#define MAX_BUFFER_SIZE (64) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_BOW_TEST +UINT_32 g_u4PrevSysTime = 0; +UINT_32 g_u4CurrentSysTime = 0; +UINT_32 g_arBowRevPalPacketTime[11]; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* forward declarations */ +static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static ssize_t +mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos); + +static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg); + +static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table *wait); + +static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp); + +static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp); + +/* character file operations */ +static const struct file_operations mt6620_ampc_fops = { + /* .owner = THIS_MODULE, */ + .read = mt6620_ampc_read, + .write = mt6620_ampc_write, + .unlocked_ioctl = mt6620_ampc_ioctl, + .poll = mt6620_ampc_poll, + .open = mt6620_ampc_open, + .release = mt6620_ampc_release, +}; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for character device to communicate with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glRegisterAmpc(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->rBowInfo.fgIsRegistered == TRUE) + return FALSE; + +#if 0 + /* 1. allocate major number dynamically */ + + if (alloc_chrdev_region(&(prGlueInfo->rBowInfo.u4DeviceNumber), 0, /* first minor number */ + 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + +#if 1 + +#if defined(CONFIG_AMPC_CDEV_NUM) + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(CONFIG_AMPC_CDEV_NUM, 0); +#else + prGlueInfo->rBowInfo.u4DeviceNumber = MKDEV(226, 0); +#endif + + if (register_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1, /* number */ + GLUE_BOW_DEVICE_NAME) != 0) + + return FALSE; +#endif + + /* 2. spin-lock initialization */ + /* spin_lock_init(&(prGlueInfo->rBowInfo.rSpinLock)); */ + + /* 3. initialize kfifo */ +/* prGlueInfo->rBowInfo.prKfifo = kfifo_alloc(GLUE_BOW_KFIFO_DEPTH, + GFP_KERNEL, + &(prGlueInfo->rBowInfo.rSpinLock));*/ + if ((kfifo_alloc((struct kfifo *)&(prGlueInfo->rBowInfo.rKfifo), GLUE_BOW_KFIFO_DEPTH, GFP_KERNEL))) + goto fail_kfifo_alloc; + +/* if(prGlueInfo->rBowInfo.prKfifo == NULL) */ + if (&(prGlueInfo->rBowInfo.rKfifo) == NULL) + goto fail_kfifo_alloc; + + /* 4. initialize cdev */ + cdev_init(&(prGlueInfo->rBowInfo.cdev), &mt6620_ampc_fops); + /* prGlueInfo->rBowInfo.cdev.owner = THIS_MODULE; */ + prGlueInfo->rBowInfo.cdev.ops = &mt6620_ampc_fops; + + /* 5. add character device */ + if (cdev_add(&(prGlueInfo->rBowInfo.cdev), prGlueInfo->rBowInfo.u4DeviceNumber, 1)) + goto fail_cdev_add; + + /* 6. in queue initialization */ + init_waitqueue_head(&(prGlueInfo->rBowInfo.outq)); + + /* 7. finish */ + prGlueInfo->rBowInfo.fgIsRegistered = TRUE; + return TRUE; + +fail_cdev_add: + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ +fail_kfifo_alloc: + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + return FALSE; +} /* end of glRegisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister character device for communicating with 802.11 PAL +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glUnregisterAmpc(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->rBowInfo.fgIsRegistered == FALSE) + return FALSE; + + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + + /* 1. free netdev if necessary */ +#if CFG_BOW_SEPARATE_DATA_PATH + kalUninitBowDevice(prGlueInfo); +#endif + + /* 2. removal of character device */ + cdev_del(&(prGlueInfo->rBowInfo.cdev)); + + /* 3. free kfifo */ +/* kfifo_free(prGlueInfo->rBowInfo.prKfifo); */ + kfifo_free(&(prGlueInfo->rBowInfo.rKfifo)); +/* prGlueInfo->rBowInfo.prKfifo = NULL; */ +/* prGlueInfo->rBowInfo.rKfifo = NULL; */ + + /* 4. free device number */ + unregister_chrdev_region(prGlueInfo->rBowInfo.u4DeviceNumber, 1); + + return TRUE; +} /* end of glUnregisterAmpc */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief read handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t mt6620_ampc_read(IN struct file *filp, IN char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + ssize_t retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* size check */ +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) >= size) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) >= size) + retval = size; + else + retval = kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); +/* retval = kfifo_len(prGlueInfo->rBowInfo.prKfifo); */ + +/* kfifo_get(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ +/* kfifo_out(prGlueInfo->rBowInfo.prKfifo, aucBuffer, retval); */ + if (!(kfifo_out(&(prGlueInfo->rBowInfo.rKfifo), aucBuffer, retval))) { + retval = -EIO; + return retval; + } + + if (copy_to_user(buf, aucBuffer, retval)) + retval = -EIO; + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief write handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t +mt6620_ampc_write(IN struct file *filp, OUT const char __user *buf, IN size_t size, IN OUT loff_t *ppos) +{ +#if CFG_BOW_TEST + UINT_8 i; +#endif + + UINT_8 aucBuffer[MAX_BUFFER_SIZE]; + P_AMPC_COMMAND prCmd; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + if (size > MAX_BUFFER_SIZE) + return -EINVAL; + else if (copy_from_user(aucBuffer, buf, size)) + return -EIO; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "AMP driver CMD buffer size : %d.\n", size); + + for (i = 0; i < MAX_BUFFER_SIZE; i++) + DBGLOG(BOW, EVENT, "AMP write content : 0x%x.\n", aucBuffer[i]); + + DBGLOG(BOW, EVENT, "BoW CMD write.\n"); +#endif + + prCmd = (P_AMPC_COMMAND) aucBuffer; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "AMP write content payload length : %d.\n", prCmd->rHeader.u2PayloadLength); + + DBGLOG(BOW, EVENT, "AMP write content header length : %d.\n", sizeof(AMPC_COMMAND_HEADER_T)); +#endif + + /* size check */ + if (prCmd->rHeader.u2PayloadLength + sizeof(AMPC_COMMAND_HEADER_T) != size) { +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "Wrong CMD total length.\n"); +#endif + + return -EINVAL; + } + + if (wlanbowHandleCommand(prGlueInfo->prAdapter, prCmd) == WLAN_STATUS_SUCCESS) + return size; + else + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static long mt6620_ampc_ioctl(IN struct file *filp, IN unsigned int cmd, IN OUT unsigned long arg) +{ + int err = 0; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + /* permission check */ + if (_IOC_DIR(cmd) & _IOC_READ) + err = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd)); + else if (_IOC_DIR(cmd) & _IOC_WRITE) + err = !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd)); + if (err) + return -EFAULT; + + /* no ioctl is implemented yet */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static unsigned int mt6620_ampc_poll(IN struct file *filp, IN poll_table *wait) +{ + unsigned int retval; + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return -EFAULT; + + poll_wait(filp, &prGlueInfo->rBowInfo.outq, wait); + + retval = (POLLOUT | POLLWRNORM); /* always accepts incoming command packets */ + +/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLOUT | POLLWRNORM, %x\n", retval)); */ + +/* if(kfifo_len(prGlueInfo->rBowInfo.prKfifo) > 0) */ + if (kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)) > 0) { + retval |= (POLLIN | POLLRDNORM); + +/* DBGLOG(BOW, EVENT, ("mt6620_ampc_pol, POLLIN | POLLRDNORM, %x\n", retval)); */ + + } + + return retval; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief open handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int mt6620_ampc_open(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + P_GL_BOW_INFO prBowInfo; + + prBowInfo = container_of(inodep->i_cdev, GL_BOW_INFO, cdev); + ASSERT(prBowInfo); + + prGlueInfo = container_of(prBowInfo, GLUE_INFO_T, rBowInfo); + ASSERT(prGlueInfo); + + /* set-up private data */ + filp->private_data = prGlueInfo; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief close handler for character device to communicate with 802.11 PAL +* +* \param[in] +* \return +* Follows Linux Character Device Interface +* +*/ +/*----------------------------------------------------------------------------*/ +static int mt6620_ampc_release(IN struct inode *inodep, IN struct file *filp) +{ + P_GLUE_INFO_T prGlueInfo; + + prGlueInfo = (P_GLUE_INFO_T) (filp->private_data); + + ASSERT(prGlueInfo); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to indicate event for Bluetooth over Wi-Fi +* +* \param[in] +* prGlueInfo +* prEvent +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent) +{ + size_t u4AvailSize, u4EventSize; + + ASSERT(prGlueInfo); + ASSERT(prEvent); + + /* check device */ + if ((prGlueInfo->rBowInfo.fgIsRegistered == FALSE) || (prGlueInfo->ulFlag & GLUE_FLAG_HALT)) + return; + +/* u4AvailSize = + GLUE_BOW_KFIFO_DEPTH - kfifo_len(prGlueInfo->rBowInfo.prKfifo);*/ + + u4AvailSize = GLUE_BOW_KFIFO_DEPTH - kfifo_len(&(prGlueInfo->rBowInfo.rKfifo)); + + u4EventSize = prEvent->rHeader.u2PayloadLength + sizeof(AMPC_EVENT_HEADER_T); + + /* check kfifo availability */ + if (u4AvailSize < u4EventSize) { + DBGLOG(BOW, EVENT, "[bow] no space for event: %zu/%zu\n", u4EventSize, u4AvailSize); + return; + } + /* queue into kfifo */ +/* kfifo_put(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ +/* kfifo_in(prGlueInfo->rBowInfo.prKfifo, (PUINT_8)prEvent, u4EventSize); */ + kfifo_in(&(prGlueInfo->rBowInfo.rKfifo), (PUINT_8) prEvent, u4EventSize); + wake_up_interruptible(&(prGlueInfo->rBowInfo.outq)); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalGetBowState.\n"); +#endif + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalGetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalGetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, + prGlueInfo->rBowInfo.aeState[i]); + +#endif + + return prGlueInfo->rBowInfo.aeState[i]; + } + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, IN UINT_8 aucPeerAddress[6]) +{ + UINT_8 i; + + ASSERT(prGlueInfo); + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalSetBowState.\n"); + + DBGLOG(BOW, EVENT, "kalSetBowState, prGlueInfo->rBowInfo.arPeerAddr, %x:%x:%x:%x:%x:%x.\n", + prGlueInfo->rBowInfo.arPeerAddr[0], + prGlueInfo->rBowInfo.arPeerAddr[1], + prGlueInfo->rBowInfo.arPeerAddr[2], + prGlueInfo->rBowInfo.arPeerAddr[3], + prGlueInfo->rBowInfo.arPeerAddr[4], prGlueInfo->rBowInfo.arPeerAddr[5])); + + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress, %x:%x:%x:%x:%x:%x.\n", + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5]); +#endif + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr, aucPeerAddress) == 0) { + prGlueInfo->rBowInfo.aeState[i] = eBowState; + +#if CFG_BOW_TEST + DBGLOG(BOW, EVENT, "kalSetBowState, aucPeerAddress %x, %x:%x:%x:%x:%x:%x.\n", i, + aucPeerAddress[0], + aucPeerAddress[1], + aucPeerAddress[2], + aucPeerAddress[3], aucPeerAddress[4], aucPeerAddress[5])); + + DBGLOG(BOW, EVENT, + "kalSetBowState, prGlueInfo->rBowInfo.aeState %x, %x.\n", i, + prGlueInfo->rBowInfo.aeState[i]); +#endif + + return TRUE; + } + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi global state +* +* \param[in] +* prGlueInfo +* +* \return +* BOW_DEVICE_STATE_DISCONNECTED +* in case there is no BoW connection or +* BoW connection under initialization +* +* BOW_DEVICE_STATE_STARTING +* in case there is no BoW connection but +* some BoW connection under initialization +* +* BOW_DEVICE_STATE_CONNECTED +* in case there is any BoW connection available +*/ +/*----------------------------------------------------------------------------*/ +ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + +/* Henry, can reduce this logic to indentify state change */ + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_CONNECTED) + return BOW_DEVICE_STATE_CONNECTED; + } + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_STARTING) + return BOW_DEVICE_STATE_STARTING; + } + + return BOW_DEVICE_STATE_DISCONNECTED; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rBowInfo.u4FreqInKHz; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: Responder +* 1: Initiator +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) + return prGlueInfo->rBowInfo.aucRole[i]; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* ucRole +* 0: Responder +* 1: Initiator +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr) +{ + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 1); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (EQUAL_MAC_ADDR(prGlueInfo->rBowInfo.arPeerAddr[i], rPeerAddr) == 0) + prGlueInfo->rBowInfo.aucRole[i] = ucRole; /* Henry, 0 : Responder, 1 : Initiator */ + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get available Bluetooth-over-Wi-Fi physical link number +* +* \param[in] +* prGlueInfo +* \return +* UINT_32 +* how many physical links are aviailable +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 i; + UINT_8 ucLinkCount = 0; + + ASSERT(prGlueInfo); + + for (i = 0; i < CFG_BOW_PHYSICAL_LINK_NUM; i++) { + if (prGlueInfo->rBowInfo.aeState[i] == BOW_DEVICE_STATE_DISCONNECTED) + ucLinkCount++; + } + +#if 0 /* CFG_BOW_TEST */ + DBGLOG(BOW, EVENT, "kalGetBowAvailablePhysicalLinkCount, ucLinkCount, %c.\n", ucLinkCount); +#endif + + return ucLinkCount; +} + +#if CFG_BOW_SEPARATE_DATA_PATH + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int bowOpen(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 2. carrier on & start TX queue */ + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int bowStop(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); + + /* 2. turn of carrier */ + if (netif_carrier_ok(prDev)) + netif_carrier_off(prDev); + + return 0; +}; + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is TX entry point of NET DEVICE. + * + * \param[in] prSkb Pointer of the sk_buff to be sent + * \param[in] prDev Pointer to struct net_device + * + * \retval NETDEV_TX_OK - on success. + * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + */ +/*----------------------------------------------------------------------------*/ +static int bowHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + PUINT_8 aucLookAheadBuf = NULL; + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + + aucLookAheadBuf = prSkb->data; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + prGlueInfo->u8SkbToDriver++; + + if (!(ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) || (prSkb->len > 1514)) { + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Invalid BOW packet, skip tx\n"); +#endif + + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(BOW, TRACE, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Tx sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "Tx sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "Tx sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"; +#endif +#if CFG_BOW_TEST +/* g_u4CurrentSysTime = (OS_SYSTIME)kalGetTimeTick(; */ + g_u4CurrentSysTime = (OS_SYSTIME) jiffies_to_usecs(jiffies); + i = g_u4CurrentSysTime - g_u4PrevSysTime; + if ((i >> 10) > 0) + i = 10; + else + i = i >> 7; + g_arBowRevPalPacketTime[i]++; + g_u4PrevSysTime = g_u4CurrentSysTime; +#endif + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) + DBGLOG(TX, INFO, "netif_stop_subqueue for BOW, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_BOW_INDEX][u2QueueIdx]); + + netif_stop_subqueue(prDev, u2QueueIdx); + } else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} + +/* callbacks for netdevice */ +static const struct net_device_ops bow_netdev_ops = { + .ndo_open = bowOpen, .ndo_stop = bowStop, .ndo_start_xmit = bowHardStartXmit,}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief initialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* prDevName +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName) +{ + P_ADAPTER_T prAdapter; + P_GL_HIF_INFO_T prHif; + PARAM_MAC_ADDRESS rMacAddr; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + if (prGlueInfo->rBowInfo.fgIsNetRegistered == FALSE) { + prGlueInfo->rBowInfo.prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + if (!prGlueInfo->rBowInfo.prDevHandler) + return FALSE; + + /* 1. setup netdev */ + /* 1.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->rBowInfo.prDevHandler)) = prGlueInfo; + /* 1.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] |= 0x2; + /* change to local administrated address */ + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prGlueInfo->rBowInfo.prDevHandler->perm_addr, + prGlueInfo->rBowInfo.prDevHandler->dev_addr); + /* 1.3 register callback functions */ + prGlueInfo->rBowInfo.prDevHandler->netdev_ops = &bow_netdev_ops; +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prGlueInfo->rBowInfo.prDevHandler, prHif->Dev); +#endif + register_netdev(prGlueInfo->rBowInfo.prDevHandler); + /* 2. net device initialize */ + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + /* 3. finish */ + prGlueInfo->rBowInfo.fgIsNetRegistered = TRUE; + } + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief uninitialize net device for Bluetooth-over-Wi-Fi +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + /* ASSERT(prGlueInfo->rBowInfo.fgIsRegistered == TRUE); */ + if (prGlueInfo->rBowInfo.fgIsNetRegistered == TRUE) { + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + if (netif_carrier_ok(prGlueInfo->rBowInfo.prDevHandler)) + netif_carrier_off(prGlueInfo->rBowInfo.prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->rBowInfo.prDevHandler); + /* netdevice unregistration & free */ + unregister_netdev(prGlueInfo->rBowInfo.prDevHandler); + free_netdev(prGlueInfo->rBowInfo.prDevHandler); + prGlueInfo->rBowInfo.prDevHandler = NULL; + return TRUE; + } else { + return FALSE; + } +} +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c new file mode 100644 index 0000000000000..1fed65ebc60e6 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_cfg80211.c @@ -0,0 +1,3110 @@ +/* +** Id: @(#) gl_cfg80211.c@@ +*/ + +/*! \file gl_cfg80211.c + \brief Main routines for supporintg MT6620 cfg80211 control interface + + This file contains the support routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_cfg80211.c +** +** 09 05 2013 cp.wu +** correct length to pass to wlanoidSetBssid() +** +** 09 04 2013 cp.wu +** fix typo +** +** 09 03 2013 cp.wu +** add path for reassociation +** +** 11 23 2012 yuche.tsai +** [ALPS00398671] [Acer-Tablet] Remove Wi-Fi Direct completely +** Fix bug of WiFi may reboot under user load, when WiFi Direct is removed.. +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 30 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "debug.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include +#include +#include +#include "gl_cfg80211.h" +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/* workaround for some ANR CRs. if suppliant is blocked longer than 10s, wifi hal will tell wifiMonitor +to teminate. for the case which can block supplicant 10s is to del key more than 5 times. the root cause +is that there is no resource in TC4, so del key command was not able to set, and then oid +timeout was happed. if we found the root cause why fw couldn't release TC resouce, we will remove this +workaround */ +static UINT_8 gucKeyIndex = 255; + +P_SW_RFB_T g_arGscnResultsTempBuffer[MAX_BUFFERED_GSCN_RESULTS]; +UINT_8 g_GscanResultsTempBufferIndex = 0; +UINT_8 g_arGscanResultsIndicateNumber[MAX_BUFFERED_GSCN_RESULTS] = { 0, 0, 0, 0, 0 }; + +UINT_8 g_GetResultsBufferedCnt = 0; +UINT_8 g_GetResultsCmdCnt = 0; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for change STA type between + * 1. Infrastructure Client (Non-AP STA) + * 2. Ad-Hoc IBSS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type, /*u32 *flags,*/ struct vif_params *params) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + ENUM_PARAM_OP_MODE_T eOpMode; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (type == NL80211_IFTYPE_STATION) + eOpMode = NET_TYPE_INFRA; + else if (type == NL80211_IFTYPE_ADHOC) + eOpMode = NET_TYPE_IBSS; + else + return -EINVAL; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set infrastructure mode error:%x\n", rStatus); + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding key + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) +{ + PARAM_KEY_T rKey; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Rslt = -EINVAL; + UINT_32 u4BufLen = 0; + UINT_8 tmp1[8]; + UINT_8 tmp2[8]; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rKey, sizeof(PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + + if (mac_addr) { + COPY_MAC_ADDR(rKey.arBSSID, mac_addr); + if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && + (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + } + if (rKey.arBSSID[0] != 0xFF) { + rKey.u4KeyIndex |= BIT(31); + if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || + (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) + rKey.u4KeyIndex |= BIT(30); + } + } else { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + /* rKey.u4KeyIndex |= BIT(31);//Enable BIT 31 will make tx use bc key id,should use pairwise key id 0 */ + } + + if (params->key) { + /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + if (params->key_len == 32) { + kalMemCopy(tmp1, ¶ms->key[16], 8); + kalMemCopy(tmp2, ¶ms->key[24], 8); + kalMemCopy(&rKey.aucKeyMaterial[16], tmp2, 8); + kalMemCopy(&rKey.aucKeyMaterial[24], tmp1, 8); + } + } + + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *)) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for removing key for specified STA + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + PARAM_REMOVE_KEY_T rRemoveKey; + UINT_32 u4BufLen = 0; + INT_32 i4Rslt = -EINVAL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(&rRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if (mac_addr) + COPY_MAC_ADDR(rRemoveKey.arBSSID, mac_addr); + else if (key_index <= gucKeyIndex) { /* new operation, reset gucKeyIndex */ + gucKeyIndex = 255; + } else { /* bypass the next remove key operation */ + gucKeyIndex = key_index; + return -EBUSY; + } + rRemoveKey.u4KeyIndex = key_index; + rRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, &rRemoveKey, rRemoveKey.u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "remove key error:%x\n", rStatus); + if (WLAN_STATUS_FAILURE == rStatus && mac_addr) { + i4Rslt = -EBUSY; + gucKeyIndex = key_index; + } + } else { + gucKeyIndex = 255; + i4Rslt = 0; + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting default key on an interface + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for setting set_default_mgmt_ke on an interface + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for getting station information such as RSSI + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo) +{ +#define LINKSPEED_MAX_RANGE_11BGN 3000 + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + PARAM_MAC_ADDRESS arBssid; + UINT_32 u4BufLen; + UINT_32 u4Rate = 0; + UINT_32 u8diffTxBad, u8diffRetry; + INT_32 i4Rssi = 0; + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, mac)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", + mac, arBssid); + return -ENOENT; + } + + /* 2. fill TX rate */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= BIT(NL80211_STA_INFO_TX_BITRATE); + + if ((rStatus != WLAN_STATUS_SUCCESS) || (u4Rate == 0)) { + /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n")); */ + DBGLOG(REQ, WARN, "last link speed\n"); + sinfo->txrate.legacy = prGlueInfo->u4LinkSpeedCache; + } else { + /* sinfo->filled |= STATION_INFO_TX_BITRATE; */ + sinfo->txrate.legacy = u4Rate / 1000; /* convert from 100bps to 100kbps */ + prGlueInfo->u4LinkSpeedCache = u4Rate / 1000; + } + } + + /* 3. fill RSSI */ + if (prGlueInfo->eParamMediaStateIndicated != PARAM_MEDIA_STATE_CONNECTED) { + /* not connected */ + DBGLOG(REQ, WARN, "not yet connected\n"); + } else { + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); + + if (rStatus != WLAN_STATUS_SUCCESS || (i4Rssi == PARAM_WHQL_RSSI_MIN_DBM) + || (i4Rssi == PARAM_WHQL_RSSI_MAX_DBM)) { + /* DBGLOG(REQ, WARN, "unable to retrieve link speed\n"); */ + DBGLOG(REQ, WARN, "last rssi\n"); + sinfo->signal = prGlueInfo->i4RssiCache; + } else { + /* in the cfg80211 layer, the signal is a signed char variable. */ + sinfo->signal = i4Rssi; /* dBm */ + prGlueInfo->i4RssiCache = i4Rssi; + } + sinfo->rx_packets = prGlueInfo->rNetDevStats.rx_packets; + + /* 4. Fill Tx OK and Tx Bad */ + + sinfo->filled |= BIT(NL80211_STA_INFO_TX_PACKETS); + sinfo->filled |= BIT(NL80211_STA_INFO_TX_FAILED); + { + WLAN_STATUS rStatus; + + kalMemZero(&rStatistics, sizeof(rStatistics)); + /* Get Tx OK/Fail cnt from AIS statistic counter */ + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatisticsPL, + &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "unable to retrieive statistic\n"); + } else { + INT_32 i4RssiThreshold = -85; /* set rssi threshold -85dBm */ + UINT_32 u4LinkspeedThreshold = 55; /* set link speed threshold 5.5Mbps */ + BOOLEAN fgWeighted = 0; + + /* calculate difference */ + u8diffTxBad = rStatistics.rFailedCount.QuadPart - prGlueInfo->u8Statistic[0]; + u8diffRetry = rStatistics.rRetryCount.QuadPart - prGlueInfo->u8Statistic[1]; + /* restore counters */ + prGlueInfo->u8Statistic[0] = rStatistics.rFailedCount.QuadPart; + prGlueInfo->u8Statistic[1] = rStatistics.rRetryCount.QuadPart; + + /* check threshold is valid */ + if (prGlueInfo->fgPoorlinkValid) { + if (prGlueInfo->i4RssiThreshold) + i4RssiThreshold = prGlueInfo->i4RssiThreshold; + if (prGlueInfo->u4LinkspeedThreshold) + u4LinkspeedThreshold = prGlueInfo->u4LinkspeedThreshold; + } + /* add weighted to fail counter */ + if (sinfo->txrate.legacy < u4LinkspeedThreshold || sinfo->signal < i4RssiThreshold) { + prGlueInfo->u8TotalFailCnt += (u8diffTxBad * 16 + u8diffRetry); + fgWeighted = 1; + } else { + prGlueInfo->u8TotalFailCnt += u8diffTxBad; + } + /* report counters */ + prGlueInfo->rNetDevStats.tx_packets = rStatistics.rTransmittedFragmentCount.QuadPart; + prGlueInfo->rNetDevStats.tx_errors = prGlueInfo->u8TotalFailCnt; + + sinfo->tx_packets = prGlueInfo->rNetDevStats.tx_packets; + sinfo->tx_failed = prGlueInfo->rNetDevStats.tx_errors; + /* Good Fail Bad Difference retry difference Linkspeed Rate Weighted */ + DBGLOG(REQ, TRACE, + "Poorlink State TxOK(%d) TxFail(%d) Bad(%d) Retry(%d)", + sinfo->tx_packets, + sinfo->tx_failed, + (int)u8diffTxBad, + (int)u8diffRetry); + DBGLOG(REQ, TRACE, + "Rate(%d) Signal(%d) Weight(%d) QuadPart(%d)\n", + sinfo->txrate.legacy, + sinfo->signal, + (int)fgWeighted, + (int)rStatistics.rMultipleRetryCount.QuadPart); + } + } + + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ +#if (CFG_SUPPORT_TDLS == 1) + /* + EX: In supplicant, + (Supplicant) wpa_tdls_process_tpk_m3() -> + (Supplicant) wpa_tdls_enable_link() -> + (Supplicant) wpa_sm_tdls_peer_addset() -> + (Supplicant) ..tdls_peer_addset() -> + (Supplicant) wpa_supplicant_tdls_peer_addset() -> + (Supplicant) wpa_drv_sta_add() -> + (Supplicant) ..sta_add() -> + (Supplicant) wpa_driver_nl80211_sta_add() -> + (NL80211) nl80211_set_station() -> + (Driver) mtk_cfg80211_change_station() + + if nl80211_set_station fails, supplicant will tear down the link. + */ + P_GLUE_INFO_T prGlueInfo; + TDLS_CMD_PEER_UPDATE_T rCmdUpdate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen, u4Temp; + + /* sanity check */ + if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) + return -EINVAL; + + DBGLOG(TDLS, INFO, "%s: 0x%p 0x%x\n", __func__, params->supported_rates, params->sta_flags_set); + + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -EOPNOTSUPP; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + /* TODO: check if we are station mode, not AP mode */ + + /* init */ + kalMemZero(&rCmdUpdate, sizeof(rCmdUpdate)); + kalMemCopy(rCmdUpdate.aucPeerMac, mac, 6); + + if (params->supported_rates != NULL) { + u4Temp = params->supported_rates_len; + if (u4Temp > TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX) { + u4Temp = TDLS_CMD_PEER_UPDATE_SUP_RATE_MAX; + DBGLOG(TDLS, ERROR, "%s sup rate too long: %d\n", __func__, params->supported_rates_len); + } + kalMemCopy(rCmdUpdate.aucSupRate, params->supported_rates, u4Temp); + rCmdUpdate.u2SupRateLen = u4Temp; + } + + /* + In supplicant, only recognize WLAN_EID_QOS 46, not 0xDD WMM + So force to support UAPSD here. + */ + rCmdUpdate.UapsdBitmap = 0x0F; /*params->uapsd_queues; */ + rCmdUpdate.UapsdMaxSp = 0; /*params->max_sp; */ + + DBGLOG(TDLS, INFO, "%s: UapsdBitmap=0x%x UapsdMaxSp=%d\n", + __func__, rCmdUpdate.UapsdBitmap, rCmdUpdate.UapsdMaxSp); + + rCmdUpdate.u2Capability = params->capability; + + if (params->ext_capab != NULL) { + u4Temp = params->ext_capab_len; + if (u4Temp > TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN) { + u4Temp = TDLS_CMD_PEER_UPDATE_EXT_CAP_MAXLEN; + DBGLOG(TDLS, ERROR, "%s ext_capab too long: %d\n", __func__, params->ext_capab_len); + } + kalMemCopy(rCmdUpdate.aucExtCap, params->ext_capab, u4Temp); + rCmdUpdate.u2ExtCapLen = u4Temp; + } + + if (params->ht_capa != NULL) { + DBGLOG(TDLS, INFO, "%s: peer is 11n device\n", __func__); + + rCmdUpdate.rHtCap.u2CapInfo = params->ht_capa->cap_info; + rCmdUpdate.rHtCap.ucAmpduParamsInfo = params->ht_capa->ampdu_params_info; + rCmdUpdate.rHtCap.u2ExtHtCapInfo = params->ht_capa->extended_ht_cap_info; + rCmdUpdate.rHtCap.u4TxBfCapInfo = params->ht_capa->tx_BF_cap_info; + rCmdUpdate.rHtCap.ucAntennaSelInfo = params->ht_capa->antenna_selection_info; + kalMemCopy(rCmdUpdate.rHtCap.rMCS.arRxMask, + params->ht_capa->mcs.rx_mask, sizeof(rCmdUpdate.rHtCap.rMCS.arRxMask)); + rCmdUpdate.rHtCap.rMCS.u2RxHighest = params->ht_capa->mcs.rx_highest; + rCmdUpdate.rHtCap.rMCS.ucTxParams = params->ht_capa->mcs.tx_params; + rCmdUpdate.fgIsSupHt = TRUE; + } + + /* update a TDLS peer record */ + rStatus = kalIoctl(prGlueInfo, + TdlsexPeerUpdate, + &rCmdUpdate, sizeof(TDLS_CMD_PEER_UPDATE_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s update error:%x\n", __func__, rStatus); + return -EINVAL; + } +#endif /* CFG_SUPPORT_TDLS */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for adding a station information + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params) +{ +#if (CFG_SUPPORT_TDLS == 1) + /* from supplicant -- wpa_supplicant_tdls_peer_addset() */ + P_GLUE_INFO_T prGlueInfo; + TDLS_CMD_PEER_ADD_T rCmdCreate; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + if ((wiphy == NULL) || (mac == NULL) || (params == NULL)) + return -EINVAL; + + /* + wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, + NULL, 0); + + wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, + u16 aid, u16 capability, const u8 *supp_rates, + size_t supp_rates_len, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u8 qosinfo, const u8 *ext_capab, size_t ext_capab_len) + + Only MAC address of the peer is valid. + */ + + DBGLOG(TDLS, INFO, "%s: 0x%p %d\n", __func__, params->supported_rates, params->supported_rates_len); + + /* sanity check */ + if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) + return -EOPNOTSUPP; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (prGlueInfo == NULL) + return -EINVAL; + + /* TODO: check if we are station mode, not AP mode */ + + /* init */ + kalMemZero(&rCmdCreate, sizeof(rCmdCreate)); + kalMemCopy(rCmdCreate.aucPeerMac, mac, 6); + +#if 0 + rCmdCreate.eNetTypeIndex = NETWORK_TYPE_AIS_INDEX; + + rCmdCreate.u2CapInfo = params->capability; + + DBGLOG(TDLS, INFO, " %s: capability = 0x%x\n", __func__, rCmdCreate.u2CapInfo); + + if ((params->supported_rates != NULL) && (params->supported_rates_len != 0)) { + UINT32 u4Idx; + + DBGLOG(TDLS, INFO, " %s: sup rate = 0x", __func__); + + rIeSup.ucId = ELEM_ID_SUP_RATES; + rIeSup.ucLength = params->supported_rates_len; + for (u4Idx = 0; u4Idx < rIeSup.ucLength; u4Idx++) { + rIeSup.aucSupportedRates[u4Idx] = params->supported_rates[u4Idx]; + DBGLOG(TDLS, INFO, "%x ", rIeSup.aucSupportedRates[u4Idx]); + } + DBGLOG(TDLS, INFO, "\n"); + + rateGetRateSetFromIEs(&rIeSup, + NULL, + &rCmdCreate.u2OperationalRateSet, + &rCmdCreate.u2BSSBasicRateSet, &rCmdCreate.fgIsUnknownBssBasicRate); + } + + /* phy type */ +#endif + + /* create a TDLS peer record */ + rStatus = kalIoctl(prGlueInfo, + TdlsexPeerAdd, + &rCmdCreate, sizeof(TDLS_CMD_PEER_ADD_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(TDLS, ERROR, "%s create error:%x\n", __func__, rStatus); + return -EINVAL; + } +#endif /* CFG_SUPPORT_TDLS */ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for deleting a station information + * + * @param + * + * @retval 0: successful + * others: failure + * + * @other + * must implement if you have add_station(). + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params) +//int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to do a scan + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +static PARAM_SCAN_REQUEST_EXT_T rScanRequest; +int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; +/* PARAM_SCAN_REQUEST_EXT_T rScanRequest; */ + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "mtk_cfg80211_scan\n"); + kalMemZero(&rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T)); + + /* check if there is any pending scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL) { + DBGLOG(REQ, ERROR, "prGlueInfo->prScanRequest != NULL\n"); + return -EBUSY; + } + + if (request->n_ssids == 0) { + rScanRequest.rSsid.u4SsidLen = 0; + } else if (request->n_ssids == 1) { + COPY_SSID(rScanRequest.rSsid.aucSsid, rScanRequest.rSsid.u4SsidLen, request->ssids[0].ssid, + request->ssids[0].ssid_len); + } else { + DBGLOG(REQ, ERROR, "request->n_ssids:%d\n", request->n_ssids); + return -EINVAL; + } + + if (request->ie_len > 0) { + rScanRequest.u4IELength = request->ie_len; + rScanRequest.pucIE = (PUINT_8) (request->ie); + } else { + rScanRequest.u4IELength = 0; + } +#if 0 + prGlueInfo->prScanRequest = request; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanExt, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); + prGlueInfo->prScanRequest = NULL; + return -EINVAL; + } + + /*prGlueInfo->prScanRequest = request;*/ +#endif + + prGlueInfo->prScanRequest = request; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScanExt, + &rScanRequest, sizeof(PARAM_SCAN_REQUEST_EXT_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + prGlueInfo->prScanRequest = NULL; + DBGLOG(REQ, ERROR, "scan error:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +static UINT_8 wepBuf[48]; + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to connect to + * the ESS with the specified parameters + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + UINT_32 cipher; + PARAM_CONNECT_T rNewSsid; + BOOLEAN fgCarryWPSIE = FALSE; + ENUM_PARAM_OP_MODE_T eOpMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "[wlan] mtk_cfg80211_connect %p %zu\n", sme->ie, sme->ie_len); + + if (prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode > NET_TYPE_AUTO_SWITCH) + eOpMode = NET_TYPE_AUTO_SWITCH; + else + eOpMode = prGlueInfo->prAdapter->rWifiVar.rConnSettings.eOPMode; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetInfrastructureMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA; + else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_WPA2; + else + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + + switch (sme->auth_type) { + case NL80211_AUTHTYPE_OPEN_SYSTEM: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + break; + case NL80211_AUTHTYPE_SHARED_KEY: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY; + break; + default: + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY; + break; + } + + if (sme->crypto.n_ciphers_pairwise) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4PairwiseKeyCipherSuite[0] = + sme->crypto.ciphers_pairwise[0]; + switch (sme->crypto.ciphers_pairwise[0]) { + case WLAN_CIPHER_SUITE_WEP40: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + break; + default: + DBGLOG(REQ, WARN, "invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + } + + if (sme->crypto.cipher_group) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.u4GroupKeyCipherSuite = sme->crypto.cipher_group; + switch (sme->crypto.cipher_group) { + case WLAN_CIPHER_SUITE_WEP40: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP40; + break; + case WLAN_CIPHER_SUITE_WEP104: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104; + break; + case WLAN_CIPHER_SUITE_TKIP: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_TKIP; + break; + case WLAN_CIPHER_SUITE_CCMP: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; + break; + case WLAN_CIPHER_SUITE_AES_CMAC: + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_CCMP; + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); + return -EINVAL; + } + } + + if (sme->crypto.n_akm_suites) { + prGlueInfo->prAdapter->rWifiVar.rConnSettings.rRsnInfo.au4AuthKeyMgtSuite[0] = + sme->crypto.akm_suites[0]; + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); + return -EINVAL; + } + } else if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2) { + switch (sme->crypto.akm_suites[0]) { + case WLAN_AKM_SUITE_8021X: + eAuthMode = AUTH_MODE_WPA2; + break; + case WLAN_AKM_SUITE_PSK: + eAuthMode = AUTH_MODE_WPA2_PSK; + break; + default: + DBGLOG(REQ, WARN, "invalid cipher group (%d)\n", sme->crypto.cipher_group); + return -EINVAL; + } + } + } + + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? + AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; + } + + prGlueInfo->rWpaInfo.fgPrivacyInvoke = sme->privacy; + + prGlueInfo->fgWpsActive = FALSE; +#if CFG_SUPPORT_HOTSPOT_2_0 + prGlueInfo->fgConnectHS20AP = FALSE; +#endif + + if (sme->ie && sme->ie_len > 0) { + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PUINT_8 prDesiredIE = NULL; + PUINT_8 pucIEStart = (PUINT_8)sme->ie; + +#if CFG_SUPPORT_WAPI + if (wextSrchDesiredWAPIIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, "[wapi] set wapi assoc info error:%x\n", rStatus); + } +#endif + + DBGLOG(REQ, TRACE, "[wlan] wlanoidSetWapiAssocInfo: .fgWapiMode = %d\n", + prGlueInfo->prAdapter->rWifiVar.rConnSettings.fgWapiMode); + +#if CFG_SUPPORT_WPS2 + if (wextSrchDesiredWPSIE(pucIEStart, sme->ie_len, 0xDD, (PUINT_8 *) &prDesiredIE)) { + prGlueInfo->fgWpsActive = TRUE; + fgCarryWPSIE = TRUE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWSCAssocInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(SEC, WARN, "WSC] set WSC assoc info error:%x\n", rStatus); + } +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 + if (wextSrchDesiredHS20IE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ + } + } + if (wextSrchDesiredInterworkingIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set Interworking assoc info error:%lx\n", rStatus); */ + } + } + if (wextSrchDesiredRoamingConsortiumIE(pucIEStart, sme->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus); */ + } + } +#endif + } + + /* clear WSC Assoc IE buffer in case WPS IE is not detected */ + if (fgCarryWPSIE == FALSE) { + kalMemZero(&prGlueInfo->aucWSCAssocInfoIE, 200); + prGlueInfo->u2WSCAssocInfoIELen = 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set auth mode error:%x\n", rStatus); + + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) { + if (cipher & IW_AUTH_CIPHER_CCMP) { + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_TKIP) { + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_NONE) { + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + } else { + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "set encryption mode error:%x\n", rStatus); + + if (sme->key_len != 0 && prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + prWepKey->u4Length = 12 + sme->key_len; + prWepKey->u4KeyLength = (UINT_32) sme->key_len; + prWepKey->u4KeyIndex = (UINT_32) sme->key_idx; + prWepKey->u4KeyIndex |= BIT(31); + if (prWepKey->u4KeyLength > 32) { + DBGLOG(REQ, ERROR, "Too long key length (%u)\n", prWepKey->u4KeyLength); + return -EINVAL; + } + kalMemCopy(prWepKey->aucKeyMaterial, sme->key, prWepKey->u4KeyLength); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + } + + if (sme->channel) + rNewSsid.u4CenterFreq = sme->channel->center_freq; + else + rNewSsid.u4CenterFreq = 0; + rNewSsid.pucBssid = (UINT_8 *)sme->bssid; + rNewSsid.pucSsid = (UINT_8 *)sme->ssid; + rNewSsid.u4SsidLen = sme->ssid_len; + rStatus = kalIoctl(prGlueInfo, + wlanoidSetConnect, + (PVOID)(&rNewSsid), sizeof(PARAM_CONNECT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "set SSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to disconnect from + * currently connected ESS + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to join an IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) +{ + PARAM_SSID_T rNewSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + UINT_32 u4BufLen = 0; + WLAN_STATUS rStatus; + struct ieee80211_channel *channel = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* set channel */ + if (params->chandef.chan) + channel = params->chandef.chan; + if (channel) { + u4ChnlFreq = nicChannelNum2Freq(channel->hw_value); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + } + + /* set SSID */ + kalMemCopy(rNewSsid.aucSsid, params->ssid, params->ssid_len); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID)(&rNewSsid), sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set SSID:%x\n", rStatus); + return -EFAULT; + } + + return 0; + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to leave from IBSS group + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "disassociate error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to configure + * WLAN power managemenet + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + PARAM_POWER_MODE ePowerMode; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + if (enabled) { + if (timeout == -1) + ePowerMode = Param_PowerModeFast_PSP; + else + ePowerMode = Param_PowerModeMAX_PSP; + } else { + ePowerMode = Param_PowerModeCAM; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set_power_mgmt error:%x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cache + * a PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); + return -ENOMEM; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, pmksa->bssid, 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, pmksa->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to remove + * a cached PMKID for a BSSID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) +{ + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to flush + * all cached PMKID + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_FLUSH\n"); + return -ENOMEM; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, prPmkid, sizeof(PARAM_PMKID_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, WARN, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + + return 0; +} + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + + DBGLOG(REQ, LOUD, "mtk_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(REQ, LOUD, "Open packet filer probe request\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(REQ, LOUD, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(REQ, LOUD, "Open packet filer action frame.\n"); + } else { + prGlueInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(REQ, LOUD, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(REQ, TRACE, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if (prGlueInfo->prAdapter != NULL) { + /* prGlueInfo->ulFlag |= GLUE_FLAG_FRAME_FILTER_AIS; */ + set_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(REQ, TRACE, "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof + (MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_cfg80211_mgmt_frame_register */ + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to stay on a + * specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_REMAIN_ON_CHANNEL_T prMsgChnlReq = (P_MSG_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); +#endif + + *cookie = prGlueInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + kalMemZero(prMsgChnlReq, sizeof(MSG_REMAIN_ON_CHANNEL_T)); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_AIS_REMAIN_ON_CHANNEL; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4DurationMs = duration; + + prMsgChnlReq->ucChannelNum = nicFreq2ChannelNum(chan->center_freq * 1000); + + switch (chan->band) { + case NL80211_BAND_2GHZ: + prMsgChnlReq->eBand = BAND_2G4; + break; + case NL80211_BAND_5GHZ: + prMsgChnlReq->eBand = BAND_5G; + break; + default: + prMsgChnlReq->eBand = BAND_2G4; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel staying + * on a specified channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_CANCEL_REMAIN_ON_CHANNEL_T prMsgChnlAbort = (P_MSG_CANCEL_REMAIN_ON_CHANNEL_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + +#if 1 + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); +#endif + + prMsgChnlAbort = + cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_CANCEL_REMAIN_ON_CHANNEL_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_AIS_CANCEL_REMAIN_ON_CHANNEL; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to send a management frame + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int +mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + + do { +#if 1 + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); +#endif + + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + *cookie = prGlueInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_AIS_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for requesting to cancel the wait time + * from transmitting a management frame on another channel + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + /* not implemented */ + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling sched_scan start/stop request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 i, u4BufLen; + P_PARAM_SCHED_SCAN_REQUEST prSchedScanRequest; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL) { + DBGLOG(SCN, ERROR, "(prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)\n"); + return -EBUSY; + } else if (request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM) { + DBGLOG(SCN, ERROR, "(request == NULL || request->n_match_sets > CFG_SCAN_SSID_MATCH_MAX_NUM)\n"); + /* invalid scheduled scan request */ + return -EINVAL; + } else if (/* !request->n_ssids || */!request->n_match_sets) { + /* invalid scheduled scan request */ + return -EINVAL; + } + + prSchedScanRequest = (P_PARAM_SCHED_SCAN_REQUEST) kalMemAlloc(sizeof(PARAM_SCHED_SCAN_REQUEST), VIR_MEM_TYPE); + if (prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "(prSchedScanRequest == NULL) kalMemAlloc fail\n"); + return -ENOMEM; + } + + kalMemZero(prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + prSchedScanRequest->u4SsidNum = request->n_match_sets; + for (i = 0; i < request->n_match_sets; i++) { + if (request->match_sets == NULL || &(request->match_sets[i]) == NULL) { + prSchedScanRequest->arSsid[i].u4SsidLen = 0; + } else { + COPY_SSID(prSchedScanRequest->arSsid[i].aucSsid, + prSchedScanRequest->arSsid[i].u4SsidLen, + request->match_sets[i].ssid.ssid, request->match_sets[i].ssid.ssid_len); + } + } + + prSchedScanRequest->u4IELength = request->ie_len; + if (request->ie_len > 0) + prSchedScanRequest->pucIE = (PUINT_8) (request->ie); + + prSchedScanRequest->u2ScanInterval = (UINT_16) (request->scan_plans[0].interval); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetStartSchedScan, + prSchedScanRequest, sizeof(PARAM_SCHED_SCAN_REQUEST), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + kalMemFree(prSchedScanRequest, VIR_MEM_TYPE, sizeof(PARAM_SCHED_SCAN_REQUEST)); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SCN, ERROR, "scheduled scan error:%x\n", rStatus); + return -EINVAL; + } + + prGlueInfo->prSchedScanRequest = request; + + return 0; +} + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev, u64 reqid) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + /* check if there is any pending scan/sched_scan not yet finished */ + if (prGlueInfo->prSchedScanRequest == NULL) { + DBGLOG(SCN, ERROR, "prGlueInfo->prSchedScanRequest == NULL\n"); + return -EBUSY; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetStopSchedScan, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(SCN, ERROR, "scheduled scan error, rStatus: %d\n", rStatus); + return -EINVAL; + } + + /* 1. reset first for newly incoming request */ + /* GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + /* GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); */ + + DBGLOG(SCN, TRACE, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, TRACE, "tx_thread return from kalSchedScanStoppped\n"); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for handling association request + * + * @param + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_MAC_ADDRESS arBssid; +#if CFG_SUPPORT_HOTSPOT_2_0 + PUINT_8 prDesiredIE = NULL; +#endif + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(arBssid, MAC_ADDR_LEN); + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &u4BufLen); + + /* 1. check BSSID */ + if (UNEQUAL_MAC_ADDR(arBssid, req->bss->bssid)) { + /* wrong MAC address */ + DBGLOG(REQ, WARN, "incorrect BSSID: [ %pM ] currently connected BSSID[ %pM ]\n", + req->bss->bssid, arBssid); + return -ENOENT; + } + + if (req->ie && req->ie_len > 0) { +#if CFG_SUPPORT_HOTSPOT_2_0 + if (wextSrchDesiredHS20IE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetHS20Info, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set HS20 assoc info error:%lx\n", rStatus); */ + } + } + + if (wextSrchDesiredInterworkingIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInterworkingInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set Interworking assoc info error:%lx\n", rStatus); */ + } + } + + if (wextSrchDesiredRoamingConsortiumIE((PUINT_8) req->ie, req->ie_len, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingConsortiumIEInfo, + prDesiredIE, IE_SIZE(prDesiredIE), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[HS20] set RoamingConsortium assoc info error:%lx\n", rStatus); */ + } + } +#endif + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssid, + (PVOID) req->bss->bssid, MAC_ADDR_LEN, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, WARN, "set BSSID:%x\n", rStatus); + return -EINVAL; + } + + return 0; +} + +#if CONFIG_NL80211_TESTMODE +/* +#define NLA_PUT(skb, attrtype, attrlen, data) \ +do { \ + if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ + goto nla_put_failure; \ +} while (0) + +#define NLA_PUT_TYPE(skb, type, attrtype, value) \ +do { \ + type __tmp = value; \ + NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ +} while (0) + +#define NLA_PUT_U8(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, u8, attrtype, value) + +#define NLA_PUT_U16(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, u16, attrtype, value) + +#define NLA_PUT_U32(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, u32, attrtype, value) + +#define NLA_PUT_U64(skb, attrtype, value) \ + NLA_PUT_TYPE(skb, u64, attrtype, value) +*/ +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SET_KEY_EXTS prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) NULL; + struct iw_encode_exts *prIWEncExt = (struct iw_encode_exts *)NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4BufLen = 0; + + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + if (data && len) { + prParams = (P_NL80211_DRIVER_SET_KEY_EXTS) data; + } else { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_key_ext, data is NULL\n"); + return -EINVAL; + } + + if (prParams) + prIWEncExt = (struct iw_encode_exts *)&prParams->ext; + + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + /* KeyID */ + prWpiKey->ucKeyID = prParams->key_index; + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ + return -EINVAL; + } + /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } +/* #if CFG_SUPPORT_WAPI */ + /* handle_sec_msg_final(prIWEncExt->key, 32, prIWEncExt->key, NULL); */ +/* #endif */ + /* PN */ + memcpy(prWpiKey->aucPN, prIWEncExt->tx_seq, IW_ENCODE_SEQ_MAX_SIZE); + memcpy(prWpiKey->aucPN + IW_ENCODE_SEQ_MAX_SIZE, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rstatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rstatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ + fgIsValid = -EFAULT; + } + + } + return fgIsValid; +} +#endif + +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + UINT_32 u4LinkScore; + UINT_32 u4TotalError; + UINT_32 u4TxExceedThresholdCount; + UINT_32 u4TxTotalCount; + + P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; + PARAM_GET_STA_STA_STATISTICS rQueryStaStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) { + prParams = (P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS) data; + } else { + DBGLOG(QM, ERROR, "mtk_cfg80211_testmode_get_sta_statistics, data is NULL\n"); + return -EINVAL; + } +/* + if (!prParams->aucMacAddr) { + DBGLOG(QM, INFO, "%s MAC Address is NULL\n", __func__); + return -EINVAL; + } +*/ + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, ERROR, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + DBGLOG(QM, TRACE, "Get [ %pM ] STA statistics\n", prParams->aucMacAddr); + + kalMemZero(&rQueryStaStatistics, sizeof(rQueryStaStatistics)); + COPY_MAC_ADDR(rQueryStaStatistics.aucMacAddr, prParams->aucMacAddr); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStaStatistics, + &rQueryStaStatistics, sizeof(rQueryStaStatistics), TRUE, FALSE, TRUE, TRUE, &u4BufLen); + + /* Calcute Link Score */ + u4TxExceedThresholdCount = rQueryStaStatistics.u4TxExceedThresholdCount; + u4TxTotalCount = rQueryStaStatistics.u4TxTotalCount; + u4TotalError = rQueryStaStatistics.u4TxFailCount + rQueryStaStatistics.u4TxLifeTimeoutCount; + + /* u4LinkScore 10~100 , ExceedThreshold ratio 0~90 only */ + /* u4LinkScore 0~9 , Drop packet ratio 0~9 and all packets exceed threshold */ + if (u4TxTotalCount) { + if (u4TxExceedThresholdCount <= u4TxTotalCount) + u4LinkScore = (90 - ((u4TxExceedThresholdCount * 90) / u4TxTotalCount)); + else + u4LinkScore = 0; + } else { + u4LinkScore = 90; + } + + u4LinkScore += 10; + + if (u4LinkScore == 10) { + + if (u4TotalError <= u4TxTotalCount) + u4LinkScore = (10 - ((u4TotalError * 10) / u4TxTotalCount)); + else + u4LinkScore = 0; + + } + + if (u4LinkScore > 100) + u4LinkScore = 100; + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);*/ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, NL80211_DRIVER_TESTMODE_VERSION);*/ + { + unsigned char __tmp = NL80211_DRIVER_TESTMODE_VERSION; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_VERSION, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /* NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, u4LinkScore); */ + { + unsigned int __tmp = u4LinkScore; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, prParams->aucMacAddr);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAC, MAC_ADDR_LEN, &prParams->aucMacAddr) < 0)) + goto nla_put_failure; + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, rQueryStaStatistics.u4Flag);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4Flag; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FLAG, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + /* FW part STA link status */ + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_PER, rQueryStaStatistics.ucPer);*/ + { + unsigned char __tmp = rQueryStaStatistics.ucPer; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PER, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, rQueryStaStatistics.ucRcpi);*/ + { + unsigned char __tmp = rQueryStaStatistics.ucRcpi; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RSSI, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, rQueryStaStatistics.u4PhyMode);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4PhyMode; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U16(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, rQueryStaStatistics.u2LinkSpeed);*/ + { + unsigned short __tmp = rQueryStaStatistics.u2LinkSpeed; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + sizeof(unsigned short), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, rQueryStaStatistics.u4TxFailCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxFailCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, rQueryStaStatistics.u4TxLifeTimeoutCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxLifeTimeoutCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, rQueryStaStatistics.u4TxAverageAirTime);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageAirTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* Driver part link status */ + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, rQueryStaStatistics.u4TxTotalCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxTotalCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + rQueryStaStatistics.u4TxExceedThresholdCount);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxExceedThresholdCount; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + rQueryStaStatistics.u4TxAverageProcessTime);*/ + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageProcessTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = rQueryStaStatistics.u4TxMaxTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + { + unsigned int __tmp = rQueryStaStatistics.u4TxAverageHifTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + { + unsigned int __tmp = rQueryStaStatistics.u4TxMaxHifTime; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, rQueryStaStatistics.u4EnqueueCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4EnqueueCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, rQueryStaStatistics.u4DequeueCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4DequeueCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, rQueryStaStatistics.u4EnqueueStaCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4EnqueueStaCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, rQueryStaStatistics.u4DequeueStaCounter); + */ + { + unsigned int __tmp = rQueryStaStatistics.u4DequeueStaCounter; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, rQueryStaStatistics.IsrCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, rQueryStaStatistics.IsrPassCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrPassCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, rQueryStaStatistics.TaskIsrCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.TaskIsrCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, rQueryStaStatistics.IsrAbnormalCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrAbnormalCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, rQueryStaStatistics.IsrSoftWareCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrSoftWareCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + * NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, rQueryStaStatistics.IsrTxCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrTxCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* + *NLA_PUT_U32(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, rQueryStaStatistics.IsrRxCnt); + */ + { + unsigned int __tmp = rQueryStaStatistics.IsrRxCnt; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + /* Network counter */ + /*NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), rQueryStaStatistics.au4TcResourceEmptyCount);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceEmptyCount), &rQueryStaStatistics.au4TcResourceEmptyCount) < 0)) + goto nla_put_failure; + /* + NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), rQueryStaStatistics.au4DequeueNoTcResource); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + sizeof(rQueryStaStatistics.au4DequeueNoTcResource), &rQueryStaStatistics.au4DequeueNoTcResource) < 0)) + goto nla_put_failure; + /* + NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), rQueryStaStatistics.au4TcResourceBackCount); + */ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceBackCount), &rQueryStaStatistics.au4TcResourceBackCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceUsedCount), &rQueryStaStatistics.au4TcResourceUsedCount) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, + sizeof(rQueryStaStatistics.au4TcResourceWantedCount), + &rQueryStaStatistics.au4TcResourceWantedCount) < 0)) + goto nla_put_failure; + + /* Sta queue length */ + /*NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), rQueryStaStatistics.au4TcQueLen);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcQueLen), &rQueryStaStatistics.au4TcQueLen) < 0)) + goto nla_put_failure; + + + /* Global QM counter */ + /*NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), rQueryStaStatistics.au4TcAverageQueLen);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcAverageQueLen), &rQueryStaStatistics.au4TcAverageQueLen) < 0)) + goto nla_put_failure; + + /*NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), rQueryStaStatistics.au4TcCurrentQueLen);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + sizeof(rQueryStaStatistics.au4TcCurrentQueLen), &rQueryStaStatistics.au4TcCurrentQueLen) < 0)) + goto nla_put_failure; + + + /* Reserved field */ + /*NLA_PUT(skb, + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), rQueryStaStatistics.au4Reserved);*/ + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + sizeof(rQueryStaStatistics.au4Reserved), &rQueryStaStatistics.au4Reserved) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +int +mtk_cfg80211_testmode_get_link_detection(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen; + + PARAM_802_11_STATISTICS_STRUCT_T rStatistics; + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(PARAM_GET_STA_STA_STATISTICS) + 1); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + kalMemZero(&rStatistics, sizeof(rStatistics)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rStatistics, sizeof(rStatistics), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0);*/ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, rStatistics.rFailedCount.QuadPart);*/ + { + u64 __tmp = rStatistics.rFailedCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_FAIL_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, rStatistics.rRetryCount.QuadPart);*/ + { + u64 __tmp = rStatistics.rFailedCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_RETRY_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, rStatistics.rMultipleRetryCount.QuadPart);*/ + { + u64 __tmp = rStatistics.rMultipleRetryCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, rStatistics.rACKFailureCount.QuadPart);*/ + { + u64 __tmp = rStatistics.rACKFailureCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U64(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, rStatistics.rFCSErrorCount.QuadPart);*/ + { + u64 __tmp = rStatistics.rFCSErrorCount.QuadPart; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_LINK_FCS_ERR_CNT, + sizeof(u64), &__tmp) < 0)) + goto nla_put_failure; + } + + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + } + + if (WLAN_STATUS_SUCCESS != rstatus) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#if CFG_SUPPORT_HOTSPOT_2_0 +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wpa_driver_hs20_data_s *prParams = NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + DBGLOG(REQ, TRACE, "--> %s()\n", __func__); + + if (data && len) { + prParams = (struct wpa_driver_hs20_data_s *)data; + + DBGLOG(REQ, TRACE, "[%s] Cmd Type (%d)\n", __func__, prParams->CmdType); + } + + if (prParams) { + int i; + + switch (prParams->CmdType) { + case HS20_CMD_ID_SET_BSSID_POOL: + DBGLOG(REQ, TRACE, "fgBssidPoolIsEnable=%d, ucNumBssidPool=%d\n", + prParams->hs20_set_bssid_pool.fgBssidPoolIsEnable, + prParams->hs20_set_bssid_pool.ucNumBssidPool); + for (i = 0; i < prParams->hs20_set_bssid_pool.ucNumBssidPool; i++) { + DBGLOG(REQ, TRACE, "[%d][ %pM ]\n", i, + (prParams->hs20_set_bssid_pool.arBssidPool[i])); + } + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetHS20BssidPool, + &prParams->hs20_set_bssid_pool, + sizeof(struct param_hs20_set_bssid_pool), + FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + break; + default: + DBGLOG(REQ, TRACE, "[%s] Unknown Cmd Type (%d)\n", __func__, prParams->CmdType); + rstatus = WLAN_STATUS_FAILURE; + + } + + } + + if (WLAN_STATUS_SUCCESS != rstatus) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#endif +int +mtk_cfg80211_testmode_set_poorlink_param(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ + int fgIsValid = 0; + P_NL80211_DRIVER_POORLINK_PARAMS prParams = NULL; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + if (data && len) { + prParams = (P_NL80211_DRIVER_POORLINK_PARAMS) data; + } else { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_set_poorlink_param, data is NULL\n"); + return -EINVAL; + } + if (prParams->ucLinkSpeed) + prGlueInfo->u4LinkspeedThreshold = prParams->ucLinkSpeed * 10; + if (prParams->cRssi) + prGlueInfo->i4RssiThreshold = prParams->cRssi; + if (!prGlueInfo->fgPoorlinkValid) + prGlueInfo->fgPoorlinkValid = 1; +#if 0 + DBGLOG(REQ, TRACE, "poorlink set param valid(%d)rssi(%d)linkspeed(%d)\n", + prGlueInfo->fgPoorlinkValid, prGlueInfo->i4RssiThreshold, prGlueInfo->u4LinkspeedThreshold); +#endif + + return fgIsValid; + +} + +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_MODE_PARAMS prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) NULL; + INT_32 i4Status = -EINVAL; +#if CFG_SUPPORT_HOTSPOT_2_0 + BOOLEAN fgIsValid = 0; +#endif + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_MODE_PARAMS) data; + } else { + DBGLOG(REQ, ERROR, "mtk_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case TESTMODE_CMD_ID_SW_CMD: /* SW cmd */ + i4Status = mtk_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + case TESTMODE_CMD_ID_WAPI: /* WAPI */ +#if CFG_SUPPORT_WAPI + i4Status = mtk_cfg80211_testmode_set_key_ext(wiphy, data, len); +#endif + break; + case TESTMODE_CMD_ID_SUSPEND: + { + P_NL80211_DRIVER_SUSPEND_PARAMS prParams = (P_NL80211_DRIVER_SUSPEND_PARAMS) data; + + if (prParams->suspend == 1) { + wlanHandleSystemSuspend(); + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pHandleSystemSuspend(); + i4Status = 0; + } else if (prParams->suspend == 0) { + wlanHandleSystemResume(); + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pHandleSystemResume(); + i4Status = 0; + } + break; + } + case TESTMODE_CMD_ID_STATISTICS: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_LINK_DETECT: + i4Status = mtk_cfg80211_testmode_get_link_detection(wiphy, data, len, prGlueInfo); + break; + case TESTMODE_CMD_ID_POORLINK: + i4Status = mtk_cfg80211_testmode_set_poorlink_param(wiphy, data, len, prGlueInfo); + break; + +#if CFG_SUPPORT_HOTSPOT_2_0 + case TESTMODE_CMD_ID_HS20: + if (mtk_cfg80211_testmode_hs20_cmd(wiphy, data, len)) + fgIsValid = TRUE; + break; +#endif + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; +} + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ +#define NL80211_TESTMODE_P2P_SCANDONE_INVALID 0 +#define NL80211_TESTMODE_P2P_SCANDONE_STATUS 1 + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + INT_32 i4Status = -EINVAL, READY_TO_BEAM = 0; + +/* P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS prParams = NULL; */ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(prGlueInfo); + + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(UINT_32)); + READY_TO_BEAM = + (UINT_32) (prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo. + fgIsGOInitialDone) & + (!prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); + DBGLOG(QM, TRACE, + "NFC:GOInitialDone[%d] and P2PScanning[%d]\n", + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsGOInitialDone, + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rScanReqInfo.fgIsScanRequest); + + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, 0);*/ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + /*NLA_PUT_U32(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, READY_TO_BEAM);*/ + { + unsigned int __tmp = READY_TO_BEAM; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_P2P_SCANDONE_STATUS, sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + i4Status = cfg80211_testmode_reply(skb); + skb = NULL; + +nla_put_failure: + if (skb != NULL) + kfree_skb(skb); + return i4Status; +} + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +int +mtk_cfg80211_testmode_get_lte_channel(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo) +{ +#define MAXMUN_2_4G_CHA_NUM 14 +#define CHN_DIRTY_WEIGHT_UPPERBOUND 4 + + BOOLEAN fgIsReady = FALSE, fgIsFistRecord = TRUE; + BOOLEAN fgIsPureAP, fgIsLteSafeChn = FALSE; + + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_8 ucIdx = 0, ucMax_24G_Chn_List = 11, ucDefaultIdx = 0, ucArrayIdx = 0; + UINT_16 u2APNumScore = 0, u2UpThreshold = 0, u2LowThreshold = 0, ucInnerIdx = 0; + INT_32 i4Status = -EINVAL; + UINT_32 u4BufLen, u4LteSafeChnBitMask_2_4G = 0; + UINT32 AcsChnReport[4]; + /*RF_CHANNEL_INFO_T aucChannelList[MAXMUN_2_4G_CHA_NUM];*/ + + struct sk_buff *skb; + + /*PARAM_GET_CHN_LOAD rQueryLTEChn;*/ + P_PARAM_GET_CHN_LOAD prQueryLTEChn; + PARAM_PREFER_CHN_INFO rPreferChannels[2], ar2_4G_ChannelLoadingWeightScore[MAXMUN_2_4G_CHA_NUM]; + P_PARAM_CHN_LOAD_INFO prChnLoad; + P_PARAM_GET_CHN_LOAD prGetChnLoad; + + P_DOMAIN_INFO_ENTRY prDomainInfo; + +/* + P_PARAM_GET_CHN_LOAD prParams = NULL; +*/ + ASSERT(wiphy); + ASSERT(prGlueInfo); + + kalMemZero(rPreferChannels, sizeof(rPreferChannels)); + fgIsPureAP = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode; +#if 0 + if (data && len) + prParams = (P_NL80211_DRIVER_GET_LTE_PARAMS) data; +#endif + skb = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(AcsChnReport) + sizeof(UINT8) + 1); + if (!skb) { + DBGLOG(QM, TRACE, "%s allocate skb failed:%x\n", __func__, rStatus); + return -ENOMEM; + } + + DBGLOG(P2P, INFO, "[Auto Channel]Get LTE Channels\n"); + prQueryLTEChn = kalMemAlloc(sizeof(PARAM_GET_CHN_LOAD), VIR_MEM_TYPE); + if (prQueryLTEChn == NULL) { + DBGLOG(QM, TRACE, "alloc QueryLTEChn fail\n"); + kalMemFree(skb, VIR_MEM_TYPE, sizeof(struct sk_buff)); + return -ENOMEM; + } + kalMemZero(prQueryLTEChn, sizeof(PARAM_GET_CHN_LOAD)); + + /* Query LTE Safe Channels */ + prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] + = 0xFFFFFFFF; + + prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1] + = 0xFFFFFFFF; + + prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1] + = 0xFFFFFFFF; + + prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1] = + 0xFFFFFFFF; + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryACSChannelList, prQueryLTEChn, sizeof(PARAM_GET_CHN_LOAD), + TRUE, FALSE, TRUE, TRUE, &u4BufLen); +#if 0 + if (fgIsPureAP) { + + AcsChnRepot[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] = 0x20; /* Channel 6 */ + } else +#endif + { + fgIsReady = prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit; + rPreferChannels[0].u2APNum = 0xFFFF; + rPreferChannels[1].u2APNum = 0xFFFF; + + /* 4 In LTE Mode, Hotspot pick up channels from ch4. */ + ucDefaultIdx = 0; + /* + if (fgIsPureAP) { + ucDefaultIdx=3; //SKIP LTE Channels 1~3 + } + */ + + /* 4 Get the Maximun channel List in 2.4G Bands */ + + prDomainInfo = rlmDomainGetDomainInfo(prGlueInfo->prAdapter); + ASSERT(prDomainInfo); + + /* 4 ToDo: Enable Step 2 only if we could get Country Code from framework */ + /* 4 2. Get current domain channel list */ + +#if 0 + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_2G4, MAXMUN_2_4G_CHA_NUM, &ucMax_24G_Chn_List, aucChannelList); +#endif + + prGetChnLoad = (P_PARAM_GET_CHN_LOAD) &(prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo); + for (ucIdx = 0; ucIdx < ucMax_24G_Chn_List; ucIdx++) { + DBGLOG(P2P, INFO, + "[Auto Channel] ch[%d]=%d\n", ucIdx, + prGetChnLoad->rEachChnLoad[ucIdx + ucInnerIdx].u2APNum); + } + + /*Calculate Each Channel Direty Score */ + for (ucIdx = ucDefaultIdx; ucIdx < ucMax_24G_Chn_List; ucIdx++) { + +#if 1 + u2APNumScore = prGetChnLoad->rEachChnLoad[ucIdx].u2APNum * CHN_DIRTY_WEIGHT_UPPERBOUND; + u2UpThreshold = u2LowThreshold = 3; + + if (ucIdx < 3) { + u2UpThreshold = ucIdx; + u2LowThreshold = 3; + } else if (ucIdx >= (ucMax_24G_Chn_List - 3)) { + u2UpThreshold = 3; + u2LowThreshold = ucMax_24G_Chn_List - (ucIdx + 1); + + } + + /*Calculate Lower Channel Dirty Score */ + for (ucInnerIdx = 0; ucInnerIdx < u2LowThreshold; ucInnerIdx++) { + ucArrayIdx = ucIdx + ucInnerIdx + 1; + if (ucArrayIdx < MAX_AUTO_CHAL_NUM) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad[ucArrayIdx].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + } + + /*Calculate Upper Channel Dirty Score */ + for (ucInnerIdx = 0; ucInnerIdx < u2UpThreshold; ucInnerIdx++) { + ucArrayIdx = ucIdx - ucInnerIdx - 1; + if (ucArrayIdx < MAX_AUTO_CHAL_NUM) { + u2APNumScore += + (prGetChnLoad->rEachChnLoad[ucArrayIdx].u2APNum * + (CHN_DIRTY_WEIGHT_UPPERBOUND - 1 - ucInnerIdx)); + } + } + + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; + + DBGLOG(P2P, INFO, "[Auto Channel]chn=%d score=%d\n", ucIdx, u2APNumScore); +#else + if (ucIdx == 0) { + /* ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = + (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + + prGetChnLoad->rEachChnLoad[ucIdx+1].u2APNum*0.75); */ + u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ((UINT_16) + ((3 * + (prGetChnLoad-> + rEachChnLoad[ucIdx + + 1]. + u2APNum + + prGetChnLoad-> + rEachChnLoad[ucIdx + + 2]. + u2APNum)) / 4))); + + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; + DBGLOG(P2P, INFO, + "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d\n", ucIdx, + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx + 1].u2APNum)); + } + if ((ucIdx > 0) && (ucIdx < (MAXMUN_2_4G_CHA_NUM - 1))) { + u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + ((UINT_16) + ((3 * + (prGetChnLoad-> + rEachChnLoad[ucIdx + + 1]. + u2APNum + + prGetChnLoad-> + rEachChnLoad[ucIdx - + 1]. + u2APNum)) / 4))); + + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; + DBGLOG(P2P, INFO, + "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d+0.75*%d\n", ucIdx, + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx + 1].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum)); + } + + if (ucIdx == (MAXMUN_2_4G_CHA_NUM - 1)) { + u2APNumScore = (prGetChnLoad->rEachChnLoad[ucIdx].u2APNum + + ((UINT_16) ((3 * prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum) / 4))); + + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum = u2APNumScore; + DBGLOG(P2P, INFO, + "[Auto Channel]ucIdx=%d score=%d=%d+0.75*%d\n", ucIdx, + ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx].u2APNum, + prGetChnLoad->rEachChnLoad[ucIdx - 1].u2APNum)); + } +#endif + + } + + u4LteSafeChnBitMask_2_4G = + prQueryLTEChn->rLteSafeChnList.au4SafeChannelBitmask[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]; + + /*Find out the best channel */ + for (ucIdx = ucDefaultIdx; ucIdx < ucMax_24G_Chn_List; ucIdx++) { + /* 4 Skip LTE Unsafe Channel */ + fgIsLteSafeChn = ((u4LteSafeChnBitMask_2_4G & BIT(ucIdx + 1)) >> ucIdx); + if (!fgIsLteSafeChn) + continue; + + prChnLoad = + (P_PARAM_CHN_LOAD_INFO) &(prGlueInfo->prAdapter->rWifiVar. + rChnLoadInfo.rEachChnLoad[ucIdx]); + if (rPreferChannels[0].u2APNum >= ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum) { + rPreferChannels[1].ucChannel = rPreferChannels[0].ucChannel; + rPreferChannels[1].u2APNum = rPreferChannels[0].u2APNum; + + rPreferChannels[0].ucChannel = ucIdx; + rPreferChannels[0].u2APNum = ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum; + } else { + if (rPreferChannels[1].u2APNum >= ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum + || fgIsFistRecord == 1) { + fgIsFistRecord = FALSE; + rPreferChannels[1].ucChannel = ucIdx; + rPreferChannels[1].u2APNum = ar2_4G_ChannelLoadingWeightScore[ucIdx].u2APNum; + } + } + } + /* AcsChnRepot[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1-1] = + BITS((rQueryLTEChn.rLteSafeChnList.ucChannelLow-1),(rQueryLTEChn.rLteSafeChnList.ucChannelHigh-1)); */ + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] = fgIsReady ? BIT(31) : 0; + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1] |= BIT(rPreferChannels[0].ucChannel); + } + + /* ToDo: Support 5G Channel Selection */ + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1] = 0x11223344; + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1] = 0x55667788; + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1] = 0x99AABBCC; + + /*NLA_PUT_U8(skb, NL80211_TESTMODE_AVAILABLE_CHAN_INVALID, 0);*/ + { + unsigned char __tmp = 0; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_INVALID, sizeof(unsigned char), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]);*/ + { + unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1 - 1]; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1]);*/ + { + unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34 - 1]; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1]);*/ + { + unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149 - 1]; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + + /*NLA_PUT_U32(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, + AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1]);*/ + { + unsigned int __tmp = AcsChnReport[NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184 - 1]; + + if (unlikely(nla_put(skb, NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + DBGLOG(P2P, INFO, + "[Auto Channel]Relpy AcsChanInfo[%x:%x:%x:%x]\n", AcsChnReport[0], AcsChnReport[1], AcsChnReport[2], + AcsChnReport[3]); + + i4Status = cfg80211_testmode_reply(skb); + /*need confirm cfg80211_testmode_reply will free skb*/ + skb = NULL; + /*kalMemFree(prQueryLTEChn, VIR_MEM_TYPE, sizeof(PARAM_GET_CHN_LOAD));*/ + +nla_put_failure: + kalMemFree(prQueryLTEChn, VIR_MEM_TYPE, sizeof(PARAM_GET_CHN_LOAD)); + if (skb != NULL) + kfree_skb(skb); + return i4Status; + +} +#endif +#endif + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 suspend callback, will be invoked in wiphy_suspend + * + * @param wiphy: pointer to wiphy + * wow: pointer to cfg80211_wowlan + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + set_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prGlueInfo->prAdapter->ulSuspendFlag); + set_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prGlueInfo->prAdapter->ulSuspendFlag); +end: + kalHaltUnlock(); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief cfg80211 resume callback, will be invoked in wiphy_resume. + * + * @param wiphy: pointer to wiphy + * + * @retval 0: successful + * others: failure + */ +/*----------------------------------------------------------------------------*/ +int mtk_cfg80211_resume(struct wiphy *wiphy) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_BSS_DESC_T *pprBssDesc = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_8 i = 0; + + if (kalHaltTryLock()) + return 0; + + if (kalIsHalted() || !wiphy) + goto end; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + prAdapter = prGlueInfo->prAdapter; + clear_bit(SUSPEND_FLAG_CLEAR_WHEN_RESUME, &prAdapter->ulSuspendFlag); + pprBssDesc = &prAdapter->rWifiVar.rScanInfo.rNloParam.aprPendingBssDescToInd[0]; + for (; i < SCN_SSID_MATCH_MAX_NUM; i++) { + if (pprBssDesc[i] == NULL) + break; + if (pprBssDesc[i]->u2RawLength == 0) + continue; + kalIndicateBssInfo(prGlueInfo, + (PUINT_8) pprBssDesc[i]->aucRawBuf, + pprBssDesc[i]->u2RawLength, + pprBssDesc[i]->ucChannelNum, + RCPI_TO_dBm(pprBssDesc[i]->ucRCPI)); + } + DBGLOG(SCN, INFO, "pending %d sched scan results\n", i); + if (i > 0) + kalMemZero(&pprBssDesc[0], i * sizeof(P_BSS_DESC_T)); +end: + kalHaltUnlock(); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c new file mode 100644 index 0000000000000..055fa9fc7ff33 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_init.c @@ -0,0 +1,3501 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_init.c#7 +*/ + +/*! \file gl_init.c + \brief Main routines of Linux driver + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_init.c +** +** 09 03 2013 cp.wu +** add path for reassociation + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 05 25 2012 yuche.tsai + * NULL + * Fix reset KE issue. + * + * 05 11 2012 cp.wu + * [WCXRP00001237] [MT6620 Wi-Fi][Driver] Show MAC address and MAC address source for ACS's convenience + * show MAC address & source while initiliazation + * + * 03 02 2012 terry.wu + * NULL + * EXPORT_SYMBOL(rsnParseCheckForWFAInfoElem);. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 03 02 2012 terry.wu + * NULL + * Sync CFG80211 modification from branch 2,2. + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 12 22 2011 george.huang + * [WCXRP00000905] [MT6628 Wi-Fi][FW] Code refinement for ROM/ RAM module dependency + * using global variable instead of stack for setting wlanoidSetNetworkAddress(), due to buffer may be released before + * TX thread handling + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 14 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Fix large network type index assert in FW issue. + * + * 11 14 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 06 2011 eddie.chen + * [WCXRP00001027] [MT6628 Wi-Fi][Firmware/Driver] Tx fragmentation + * Add rlmDomainGetChnlList symbol. + * + * 09 22 2011 cm.chang + * NULL + * Safer writng stype to avoid unitialized regitry structure + * + * 09 21 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Avoid possible structure alignment problem + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 09 08 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * Use new fields ucChannelListMap and ucChannelListIndex in NVRAM + * + * 08 31 2011 cm.chang + * [WCXRP00000969] [MT6620 Wi-Fi][Driver][FW] Channel list for 5G band based on country code + * . + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * expose scnQuerySparseChannel() for P2P-FSM. + * + * 08 11 2011 cp.wu + * [WCXRP00000830] [MT6620 Wi-Fi][Firmware] Use MDRDY counter to detect empty channel for shortening scan time + * sparse channel detection: + * driver: collect sparse channel information with scan-done event + * + * 08 02 2011 yuche.tsai + * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting + * device issue. + * Fix GO send deauth frame issue. + * + * 07 07 2011 wh.su + * [WCXRP00000839] [MT6620 Wi-Fi][Driver] Add the dumpMemory8 and dumpMemory32 EXPORT_SYMBOL + * Add the dumpMemory8 symbol export for debug mode. + * + * 07 06 2011 terry.wu + * [WCXRP00000735] [MT6620 Wi-Fi][BoW][FW/Driver] Protect BoW connection establishment + * Improve BoW connection establishment speed. + * + * 07 05 2011 yuche.tsai + * [WCXRP00000821] [Volunteer Patch][WiFi Direct][Driver] WiFi Direct Connection Speed Issue + * Export one symbol for enhancement. + * + * 06 13 2011 eddie.chen + * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni + * Add tx rx statistics and netif_rx_ni. + * + * 05 27 2011 cp.wu + * [WCXRP00000749] [MT6620 Wi-Fi][Driver] Add band edge tx power control to Wi-Fi NVRAM + * invoke CMD_ID_SET_EDGE_TXPWR_LIMIT when there is valid data exist in NVRAM content. + * + * 05 18 2011 cp.wu + * [WCXRP00000734] [MT6620 Wi-Fi][Driver] Pass PHY_PARAM in NVRAM to firmware domain + * pass PHY_PARAM in NVRAM from driver to firmware. + * + * 05 09 2011 jeffrey.chang + * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change + * support ARP filter through kernel notifier + * + * 05 03 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Use kalMemAlloc to allocate event buffer for kalIndicateBOWEvent. + * + * 04 27 2011 george.huang + * [WCXRP00000684] [MT6620 Wi-Fi][Driver] Support P2P setting ARP filter + * Support P2P ARP filter setting on early suspend/ late resume + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Modify some driver connection flow or behavior to pass Sigma test more easier.. + * + * 04 12 2011 cm.chang + * [WCXRP00000634] [MT6620 Wi-Fi][Driver][FW] 2nd BSS will not support 40MHz bandwidth for concurrency + * . + * + * 04 11 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * export wlan functions to p2p + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * glBusFreeIrq() should use the same pvCookie as glBusSetIrq() or request_irq()/free_irq() won't work as a pair. + * + * 04 08 2011 eddie.chen + * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma + * Fix for sigma + * + * 04 06 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. do not check for pvData inside wlanNetCreate() due to it is NULL for eHPI port + * 2. update perm_addr as well for MAC address + * 3. not calling check_mem_region() anymore for eHPI + * 4. correct MSC_CS macro for 0-based notation + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * fix typo. + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 23 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * apply multi-queue operation only for linux kernel > 2.6.26 + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability for compatible with linux 2.6.12. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 18 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * remove early suspend functions + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * reverse order to prevent probing racing. + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similar APIs to hide the difference. + * + * 03 15 2011 jeffrey.chang + * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM + * refine the queue_select function + * + * 03 10 2011 cp.wu + * [WCXRP00000532] [MT6620 Wi-Fi][Driver] Migrate NVRAM configuration procedures from MT6620 E2 to MT6620 E3 + * deprecate configuration used by MT6620 E2 + * + * 03 10 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Remove unnecessary assert and message. + * + * 03 08 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Export nicQmUpdateWmmParms. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 02 24 2011 george.huang + * [WCXRP00000495] [MT6620 Wi-Fi][FW] Support pattern filter for unwanted ARP frames + * Support ARP filter during suspended + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 02 17 2011 terry.wu + * [WCXRP00000459] [MT6620 Wi-Fi][Driver] Fix deference null pointer problem in wlanRemove + * Fix deference a null pointer problem in wlanRemove. + * + * 02 16 2011 jeffrey.chang + * NULL + * fix compilig error + * + * 02 16 2011 jeffrey.chang + * NULL + * Add query ipv4 and ipv6 address during early suspend and late resume + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 02 11 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add one more export symbol. + * + * 02 10 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add RX deauthentication & disassociation process under Hot-Spot mode. + * + * 02 09 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Halt p2p module init and exit until TxThread finished p2p register and unregister. + * + * 02 08 2011 george.huang + * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler + * Support querying power mode OID. + * + * 02 08 2011 yuche.tsai + * [WCXRP00000421] [Volunteer Patch][MT6620][Driver] Fix incorrect SSID length Issue + * Export Deactivation Network. + * + * 02 01 2011 jeffrey.chang + * [WCXRP00000414] KAL Timer is not unregistered when driver not loaded + * Unregister the KAL timer during driver unloading + * + * 01 26 2011 cm.chang + * [WCXRP00000395] [MT6620 Wi-Fi][Driver][FW] Search STA_REC with additional net type index argument + * Allocate system RAM if fixed message or mgmt buffer is not available + * + * 01 19 2011 cp.wu + * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 + * add compile option to check linux version 2.6.35 for different usage of system API to improve portability + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues + * due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 15 2010 cp.wu + * [WCXRP00000265] [MT6620 Wi-Fi][Driver] Remove set_mac_address routine from legacy Wi-Fi Android driver + * remove set MAC address. MAC address is always loaded from NVRAM instead. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] + * Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 21 2010 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * . + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK + * HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000106] [MT6620 Wi-Fi][Driver] Enable setting multicast callback in Android + * . + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 27 2010 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000065] Update BoW design and settings + * Update BCM/BoW design and settings. + * + * 09 23 2010 cp.wu + * [WCXRP00000051] [MT6620 Wi-Fi][Driver] WHQL test fail in MAC address changed item + * use firmware reported mac address right after wlanAdapterStart() as permanent address + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 16 2010 yarco.yang + * NULL + * Support Linux x86 + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 jeffrey.chang + * NULL + * fix memory leak for module unloading + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 23 2010 jeffrey.chang + * + * bug fix: allocate regInfo when disabling firmware download + * + * 07 23 2010 jeffrey.chang + * + * use glue layer api to decrease or increase counter atomically + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power management macro + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Query statistics from firmware + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * modify tcp/ip checksum offload flags + * + * 04 16 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix tcp/ip checksum offload bug + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler + * * * * * * * * * * * * * * * * * capability + * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set MAC address from firmware + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * are done in adapter layer. + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)improve none-glue code portability + * * (2) disable set Multicast address during atomic context + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding debug module + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix f/w download start and load address by using config.h + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download support + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\52 2009-10-27 22:49:59 GMT mtk01090 +** Fix compile error for Linux EHPI driver +** \main\maintrunk.MT5921\51 2009-10-20 17:38:22 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, +** and then stop hw. +** \main\maintrunk.MT5921\50 2009-10-08 10:33:11 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input +** parameters and pointers. +** \main\maintrunk.MT5921\49 2009-09-28 20:19:05 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\48 2009-09-03 13:58:46 GMT mtk01088 +** remove non-used code +** \main\maintrunk.MT5921\47 2009-09-03 11:40:25 GMT mtk01088 +** adding the module parameter for wapi +** \main\maintrunk.MT5921\46 2009-08-18 22:56:41 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\45 2009-07-06 20:53:00 GMT mtk01088 +** adding the code to check the wapi 1x frame +** \main\maintrunk.MT5921\44 2009-06-23 23:18:55 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\43 2009-02-16 23:46:51 GMT mtk01461 +** Revise the order of increasing u4TxPendingFrameNum because of CFG_TX_RET_TX_CTRL_EARLY +** \main\maintrunk.MT5921\42 2009-01-22 13:11:59 GMT mtk01088 +** set the tid and 1x value at same packet reserved field +** \main\maintrunk.MT5921\41 2008-10-20 22:43:53 GMT mtk01104 +** Fix wrong variable name "prDev" in wlanStop() +** \main\maintrunk.MT5921\40 2008-10-16 15:37:10 GMT mtk01461 +** add handle WLAN_STATUS_SUCCESS in wlanHardStartXmit() for CFG_TX_RET_TX_CTRL_EARLY +** \main\maintrunk.MT5921\39 2008-09-25 15:56:21 GMT mtk01461 +** Update driver for Code review +** \main\maintrunk.MT5921\38 2008-09-05 17:25:07 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\37 2008-09-02 10:57:06 GMT mtk01461 +** Update driver for code review +** \main\maintrunk.MT5921\36 2008-08-05 01:53:28 GMT mtk01461 +** Add support for linux statistics +** \main\maintrunk.MT5921\35 2008-08-04 16:52:58 GMT mtk01461 +** Fix ASSERT if removing module in BG_SSID_SCAN state +** \main\maintrunk.MT5921\34 2008-06-13 22:52:24 GMT mtk01461 +** Revise status code handling in wlanHardStartXmit() for WLAN_STATUS_SUCCESS +** \main\maintrunk.MT5921\33 2008-05-30 18:56:53 GMT mtk01461 +** Not use wlanoidSetCurrentAddrForLinux() +** \main\maintrunk.MT5921\32 2008-05-30 14:39:40 GMT mtk01461 +** Remove WMM Assoc Flag +** \main\maintrunk.MT5921\31 2008-05-23 10:26:40 GMT mtk01084 +** modify wlanISR interface +** \main\maintrunk.MT5921\30 2008-05-03 18:52:36 GMT mtk01461 +** Fix Unset Broadcast filter when setMulticast +** \main\maintrunk.MT5921\29 2008-05-03 15:17:26 GMT mtk01461 +** Move Query Media Status to GLUE +** \main\maintrunk.MT5921\28 2008-04-24 22:48:21 GMT mtk01461 +** Revise set multicast function by using windows oid style for LP own back +** \main\maintrunk.MT5921\27 2008-04-24 12:00:08 GMT mtk01461 +** Fix multicast setting in Linux and add comment +** \main\maintrunk.MT5921\26 2008-03-28 10:40:22 GMT mtk01461 +** Fix set mac address func in Linux +** \main\maintrunk.MT5921\25 2008-03-26 15:37:26 GMT mtk01461 +** Add set MAC Address +** \main\maintrunk.MT5921\24 2008-03-26 14:24:53 GMT mtk01461 +** For Linux, set net_device has feature with checksum offload by default +** \main\maintrunk.MT5921\23 2008-03-11 14:50:52 GMT mtk01461 +** Fix typo +** \main\maintrunk.MT5921\22 2008-02-29 15:35:20 GMT mtk01088 +** add 1x decide code for sw port control +** \main\maintrunk.MT5921\21 2008-02-21 15:01:54 GMT mtk01461 +** Rearrange the set off place of GLUE spin lock in HardStartXmit +** \main\maintrunk.MT5921\20 2008-02-12 23:26:50 GMT mtk01461 +** Add debug option - Packet Order for Linux and add debug level - Event +** \main\maintrunk.MT5921\19 2007-12-11 00:11:12 GMT mtk01461 +** Fix SPIN_LOCK protection +** \main\maintrunk.MT5921\18 2007-11-30 17:02:25 GMT mtk01425 +** 1. Set Rx multicast packets mode before setting the address list +** \main\maintrunk.MT5921\17 2007-11-26 19:44:24 GMT mtk01461 +** Add OS_TIMESTAMP to packet +** \main\maintrunk.MT5921\16 2007-11-21 15:47:20 GMT mtk01088 +** fixed the unload module issue +** \main\maintrunk.MT5921\15 2007-11-07 18:37:38 GMT mtk01461 +** Fix compile warnning +** \main\maintrunk.MT5921\14 2007-11-02 01:03:19 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\13 2007-10-30 10:42:33 GMT mtk01425 +** 1. Refine for multicast list +** \main\maintrunk.MT5921\12 2007-10-25 18:08:13 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +** Revision 1.4 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:50 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_cfg80211.h" +#include "precomp.h" +#if CFG_SUPPORT_AGPS_ASSIST +#include "gl_kal.h" +#endif +#if defined(CONFIG_MTK_TC1_FEATURE) +#include +#endif +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define MAX_IOREQ_NUM 10 */ + +BOOLEAN fgIsUnderSuspend = false; + + +#if CFG_ENABLE_WIFI_DIRECT +spinlock_t g_p2p_lock; +int g_u4P2PEnding = 0; +int g_u4P2POnOffing = 0; +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Tasklet mechanism is like buttom-half in Linux. We just want to + * send a signal to OS for interrupt defer processing. All resources + * are NOT allowed reentry, so txPacket, ISR-DPC and ioctl must avoid preempty. + */ +typedef struct _WLANDEV_INFO_T { + struct net_device *prDev; +} WLANDEV_INFO_T, *P_WLANDEV_INFO_T; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#define CHAN2G(_channel, _freq, _flags) \ +{ \ + .band = NL80211_BAND_2GHZ, \ + .center_freq = (_freq), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel mtk_2ghz_channels[] = { + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + +#define CHAN5G(_channel, _flags) \ +{ \ + .band = NL80211_BAND_5GHZ, \ + .center_freq = 5000 + (5 * (_channel)), \ + .hw_value = (_channel), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +static struct ieee80211_channel mtk_5ghz_channels[] = { + CHAN5G(34, 0), CHAN5G(36, 0), + CHAN5G(38, 0), CHAN5G(40, 0), + CHAN5G(42, 0), CHAN5G(44, 0), + CHAN5G(46, 0), CHAN5G(48, 0), + CHAN5G(52, 0), CHAN5G(56, 0), + CHAN5G(60, 0), CHAN5G(64, 0), + CHAN5G(100, 0), CHAN5G(104, 0), + CHAN5G(108, 0), CHAN5G(112, 0), + CHAN5G(116, 0), CHAN5G(120, 0), + CHAN5G(124, 0), CHAN5G(128, 0), + CHAN5G(132, 0), CHAN5G(136, 0), + CHAN5G(140, 0), CHAN5G(149, 0), + CHAN5G(153, 0), CHAN5G(157, 0), + CHAN5G(161, 0), CHAN5G(165, 0), + CHAN5G(169, 0), CHAN5G(173, 0), + CHAN5G(184, 0), CHAN5G(188, 0), + CHAN5G(192, 0), CHAN5G(196, 0), + CHAN5G(200, 0), CHAN5G(204, 0), + CHAN5G(208, 0), CHAN5G(212, 0), + CHAN5G(216, 0), +}; + +#define RATETAB_ENT(_rate, _rateid, _flags) \ +{ \ + .bitrate = (_rate), \ + .hw_value = (_rateid), \ + .flags = (_flags), \ +} + +/* for cfg80211 - rate table */ +static struct ieee80211_rate mtk_rates[] = { + RATETAB_ENT(10, 0x1000, 0), + RATETAB_ENT(20, 0x1001, 0), + RATETAB_ENT(55, 0x1002, 0), + RATETAB_ENT(110, 0x1003, 0), /* 802.11b */ + RATETAB_ENT(60, 0x2000, 0), + RATETAB_ENT(90, 0x2001, 0), + RATETAB_ENT(120, 0x2002, 0), + RATETAB_ENT(180, 0x2003, 0), + RATETAB_ENT(240, 0x2004, 0), + RATETAB_ENT(360, 0x2005, 0), + RATETAB_ENT(480, 0x2006, 0), + RATETAB_ENT(540, 0x2007, 0), /* 802.11a/g */ +}; + +#define mtk_a_rates (mtk_rates + 4) +#define mtk_a_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 4) +#define mtk_g_rates (mtk_rates + 0) +#define mtk_g_rates_size (sizeof(mtk_rates) / sizeof(mtk_rates[0]) - 0) + +#define WLAN_MCS_INFO \ +{ \ + .rx_mask = {0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0},\ + .rx_highest = 0, \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ +} + +#define WLAN_HT_CAP \ +{ \ + .ht_supported = true, \ + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 \ + | IEEE80211_HT_CAP_SM_PS \ + | IEEE80211_HT_CAP_GRN_FLD \ + | IEEE80211_HT_CAP_SGI_20 \ + | IEEE80211_HT_CAP_SGI_40, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE, \ + .mcs = WLAN_MCS_INFO, \ +} + +/********************************************************** +* Public for both legacy Wi-Fi and P2P to access +**********************************************************/ +struct ieee80211_supported_band mtk_band_2ghz = { + .band = NL80211_BAND_2GHZ, + .channels = mtk_2ghz_channels, + .n_channels = ARRAY_SIZE(mtk_2ghz_channels), + .bitrates = mtk_g_rates, + .n_bitrates = mtk_g_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +struct ieee80211_supported_band mtk_band_5ghz = { + .band = NL80211_BAND_5GHZ, + .channels = mtk_5ghz_channels, + .n_channels = ARRAY_SIZE(mtk_5ghz_channels), + .bitrates = mtk_a_rates, + .n_bitrates = mtk_a_rates_size, + .ht_cap = WLAN_HT_CAP, +}; + +const UINT_32 mtk_cipher_suites[5] = { + /* keep WEP first, it may be removed below */ + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, + + /* keep last -- depends on hw flags! */ + WLAN_CIPHER_SUITE_AES_CMAC +}; + +/*********************************************************/ + +#define NIC_INF_NAME "wlan%d" /* interface name */ +#if CFG_TC1_FEATURE +#define NIC_INF_NAME_IN_AP_MODE "legacy%d" +#endif + +/* support to change debug module info dynamically */ +UINT_8 aucDebugModule[DBG_MODULE_NUM]; +UINT_32 u4DebugModule = 0; + +/* 4 2007/06/26, mikewu, now we don't use this, we just fix the number of wlan device to 1 */ +static WLANDEV_INFO_T arWlanDevInfo[CFG_MAX_WLAN_DEVICES] = { {0} }; + +static UINT_32 u4WlanDevNum; /* How many NICs coexist now */ + +/**20150205 added work queue for sched_scan to avoid cfg80211 stop schedule scan dead loack**/ +struct delayed_work sched_workq; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +#if CFG_ENABLE_WIFI_DIRECT +static SUB_MODULE_HANDLER rSubModHandler[SUB_MODULE_NUM] = { {NULL} }; +#endif + +static struct cfg80211_ops mtk_wlan_ops = { + .suspend = mtk_cfg80211_suspend, + .resume = mtk_cfg80211_resume, + .change_virtual_intf = mtk_cfg80211_change_iface, + .add_key = mtk_cfg80211_add_key, + .get_key = mtk_cfg80211_get_key, + .del_key = mtk_cfg80211_del_key, + .set_default_key = mtk_cfg80211_set_default_key, + .set_default_mgmt_key = mtk_cfg80211_set_default_mgmt_key, + .get_station = mtk_cfg80211_get_station, + .change_station = mtk_cfg80211_change_station, + .add_station = mtk_cfg80211_add_station, + .del_station = mtk_cfg80211_del_station, + .scan = mtk_cfg80211_scan, + .connect = mtk_cfg80211_connect, + .disconnect = mtk_cfg80211_disconnect, + .join_ibss = mtk_cfg80211_join_ibss, + .leave_ibss = mtk_cfg80211_leave_ibss, + .set_power_mgmt = mtk_cfg80211_set_power_mgmt, + .set_pmksa = mtk_cfg80211_set_pmksa, + .del_pmksa = mtk_cfg80211_del_pmksa, + .flush_pmksa = mtk_cfg80211_flush_pmksa, + .assoc = mtk_cfg80211_assoc, + /* Action Frame TX/RX */ + .remain_on_channel = mtk_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_cfg80211_mgmt_tx, +/* .mgmt_tx_cancel_wait = mtk_cfg80211_mgmt_tx_cancel_wait, */ + .mgmt_frame_register = mtk_cfg80211_mgmt_frame_register, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_cfg80211_testmode_cmd, +#endif +#if (CFG_SUPPORT_TDLS == 1) + .tdls_mgmt = TdlsexCfg80211TdlsMgmt, + .tdls_oper = TdlsexCfg80211TdlsOper, +#endif /* CFG_SUPPORT_TDLS */ +#if 1 /* Remove schedule_scan because we need more verification for NLO */ + .sched_scan_start = mtk_cfg80211_sched_scan_start, + .sched_scan_stop = mtk_cfg80211_sched_scan_stop, +#endif +}; + +static const struct wiphy_vendor_command mtk_wlan_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, + /* GSCAN */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_gscan_capabilities + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV, + .doit = mtk_cfg80211_vendor_set_scan_config + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_scan + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_enable_full_scan_results + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_scan_results + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_significant_change + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_SUBCMD_SET_HOTLIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_hotlist + }, + /* RTT */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_SUBCMD_GETCAPABILITY + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_rtt_capabilities + }, + /* Link Layer Statistics */ + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = LSTATS_SUBCMD_GET_INFO + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_llstats_get_info + }, + +}; + +static const struct nl80211_vendor_cmd_info mtk_wlan_vendor_events[] = { + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_FOUND + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_SCAN_RESULTS_AVAILABLE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_FULL_SCAN_RESULTS + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = RTT_EVENT_COMPLETE + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_COMPLETE_SCAN + }, + { + .vendor_id = GOOGLE_OUI, + .subcmd = GSCAN_EVENT_HOTLIST_RESULTS_LOST + }, +}; + +/* There isn't a lot of sense in it, but you can transmit anything you like */ +static const struct ieee80211_txrx_stypes + mtk_cfg80211_ais_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support mtk_wlan_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Override the implementation of select queue +* +* \param[in] dev Pointer to struct net_device +* \param[in] skb Pointer to struct skb_buff +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +unsigned int _cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp = 0; + + /* skb->priority values from 256->263 are magic values + * directly indicate a specific 802.1d priority. This is + * to allow 802.1d priority to be passed directly in from + * tags + */ + + if (skb->priority >= 256 && skb->priority <= 263) + return skb->priority - 256; + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + } + return dscp >> 5; +} + +static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +static UINT_16 wlanSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + skb->priority = _cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Load NVRAM data and translate it into REG_INFO_T +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* \param[out] prRegInfo Pointer to struct REG_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void glLoadNvram(IN P_GLUE_INFO_T prGlueInfo, OUT P_REG_INFO_T prRegInfo) +{ + UINT_32 i, j; + UINT_8 aucTmp[2]; + PUINT_8 pucDest; + + ASSERT(prGlueInfo); + ASSERT(prRegInfo); + + if ((!prGlueInfo) || (!prRegInfo)) + return; + + if (kalCfgDataRead16(prGlueInfo, sizeof(WIFI_CFG_PARAM_STRUCT) - sizeof(UINT_16), (PUINT_16) aucTmp) == TRUE) { + prGlueInfo->fgNvramAvailable = TRUE; + + /* load MAC Address */ +#if !defined(CONFIG_MTK_TC1_FEATURE) + for (i = 0; i < PARAM_MAC_ADDR_LEN; i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8) prRegInfo->aucMacAddr) + i)); + } +#else + TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prRegInfo->aucMacAddr); +#endif + + /* load country code */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucCountryCode[0]), (PUINT_16) aucTmp); + + /* cast to wide characters */ + prRegInfo->au2CountryCode[0] = (UINT_16) aucTmp[0]; + prRegInfo->au2CountryCode[1] = (UINT_16) aucTmp[1]; + + /* load default normal TX power */ + for (i = 0; i < sizeof(TX_PWR_PARAM_T); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rTxPwr) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->rTxPwr)) + i)); + } + + /* load feature flags */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucTxPwrValid), (PUINT_16) aucTmp); + prRegInfo->ucTxPwrValid = aucTmp[0]; + prRegInfo->ucSupport5GBand = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2G4BwFixed20M), (PUINT_16) aucTmp); + prRegInfo->uc2G4BwFixed20M = aucTmp[0]; + prRegInfo->uc5GBwFixed20M = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucEnable5GBand), (PUINT_16) aucTmp); + prRegInfo->ucEnable5GBand = aucTmp[0]; + + /* load EFUSE overriding part */ + for (i = 0; i < sizeof(prRegInfo->aucEFUSE); i += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucEFUSE) + i, + (PUINT_16) (((PUINT_8) &(prRegInfo->aucEFUSE)) + i)); + } + + /* load band edge tx power control */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fg2G4BandEdgePwrUsed), (PUINT_16) aucTmp); + prRegInfo->fg2G4BandEdgePwrUsed = (BOOLEAN) aucTmp[0]; + if (aucTmp[0]) { + prRegInfo->cBandEdgeMaxPwrCCK = (INT_8) aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, cBandEdgeMaxPwrOFDM20), (PUINT_16) aucTmp); + prRegInfo->cBandEdgeMaxPwrOFDM20 = (INT_8) aucTmp[0]; + prRegInfo->cBandEdgeMaxPwrOFDM40 = (INT_8) aucTmp[1]; + } + + /* load regulation subbands */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, ucRegChannelListMap), (PUINT_16) aucTmp); + prRegInfo->eRegChannelListMap = (ENUM_REG_CH_MAP_T) aucTmp[0]; + prRegInfo->ucRegChannelListIndex = aucTmp[1]; + + if (prRegInfo->eRegChannelListMap == REG_CH_MAP_CUSTOMIZED) { + for (i = 0; i < MAX_SUBBAND_NUM; i++) { + pucDest = (PUINT_8) &prRegInfo->rDomainInfo.rSubBand[i]; + for (j = 0; j < 6; j += sizeof(UINT_16)) { + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucRegSubbandInfo) + + (i * 6 + j), (PUINT_16) aucTmp); + + *pucDest++ = aucTmp[0]; + *pucDest++ = aucTmp[1]; + } + } + } + /* load RSSI compensation */ + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, uc2GRssiCompensation), (PUINT_16) aucTmp); + prRegInfo->uc2GRssiCompensation = aucTmp[0]; + prRegInfo->uc5GRssiCompensation = aucTmp[1]; + + kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, fgRssiCompensationValidbit), (PUINT_16) aucTmp); + prRegInfo->fgRssiCompensationValidbit = aucTmp[0]; + prRegInfo->ucRxAntennanumber = aucTmp[1]; + } else { + prGlueInfo->fgNvramAvailable = FALSE; + } + +} + +#if CFG_ENABLE_WIFI_DIRECT +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module init function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo) +{ + /*now, we only have p2p module */ + if (rSubModHandler[P2P_MODULE].fgIsInited == FALSE) { + rSubModHandler[P2P_MODULE].subModInit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = TRUE; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief called by txthread, run sub module exit function +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo) +{ + /*now, we only have p2p module */ + if (rSubModHandler[P2P_MODULE].fgIsInited == TRUE) { + rSubModHandler[P2P_MODULE].subModExit(prGlueInfo); + rSubModHandler[P2P_MODULE].fgIsInited = FALSE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module init flag, force TxThread to run sub modle init +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo) +{ + /* 4 Mark HALT, notify main thread to finish current job */ + prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_INIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module INIT */ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + +#if 0 + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pNetRegister(prGlueInfo); +#endif + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set sub module exit flag, force TxThread to run sub modle exit +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo) +{ +#if 0 + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + p2pNetUnregister(prGlueInfo); +#endif + + /* 4 Mark HALT, notify main thread to finish current job */ + prGlueInfo->ulFlag |= GLUE_FLAG_SUB_MOD_EXIT; + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread finish sub module EXIT */ + wait_for_completion_interruptible(&prGlueInfo->rSubModComp); + + return TRUE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set by sub module, indicate sub module is already inserted +* +* \param[in] rSubModInit, function pointer point to sub module init function +* \param[in] rSubModExit, function pointer point to sub module exit function +* \param[in] eSubModIdx, sub module index +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx) +{ + rSubModHandler[eSubModIdx].subModInit = rSubModInit; + rSubModHandler[eSubModIdx].subModExit = rSubModExit; + rSubModHandler[eSubModIdx].fgIsInited = FALSE; +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief check wlan is launched or not +* +* \param[in] (none) +* +* \return TRUE, wlan is already started +* FALSE, wlan is not started yet +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wlanIsLaunched(VOID) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (0 == u4WlanDevNum) + return FALSE; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + + ASSERT(prDev); + if (NULL == prDev) + return FALSE; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (NULL == prGlueInfo) + return FALSE; + + return prGlueInfo->prAdapter->fgIsWlanLaunched; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Export wlan GLUE_INFO_T pointer to p2p module +* +* \param[in] prGlueInfo Pointer to struct GLUE_INFO_T +* +* \return TRUE: get GlueInfo pointer successfully +* FALSE: wlan is not started yet +*/ +/*---------------------------------------------------------------------------*/ +BOOLEAN wlanExportGlueInfo(P_GLUE_INFO_T *prGlueInfoExpAddr) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (0 == u4WlanDevNum) + return FALSE; + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + if (NULL == prDev) + return FALSE; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (NULL == prGlueInfo) + return FALSE; + + if (FALSE == prGlueInfo->prAdapter->fgIsWlanLaunched) + return FALSE; + + *prGlueInfoExpAddr = prGlueInfo; + return TRUE; +} + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release prDev from wlandev_array and free tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanClearDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == prDev) { + arWlanDevInfo[i].prDev = NULL; + u4WlanDevNum--; + } + } + +} /* end of wlanClearDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate an unique interface index, net_device::ifindex member for this +* wlan device. Store the net_device in wlandev_array, and initialize +* tasklet object related to it. +* +* \param[in] prDev Pointer to struct net_device +* +* \retval >= 0 The device number. +* \retval -1 Fail to get index. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanGetDevIdx(struct net_device *prDev) +{ + int i; + + ASSERT(prDev); + + for (i = 0; i < CFG_MAX_WLAN_DEVICES; i++) { + if (arWlanDevInfo[i].prDev == (struct net_device *)NULL) { + /* Reserve 2 bytes space to store one digit of + * device number and NULL terminator. + */ + arWlanDevInfo[i].prDev = prDev; + u4WlanDevNum++; + return i; + } + } + + return -1; +} /* end of wlanGetDevIdx() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, a primary SOCKET interface to configure +* the interface lively. Handle an ioctl call on one of our devices. +* Everything Linux ioctl specific is done here. Then we pass the contents +* of the ifr->data to the request message handler. +* +* \param[in] prDev Linux kernel netdevice +* +* \param[in] prIfReq Our private ioctl request structure, typed for the generic +* struct ifreq so we can use ptr to function +* +* \param[in] cmd Command ID +* +* \retval 0 The IOCTL command is executed successfully. +* \retval <0 The execution of IOCTL command is failed. +*/ +/*----------------------------------------------------------------------------*/ +int wlanDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + + /* Verify input parameters for the following functions */ + ASSERT(prDev && prIfReq); + if (!prDev || !prIfReq) { + DBGLOG(INIT, ERROR, "Invalid input data\n"); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(INIT, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + if ((i4Cmd >= SIOCIWFIRST) && (i4Cmd < SIOCIWFIRSTPRIV)) { + /* 0x8B00 ~ 0x8BDF, wireless extension region */ + ret = wext_support_ioctl(prDev, prIfReq, i4Cmd); + } else if ((i4Cmd >= SIOCIWFIRSTPRIV) && (i4Cmd < SIOCIWLASTPRIV)) { + /* 0x8BE0 ~ 0x8BFF, private ioctl region */ + ret = priv_support_ioctl(prDev, prIfReq, i4Cmd); + } else if (i4Cmd == SIOCDEVPRIVATE + 1) { + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + } else { + DBGLOG(INIT, WARN, "Unexpected ioctl command: 0x%04x\n", i4Cmd); + ret = -EOPNOTSUPP; + } + + return ret; +} /* end of wlanDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is to set multicast list and set rx mode. +* +* \param[in] prDev Pointer to struct net_device +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +static struct delayed_work workq; +static struct net_device *gPrDev; +static BOOLEAN fgIsWorkMcStart = FALSE; +static BOOLEAN fgIsWorkMcEverInit = FALSE; +static struct wireless_dev *gprWdev; + +static void createWirelessDevice(void) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; +#if CFG_SUPPORT_PERSIST_NETDEV + struct net_device *prNetDev = NULL; +#endif + + /* <1.1> Create wireless_dev */ + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return; + } + + + /* <1.2> Create wiphy */ + prWiphy = wiphy_new(&mtk_wlan_ops, sizeof(GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(INIT, ERROR, "Allocating memory to wiphy device failed\n"); + goto free_wdev; + } + + /* <1.3> configure wireless_dev & wiphy */ + prWdev->iftype = NL80211_IFTYPE_STATION; + prWiphy->max_scan_ssids = 1; /* FIXME: for combo scan */ + prWiphy->max_scan_ie_len = 512; + + prWiphy->max_sched_scan_ssids = CFG_SCAN_SSID_MAX_NUM; + prWiphy->max_match_sets = CFG_SCAN_SSID_MATCH_MAX_NUM; + prWiphy->max_sched_scan_ie_len = CFG_CFG80211_IE_BUF_LEN; + prWiphy->max_sched_scan_reqs = 1; + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + prWiphy->bands[NL80211_BAND_2GHZ] = &mtk_band_2ghz; + /* always assign 5Ghz bands here, if the chip is not support 5Ghz, + bands[IEEE80211_BAND_5GHZ] will be assign to NULL */ + prWiphy->bands[NL80211_BAND_5GHZ] = &mtk_band_5ghz; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_SUPPORTS_FW_ROAM + | WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; +#if CFG_SUPPORT_TDLS + TDLSEX_WIPHY_FLAGS_INIT(prWiphy->flags); +#endif /* CFG_SUPPORT_TDLS */ + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->mgmt_stypes = mtk_cfg80211_ais_default_mgmt_stypes; + prWiphy->vendor_commands = mtk_wlan_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_wlan_vendor_ops) / sizeof(struct wiphy_vendor_command); + prWiphy->vendor_events = mtk_wlan_vendor_events; + prWiphy->n_vendor_events = ARRAY_SIZE(mtk_wlan_vendor_events); + + /* <1.4> wowlan support */ +#ifdef CONFIG_PM + prWiphy->wowlan = &mtk_wlan_wowlan_support; +#endif +#ifdef CONFIG_CFG80211_WEXT + /* <1.5> Use wireless extension to replace IOCTL */ + prWiphy->wext = &wext_handler_def; +#endif + + if (wiphy_register(prWiphy) < 0) { + DBGLOG(INIT, ERROR, "wiphy_register error\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; + +#if CFG_SUPPORT_PERSIST_NETDEV + /* <2> allocate and register net_device */ +#if CFG_TC1_FEATURE + if (wlan_if_changed) + prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME_IN_AP_MODE, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + else +#else + prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prNetDev) { + DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); + goto unregister_wiphy; + } + + *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = (P_GLUE_INFO_T) wiphy_priv(prWiphy); + + prNetDev->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prNetDev->wireless_handlers = &wext_handler_def; +#endif + netif_carrier_off(prNetDev); + netif_tx_stop_all_queues(prNetDev); + + /* <2.1> co-relate with wireless_dev bi-directionally */ + prNetDev->ieee80211_ptr = prWdev; + prWdev->netdev = prNetDev; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prNetDev->features = NETIF_F_HW_CSUM; +#endif + + /* <2.2> co-relate net device & device tree */ + SET_NETDEV_DEV(prNetDev, wiphy_dev(prWiphy)); + + /* <2.3> register net_device */ + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "wlanNetRegister: net_device context is not registered.\n"); + goto unregister_wiphy; + } +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + gprWdev = prWdev; + DBGLOG(INIT, INFO, "create wireless device success\n"); + return; + +#if CFG_SUPPORT_PERSIST_NETDEV +unregister_wiphy: + wiphy_unregister(prWiphy); +#endif +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +} + +static void destroyWirelessDevice(void) +{ +#if CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(gprWdev->netdev); + free_netdev(gprWdev->netdev); +#endif + wiphy_unregister(gprWdev->wiphy); + wiphy_free(gprWdev->wiphy); + kfree(gprWdev); + gprWdev = NULL; +} + +static void wlanSetMulticastList(struct net_device *prDev) +{ + gPrDev = prDev; + schedule_delayed_work(&workq, 0); +} + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this */ + +static void wlanSetMulticastListWorkQueue(struct work_struct *work) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4PacketFilter = 0; + UINT_32 u4SetInfoLen; + struct net_device *prDev = gPrDev; + + fgIsWorkMcStart = TRUE; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + if (kalIsHalted()) { + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + return; + } + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(INIT, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + return; + } + + if (prDev->flags & IFF_PROMISC) + u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { + + u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } else { + u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + kalHaltUnlock(); + + if (kalIoctl(prGlueInfo, + wlanoidSetCurrentPacketFilter, + &u4PacketFilter, + sizeof(u4PacketFilter), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen) != WLAN_STATUS_SUCCESS) { + fgIsWorkMcStart = FALSE; + DBGLOG(INIT, ERROR, "wlanSetMulticastListWorkQueue kalIoctl u4PacketFilter=%d\n", u4PacketFilter); + return; + } + + if (u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + PUINT_8 prMCAddrList = NULL; + UINT_32 i = 0; + + if (kalHaltLock(KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE)) + return; + if (kalIsHalted()) { + fgIsWorkMcStart = FALSE; + kalHaltUnlock(); + /*DBGLOG(INIT, WARN, "wlanSetMulticastListWorkQueue g_u4HaltFlag=%d\n", g_u4HaltFlag);*/ + return; + } + + prMCAddrList = kalMemAlloc(MAX_NUM_GROUP_ADDR * ETH_ALEN, VIR_MEM_TYPE); + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + memcpy((prMCAddrList + i * ETH_ALEN), ha->addr, ETH_ALEN); + i++; + } + } + + kalHaltUnlock(); + + kalIoctl(prGlueInfo, + wlanoidSetMulticastList, + prMCAddrList, (i * ETH_ALEN), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + kalMemFree(prMCAddrList, VIR_MEM_TYPE, MAX_NUM_GROUP_ADDR * ETH_ALEN); + } + + fgIsWorkMcStart = FALSE; + +} /* end of wlanSetMulticastList() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID wlanSchedScanStoppedWorkQueue(struct work_struct *work) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct net_device *prDev = gPrDev; + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + if (!prGlueInfo) { + DBGLOG(SCN, ERROR, "prGlueInfo == NULL unexpected\n"); + return; + } + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue due to sched_scan_mtx dead lock issue */ + cfg80211_sched_scan_stopped(priv_to_wiphy(prGlueInfo),0); + DBGLOG(SCN, INFO, + "cfg80211_sched_scan_stopped event send done\n"); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is TX entry point of NET DEVICE. +* +* \param[in] prSkb Pointer of the sk_buff to be sent +* \param[in] prDev Pointer to struct net_device +* +* \retval NETDEV_TX_OK - on success. +* \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. +*/ +/*----------------------------------------------------------------------------*/ +int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + UINT_16 u2QueueIdx = 0; +#if (CFG_SUPPORT_TDLS_DBG == 1) + UINT16 u2Identifier = 0; +#endif + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + ASSERT(prGlueInfo); + prGlueInfo->u8SkbToDriver++; + +#if (CFG_SUPPORT_TDLS_DBG == 1) + { + UINT8 *pkt = prSkb->data; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + /* u2TdlsTxSeq[u4TdlsTxSeqId ++] = u2Identifier; */ + DBGLOG(INIT, INFO, " %d\n", u2Identifier); + } + } +#endif + /* check if WiFi is halt */ + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "GLUE_FLAG_HALT skip tx\n"); + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } +#if CFG_SUPPORT_HOTSPOT_2_0 + if (prGlueInfo->fgIsDad) { + /* kalPrint("[Passpoint R2] Due to ipv4_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } + if (prGlueInfo->fgIs6Dad) { + /* kalPrint("[Passpoint R2] Due to ipv6_dad...TX is forbidden\n"); */ + dev_kfree_skb(prSkb); + prGlueInfo->u8SkbFreed++; + return NETDEV_TX_OK; + } +#endif + + STATS_TX_TIME_ARRIVE(prSkb); + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"); +#endif + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + /* non-1x packets */ + +#if CFG_DBG_GPIO_PINS + { + /* TX request from OS */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_LOW); + kalUdelay(1); + mtk_wcn_stp_debug_gpio_assert(IDX_TX_REQ, DBG_TIE_HIGH); + } +#endif + + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); +#endif + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + if (u2QueueIdx < CFG_MAX_TXQ_NUM) + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); +/* GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); */ +/* GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); */ + + if (u2QueueIdx < CFG_MAX_TXQ_NUM) { + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_stop_subqueue for wlan0, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_AIS_INDEX][u2QueueIdx]); + + netif_stop_subqueue(prDev, u2QueueIdx); + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + prGlueInfo->rHifInfo.HifLoopbkFlg |= 0x01; +#endif /* CONF_HIF_LOOPBACK_AUTO */ + } + } + } else { + /* printk("is security frame\n"); */ + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + DBGLOG(TX, EVENT, "\n+++++ pending frame %d len = %d +++++\n", prGlueInfo->i4TxPendingFrameNum, prSkb->len); + prGlueInfo->rNetDevStats.tx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.tx_packets++; + kalPerMonStart(prGlueInfo); + + /* set GLUE_FLAG_TXREQ_BIT */ + + /* pr->u4Flag |= GLUE_FLAG_TXREQ; */ + /* wake_up_interruptible(&prGlueInfo->waitq); */ + kalSetEvent(prGlueInfo); + + /* For Linux, we'll always return OK FLAG, because we'll free this skb by ourself */ + return NETDEV_TX_OK; +} /* end of wlanHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] prDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +*/ +/*----------------------------------------------------------------------------*/ +struct net_device_stats *wlanGetStats(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + +#if 0 + WLAN_STATUS rStatus; + UINT_32 u4XmitError = 0; + UINT_32 u4XmitOk = 0; + UINT_32 u4RecvError = 0; + UINT_32 u4RecvOk = 0; + UINT_32 u4BufLen; + + ASSERT(prDev); + + /* @FIX ME: need a more clear way to do this */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryXmitError, &u4XmitError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryXmitOk, &u4XmitOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRcvOk, &u4RecvOk, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRcvError, &u4RecvError, sizeof(UINT_32), TRUE, TRUE, TRUE, &u4BufLen); + prGlueInfo->rNetDevStats.rx_packets = u4RecvOk; + prGlueInfo->rNetDevStats.tx_packets = u4XmitOk; + prGlueInfo->rNetDevStats.tx_errors = u4XmitError; + prGlueInfo->rNetDevStats.rx_errors = u4RecvError; + /* prGlueInfo->rNetDevStats.rx_bytes = rCustomNetDevStats.u4RxBytes; */ + /* prGlueInfo->rNetDevStats.tx_bytes = rCustomNetDevStats.u4TxBytes; */ + /* prGlueInfo->rNetDevStats.rx_errors = rCustomNetDevStats.u4RxErrors; */ + /* prGlueInfo->rNetDevStats.multicast = rCustomNetDevStats.u4Multicast; */ +#endif + /* prGlueInfo->rNetDevStats.rx_packets = 0; */ + /* prGlueInfo->rNetDevStats.tx_packets = 0; */ + prGlueInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->rNetDevStats.rx_errors = 0; + /* prGlueInfo->rNetDevStats.rx_bytes = 0; */ + /* prGlueInfo->rNetDevStats.tx_bytes = 0; */ + prGlueInfo->rNetDevStats.rx_errors = 0; + prGlueInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->rNetDevStats; + +} /* end of wlanGetStats() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanInit(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + if (fgIsWorkMcEverInit == FALSE) { + if (!prDev) + return -ENXIO; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + INIT_DELAYED_WORK(&workq, wlanSetMulticastListWorkQueue); + + /* 20150205 work queue for sched_scan */ + INIT_DELAYED_WORK(&sched_workq, wlanSchedScanStoppedWorkQueue); + + fgIsWorkMcEverInit = TRUE; + } + + return 0; /* success */ +} /* end of wlanInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void wlanUninit(struct net_device *prDev) +{ + +} /* end of wlanUninit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->open +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanOpen succeeds. +* \retval < 0 The execution of wlanOpen failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanOpen(struct net_device *prDev) +{ + ASSERT(prDev); + + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->stop +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanStop succeeds. +* \retval < 0 The execution of wlanStop failed. +*/ +/*----------------------------------------------------------------------------*/ +static int wlanStop(struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + + struct cfg80211_scan_info info = { + .aborted = true, + }; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest != NULL) { + prScanRequest = prGlueInfo->prScanRequest; + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prScanRequest) + cfg80211_scan_done(prScanRequest, &info); + netif_tx_stop_all_queues(prDev); + + return 0; /* success */ +} /* end of wlanStop() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief Update channel table for cfg80211 based on current country domain + * + * \param[in] prGlueInfo Pointer to glue info + * + * \return none + */ +/*----------------------------------------------------------------------------*/ +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 i, j; + UINT_8 ucNumOfChannel; + RF_CHANNEL_INFO_T aucChannelList[ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels)]; + + /* 1. Disable all channels */ + for (i = 0; i < ARRAY_SIZE(mtk_2ghz_channels); i++) { + mtk_2ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + for (i = 0; i < ARRAY_SIZE(mtk_5ghz_channels); i++) { + mtk_5ghz_channels[i].flags |= IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[i].orig_flags |= IEEE80211_CHAN_DISABLED; + } + + /* 2. Get current domain channel list */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, + BAND_NULL, FALSE, + ARRAY_SIZE(mtk_2ghz_channels) + ARRAY_SIZE(mtk_5ghz_channels), + &ucNumOfChannel, aucChannelList); + + /* 3. Enable specific channel based on domain channel list */ + for (i = 0; i < ucNumOfChannel; i++) { + switch (aucChannelList[i].eBand) { + case BAND_2G4: + for (j = 0; j < ARRAY_SIZE(mtk_2ghz_channels); j++) { + if (mtk_2ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_2ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_2ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + case BAND_5G: + for (j = 0; j < ARRAY_SIZE(mtk_5ghz_channels); j++) { + if (mtk_5ghz_channels[j].hw_value == aucChannelList[i].ucChannelNum) { + mtk_5ghz_channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + mtk_5ghz_channels[j].orig_flags &= ~IEEE80211_CHAN_DISABLED; + break; + } + } + break; + + default: + DBGLOG(INIT, WARN, "Unknown band %d\n", aucChannelList[i].eBand); + break; + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register the device to the kernel and return the index. +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanNetRegister succeeds. +* \retval < 0 The execution of wlanNetRegister failed. +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanNetRegister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + INT_32 i4DevIdx = -1; + + ASSERT(prWdev); + + do { + if (!prWdev) + break; + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + i4DevIdx = wlanGetDevIdx(prWdev->netdev); + if (i4DevIdx < 0) { + DBGLOG(INIT, ERROR, "wlanNetRegister: net_device number exceeds.\n"); + break; + } + +#if !CFG_SUPPORT_PERSIST_NETDEV + if (register_netdev(prWdev->netdev) < 0) { + DBGLOG(INIT, ERROR, "wlanNetRegister: net_device context is not registered.\n"); + + wiphy_unregister(prWdev->wiphy); + wlanClearDevIdx(prWdev->netdev); + i4DevIdx = -1; + } +#endif + if (i4DevIdx != -1) + prGlueInfo->fgIsRegistered = TRUE; + + } while (FALSE); + + return i4DevIdx; /* success */ +} /* end of wlanNetRegister() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister the device from the kernel +* +* \param[in] prWdev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetUnregister(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetUnregister: The device context is NULL\n"); + return; + } + DBGLOG(INIT, TRACE, "unregister net_dev(0x%p)\n", prWdev->netdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + wlanClearDevIdx(prWdev->netdev); +#if !CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(prWdev->netdev); +#endif + prGlueInfo->fgIsRegistered = FALSE; + + DBGLOG(INIT, INFO, "unregister wireless_dev(0x%p), ifindex=%d\n", prWdev, prWdev->netdev->ifindex); + +} /* end of wlanNetUnregister() */ + +static const struct net_device_ops wlan_netdev_ops = { + .ndo_open = wlanOpen, + .ndo_stop = wlanStop, + .ndo_set_rx_mode = wlanSetMulticastList, + .ndo_get_stats = wlanGetStats, + .ndo_do_ioctl = wlanDoIOCTL, + .ndo_start_xmit = wlanHardStartXmit, + .ndo_init = wlanInit, + .ndo_uninit = wlanUninit, + .ndo_select_queue = wlanSelectQueue, +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method for creating Linux NET4 struct net_device object and the +* private data(prGlueInfo and prAdapter). Setup the IO address to the HIF. +* Assign the function pointer to the net_device object +* +* \param[in] pvData Memory address for the device +* +* \retval Not null The wireless_dev object. +* \retval NULL Fail to create wireless_dev object +*/ +/*----------------------------------------------------------------------------*/ +static struct lock_class_key rSpinKey[SPIN_LOCK_NUM]; +static struct wireless_dev *wlanNetCreate(PVOID pvData) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct wireless_dev *prWdev = gprWdev; + UINT_32 i; + struct device *prDev; + + if (!prWdev) { + DBGLOG(INIT, ERROR, "Allocating memory to wireless_dev context failed\n"); + return NULL; + } + /* 4 <1> co-relate wiphy & prDev */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(*((MTK_WCN_HIF_SDIO_CLTCTX *) pvData), &prDev); +#else +/* prDev = &((struct sdio_func *) pvData)->dev; //samp */ + prDev = pvData; /* samp */ +#endif + if (!prDev) + DBGLOG(INIT, WARN, "unable to get struct dev for wlan\n"); + /* don't set prDev as parent of wiphy->dev, because we have done device_add + in driver init. if we set parent here, parent will be not able to know this child, + and may occurs a KE in device_shutdown, to free wiphy->dev, because his parent + has been freed. */ + /*set_wiphy_dev(prWdev->wiphy, prDev);*/ + +#if !CFG_SUPPORT_PERSIST_NETDEV + /* 4 <3> Initial Glue structure */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + kalMemZero(prGlueInfo, sizeof(GLUE_INFO_T)); + /* 4 <3.1> Create net device */ +#if CFG_TC1_FEATURE + if (wlan_if_changed) { + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME_IN_AP_MODE, + NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + } else { + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + } +#else + prGlueInfo->prDevHandler = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), NIC_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); +#endif + if (!prGlueInfo->prDevHandler) { + DBGLOG(INIT, ERROR, "Allocating memory to net_device context failed\n"); + return NULL; + } + DBGLOG(INIT, INFO, "net_device prDev(0x%p) allocated ifindex=%d\n", + prGlueInfo->prDevHandler, prGlueInfo->prDevHandler->ifindex); + + /* 4 <3.1.1> initialize net device varaiables */ + *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prDevHandler)) = prGlueInfo; + + prGlueInfo->prDevHandler->netdev_ops = &wlan_netdev_ops; +#ifdef CONFIG_WIRELESS_EXT + prGlueInfo->prDevHandler->wireless_handlers = &wext_handler_def; +#endif + netif_carrier_off(prGlueInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); + + /* 4 <3.1.2> co-relate with wiphy bi-directionally */ + prGlueInfo->prDevHandler->ieee80211_ptr = prWdev; +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prGlueInfo->prDevHandler->features = NETIF_F_HW_CSUM; +#endif + prWdev->netdev = prGlueInfo->prDevHandler; + + /* 4 <3.1.3> co-relate net device & prDev */ + /*SET_NETDEV_DEV(prGlueInfo->prDevHandler, wiphy_dev(prWdev->wiphy));*/ + SET_NETDEV_DEV(prGlueInfo->prDevHandler, prDev); +#else /* CFG_SUPPORT_PERSIST_NETDEV */ + prGlueInfo->prDevHandler = gprWdev->netdev; +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + + /* 4 <3.2> initiali glue variables */ + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + prGlueInfo->ePowerState = ParamDeviceStateD0; + prGlueInfo->fgIsMacAddrOverride = FALSE; + prGlueInfo->fgIsRegistered = FALSE; + prGlueInfo->prScanRequest = NULL; + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* Init DAD */ + prGlueInfo->fgIsDad = FALSE; + prGlueInfo->fgIs6Dad = FALSE; + kalMemZero(prGlueInfo->aucDADipv4, 4); + kalMemZero(prGlueInfo->aucDADipv6, 16); +#endif + + init_completion(&prGlueInfo->rScanComp); + init_completion(&prGlueInfo->rHaltComp); + init_completion(&prGlueInfo->rPendComp); +#if CFG_ENABLE_WIFI_DIRECT + init_completion(&prGlueInfo->rSubModComp); +#endif + + /* initialize timer for OID timeout checker */ + kalOsTimerInitialize(prGlueInfo, kalTimeoutHandler); + + for (i = 0; i < SPIN_LOCK_NUM; i++) { + spin_lock_init(&prGlueInfo->rSpinLock[i]); + lockdep_set_class(&prGlueInfo->rSpinLock[i], &rSpinKey[i]); + } + + /* initialize semaphore for ioctl */ + sema_init(&prGlueInfo->ioctl_sem, 1); + + glSetHifInfo(prGlueInfo, (ULONG) pvData); + + /* 4 <8> Init Queues */ + init_waitqueue_head(&prGlueInfo->waitq); + QUEUE_INITIALIZE(&prGlueInfo->rCmdQueue); + QUEUE_INITIALIZE(&prGlueInfo->rTxQueue); + + /* 4 <4> Create Adapter structure */ + prGlueInfo->prAdapter = (P_ADAPTER_T) wlanAdapterCreate(prGlueInfo); + + if (!prGlueInfo->prAdapter) { + DBGLOG(INIT, ERROR, "Allocating memory to adapter failed\n"); + return NULL; + } + KAL_WAKE_LOCK_INIT(prAdapter, &prGlueInfo->rAhbIsrWakeLock, "WLAN AHB ISR"); +#if CFG_SUPPORT_PERSIST_NETDEV + dev_open(prGlueInfo->prDevHandler); + netif_carrier_off(prGlueInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prDevHandler); +#endif + + return prWdev; +} /* end of wlanNetCreate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Destroying the struct net_device object and the private data. +* +* \param[in] prWdev Pointer to struct wireless_dev. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanNetDestroy(struct wireless_dev *prWdev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prWdev); + + if (!prWdev) { + DBGLOG(INIT, ERROR, "wlanNetDestroy: The device context is NULL\n"); + return; + } + + /* prGlueInfo is allocated with net_device */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + ASSERT(prGlueInfo); + + /* destroy kal OS timer */ + kalCancelTimer(prGlueInfo); + + glClearHifInfo(prGlueInfo); + + wlanAdapterDestroy(prGlueInfo->prAdapter); + prGlueInfo->prAdapter = NULL; + +#if CFG_SUPPORT_PERSIST_NETDEV + /* take the net_device to down state */ + dev_close(prGlueInfo->prDevHandler); +#else + /* Free net_device and private data prGlueInfo, which are allocated by alloc_netdev(). */ + free_netdev(prWdev->netdev); +#endif + +} /* end of wlanNetDestroy() */ + +#ifndef CONFIG_X86 +UINT_8 g_aucBufIpAddr[32] = { 0 }; +static void wlanNotifyFwSuspend(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgSuspend) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen; + + rStatus = kalIoctl(prGlueInfo, + wlanoidNotifyFwSuspend, + (PVOID)&fgSuspend, + sizeof(fgSuspend), + FALSE, + FALSE, + TRUE, + FALSE, + &u4SetInfoLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, INFO, "wlanNotifyFwSuspend fail\n"); +} + +void wlanHandleSystemSuspend(void) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + + /* <1> Sanity check and acquire the net_device */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "wlanEarlySuspend u4WlanDevNum==0 invalid!!\n"); + return; + } + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + + fgIsUnderSuspend = true; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + kalPerMonDisable(prGlueInfo); + + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + goto notify_suspend; + } + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +#ifdef CONFIG_IPV6 + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + goto notify_suspend; + } + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], + ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] + ); + + /* todo: traverse between list to find whole sets of IPv6 addresses */ + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) { + /* Do nothing */ + /* u4NumIPv6++; */ + } +#endif + + /* <7> set up the ARP filter */ + { + UINT_32 u4SetInfoLen = 0; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#ifdef CONFIG_IPV6 + prParamNetAddrList->u4AddressCount += u4NumIPv6; +#endif + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); + } +#ifdef CONFIG_IPV6 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(g_aucBufIpAddr)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + +notify_suspend: + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) + wlanNotifyFwSuspend(prGlueInfo, TRUE); +} + +void wlanHandleSystemResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ +#endif + EVENT_AIS_BSS_INFO_T rParam; + UINT_32 u4BufLen = 0; + + /* <1> Sanity check and acquire the net_device */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (u4WlanDevNum == 0) { + DBGLOG(INIT, ERROR, "wlanLateResume u4WlanDevNum==0 invalid!!\n"); + return; + } + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + /* ASSERT(prDev); */ + + fgIsUnderSuspend = false; + + if (!prDev) { + DBGLOG(INIT, INFO, "prDev == NULL!!!\n"); + return; + } + /* <3> acquire the prGlueInfo */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + kalPerMonEnable(prGlueInfo); + + /* + We will receive the event in rx, we will check if the status is the same in driver + and FW, if not the same, trigger disconnetion procedure. + */ + + kalMemZero(&rParam, sizeof(EVENT_AIS_BSS_INFO_T)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBSSInfo, + &rParam, sizeof(EVENT_AIS_BSS_INFO_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "Query BSSinfo fail 0x%x!!\n", rStatus); + } + + /* <2> get the IPv4 address */ + if (!(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + goto notify_resume; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + goto notify_resume; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(INIT, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], + ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15] + ); +#endif + /* <7> clear the ARP filter */ + { + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + +notify_resume: + DBGLOG(INIT, INFO, "Query BSS result: %d %d %d, IP: %d.%d.%d.%d, rStatus: %u\n", + rParam.eConnectionState, rParam.eCurrentOPMode, rParam.fgIsNetActive, + ip[0], ip[1], ip[2], ip[3], rStatus); + if (rStatus != WLAN_STATUS_SUCCESS) { + wlanNotifyFwSuspend(prGlueInfo, FALSE); + } +} +#endif /* ! CONFIG_X86 */ + +int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode) +{ +#if 0 + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + rWlanStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pMode, + (PVOID) &rSetP2P, + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(INIT, INFO, "ret = %d\n", rWlanStatus); + if (rSetP2P.u4Enable) + p2pNetRegister(prGlueInfo, TRUE); + + return 0; + +#else + + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(netdev)); + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgIsP2PEnding; + UINT_32 u4BufLen = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + DBGLOG(INIT, INFO, "%u %u\n", (UINT_32) p2pmode.u4Enable, (UINT_32) p2pmode.u4Mode); + + /* avoid remove & p2p off command simultaneously */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2PEnding = g_u4P2PEnding; + g_u4P2POnOffing = 1; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + if (fgIsP2PEnding == 1) { + /* skip the command if we are removing */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + return 0; + } + + rSetP2P.u4Enable = p2pmode.u4Enable; + rSetP2P.u4Mode = p2pmode.u4Mode; + +#if !CFG_SUPPORT_PERSIST_NETDEV + if ((!rSetP2P.u4Enable) && (fgIsResetting == FALSE)) + p2pNetUnregister(prGlueInfo, TRUE); +#endif + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + /* + Scenario: + 1. System enters suspend/resume but not yet enter wlanearlysuspend() + or wlanlateresume(); + + 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() + and get g_halt_sem then do glRegisterEarlySuspend() or + glUnregisterEarlySuspend(); + + But system suspend/resume procedure is not yet finished so we + suspend; + + 3. System switches back to do suspend/resume procedure and execute + kalIoctl(). But driver does not yet release g_halt_sem so system + suspend in wlanearlysuspend() or wlanlateresume(); + + ==> deadlock occurs. + */ + + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, (PVOID) &rSetP2P,/* pu4IntBuf[0]is used as input SubCmd */ + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); +#if !CFG_SUPPORT_PERSIST_NETDEV + /* Need to check fgIsP2PRegistered, in case of whole chip reset. + * in this case, kalIOCTL return success always, + * and prGlueInfo->prP2pInfo may be NULL */ + if ((rSetP2P.u4Enable) && (prGlueInfo->prAdapter->fgIsP2PRegistered) && (fgIsResetting == FALSE)) + p2pNetRegister(prGlueInfo, TRUE); +#endif + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + return 0; +#endif +} + +static void set_dbg_level_handler(unsigned char dbg_lvl[DBG_MODULE_NUM]) +{ + kalMemCopy(aucDebugModule, dbg_lvl, sizeof(aucDebugModule)); + kalPrint("[wlan] change debug level"); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Wlan probe function. This function probes and initializes the device. +* +* \param[in] pvData data passed by bus driver init function +* _HIF_EHPI: NULL +* _HIF_SDIO: sdio bus driver handle +* +* \retval 0 Success +* \retval negative value Failed +*/ +/*----------------------------------------------------------------------------*/ +static INT_32 wlanProbe(PVOID pvData) +{ + struct wireless_dev *prWdev = NULL; + enum probe_fail_reason { + BUS_INIT_FAIL, + NET_CREATE_FAIL, + BUS_SET_IRQ_FAIL, + ADAPTER_START_FAIL, + NET_REGISTER_FAIL, + PROC_INIT_FAIL, + FAIL_REASON_NUM + } eFailReason; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + INT_32 i4DevIdx = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + INT_32 i4Status = 0; + BOOLEAN bRet = FALSE; + + eFailReason = FAIL_REASON_NUM; + do { + /* 4 <1> Initialize the IO port of the interface */ + /* GeorgeKuo: pData has different meaning for _HIF_XXX: + * _HIF_EHPI: pointer to memory base variable, which will be + * initialized by glBusInit(). + * _HIF_SDIO: bus driver handle + */ + + bRet = glBusInit(pvData); + wlanDebugInit(); + /* Cannot get IO address from interface */ + if (FALSE == bRet) { + DBGLOG(INIT, ERROR, KERN_ALERT "wlanProbe: glBusInit() fail\n"); + i4Status = -EIO; + eFailReason = BUS_INIT_FAIL; + break; + } + /* 4 <2> Create network device, Adapter, KalInfo, prDevHandler(netdev) */ + prWdev = wlanNetCreate(pvData); + if (prWdev == NULL) { + DBGLOG(INIT, ERROR, "wlanProbe: No memory for dev and its private\n"); + i4Status = -ENOMEM; + eFailReason = NET_CREATE_FAIL; + break; + } + /* 4 <2.5> Set the ioaddr to HIF Info */ + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(prWdev->wiphy); + gPrDev = prGlueInfo->prDevHandler; + + /* 4 <4> Setup IRQ */ + prWlandevInfo = &arWlanDevInfo[i4DevIdx]; + + i4Status = glBusSetIrq(prWdev->netdev, NULL, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + + if (i4Status != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, ERROR, "wlanProbe: Set IRQ error\n"); + eFailReason = BUS_SET_IRQ_FAIL; + break; + } + + prGlueInfo->i4DevIdx = i4DevIdx; + + prAdapter = prGlueInfo->prAdapter; + + prGlueInfo->u4ReadyFlag = 0; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prAdapter->u4CSUMFlags = (CSUM_OFFLOAD_EN_TX_TCP | CSUM_OFFLOAD_EN_TX_UDP | CSUM_OFFLOAD_EN_TX_IP); +#endif +#if CFG_SUPPORT_CFG_FILE + { + PUINT_8 pucConfigBuf; + UINT_32 u4ConfigReadLen; + + wlanCfgInit(prAdapter, NULL, 0, 0); + pucConfigBuf = (PUINT_8) kalMemAlloc(WLAN_CFG_FILE_BUF_SIZE, VIR_MEM_TYPE); + u4ConfigReadLen = 0; + DBGLOG(INIT, LOUD, "CFG_FILE: Read File...\n"); + if (pucConfigBuf) { + kalMemZero(pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE); + if (kalReadToFile("/data/misc/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi.cfg\n"); + + } else if (kalReadToFile("/data/misc/wifi/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /data/misc/wifi/wifi.cfg\n"); + } else if (kalReadToFile("/etc/firmware/wifi.cfg", + pucConfigBuf, WLAN_CFG_FILE_BUF_SIZE, &u4ConfigReadLen) == 0) { + DBGLOG(INIT, LOUD, "CFG_FILE: Read /etc/firmware/wifi.cfg\n"); + } + + if (pucConfigBuf[0] != '\0' && u4ConfigReadLen > 0) + wlanCfgInit(prAdapter, pucConfigBuf, u4ConfigReadLen, 0); + kalMemFree(pucConfigBuf, VIR_MEM_TYPE, WLAN_CFG_FILE_BUF_SIZE); + } /* pucConfigBuf */ + } +#endif + /* 4 <5> Start Device */ + /* */ +#if CFG_ENABLE_FW_DOWNLOAD + DBGLOG(INIT, TRACE, "start to download firmware...\n"); + + /* before start adapter, we need to open and load firmware */ + { + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ + kalMemSet(prRegInfo, 0, sizeof(REG_INFO_T)); + prRegInfo->u4StartAddress = CFG_FW_START_ADDRESS; + prRegInfo->u4LoadAddress = CFG_FW_LOAD_ADDRESS; + + /* Load NVRAM content to REG_INFO_T */ + glLoadNvram(prGlueInfo, prRegInfo); +#if CFG_SUPPORT_CFG_FILE + wlanCfgApply(prAdapter); +#endif + + /* kalMemCopy(&prGlueInfo->rRegInfo, prRegInfo, sizeof(REG_INFO_T)); */ + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + prRegInfo->fgEnArpFilter = TRUE; + + if (kalFirmwareImageMapping(prGlueInfo, &prFwBuffer, &u4FwSize) == NULL) { + i4Status = -EIO; + DBGLOG(INIT, ERROR, "kalFirmwareImageMapping fail!\n"); + goto bailout; + } else { + + if (wlanAdapterStart(prAdapter, prRegInfo, prFwBuffer, + u4FwSize) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + } + } + + kalFirmwareImageUnmapping(prGlueInfo, NULL, prFwBuffer); + +bailout: + /* kfree(prRegInfo); */ + + DBGLOG(INIT, TRACE, "download firmware status = %d\n", i4Status); + + if (i4Status < 0) { + GL_HIF_INFO_T *HifInfo; + UINT_32 u4FwCnt; + + DBGLOG(INIT, WARN, "CONNSYS FW CPUINFO:\n"); + HifInfo = &prAdapter->prGlueInfo->rHifInfo; + for (u4FwCnt = 0; u4FwCnt < 16; u4FwCnt++) + DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(HifInfo, CONN_MCU_CPUPCR)); + /* CONSYS_REG_READ(CONSYS_CPUPCR_REG) */ + + /* dump HIF/DMA registers, if fgIsBusAccessFailed is FALSE, otherwise, */ + /* dump HIF register may be hung */ + if (!fgIsBusAccessFailed) + HifRegDump(prGlueInfo->prAdapter); +/* if (prGlueInfo->rHifInfo.DmaOps->DmaRegDump != NULL) */ +/* prGlueInfo->rHifInfo.DmaOps->DmaRegDump(&prGlueInfo->rHifInfo); */ + eFailReason = ADAPTER_START_FAIL; + break; + } + } +#else + /* P_REG_INFO_T prRegInfo = (P_REG_INFO_T) kmalloc(sizeof(REG_INFO_T), GFP_KERNEL); */ + kalMemSet(&prGlueInfo->rRegInfo, 0, sizeof(REG_INFO_T)); + P_REG_INFO_T prRegInfo = &prGlueInfo->rRegInfo; + + /* Load NVRAM content to REG_INFO_T */ + glLoadNvram(prGlueInfo, prRegInfo); + + prRegInfo->u4PowerMode = CFG_INIT_POWER_SAVE_PROF; + + if (wlanAdapterStart(prAdapter, prRegInfo, NULL, 0) != WLAN_STATUS_SUCCESS) { + i4Status = -EIO; + eFailReason = ADAPTER_START_FAIL; + break; + } +#endif + if (FALSE == prAdapter->fgEnable5GBand) + prWdev->wiphy->bands[NL80211_BAND_5GHZ] = NULL; + + prGlueInfo->main_thread = kthread_run(tx_thread, prGlueInfo->prDevHandler, "tx_thread"); + kalSetHalted(FALSE); +#if CFG_SUPPORT_ROAMING_ENC + /* adjust roaming threshold */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + CMD_ROAMING_INFO_T rRoamingInfo; + UINT_32 u4SetInfoLen = 0; + + prAdapter->fgIsRoamingEncEnabled = TRUE; + + /* suggestion from Tsaiyuan.Hsu */ + kalMemZero(&rRoamingInfo, sizeof(CMD_ROAMING_INFO_T)); + rRoamingInfo.fgIsFastRoamingApplied = TRUE; + + DBGLOG(INIT, TRACE, "Enable roaming enhance function\n"); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRoamingInfo, + &rRoamingInfo, sizeof(rRoamingInfo), TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, ERROR, "set roaming advance info fail 0x%x\n", rStatus); + } +#endif /* CFG_SUPPORT_ROAMING_ENC */ + +#if (CFG_SUPPORT_TXR_ENC == 1) + /* adjust tx rate switch threshold */ + rlmTxRateEnhanceConfig(prGlueInfo->prAdapter); +#endif /* CFG_SUPPORT_TXR_ENC */ + + /* set MAC address */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + struct sockaddr MacAddr; + UINT_32 u4SetInfoLen = 0; + + kalMemZero(MacAddr.sa_data, sizeof(MacAddr.sa_data)); + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryCurrentAddr, + &MacAddr.sa_data, + PARAM_MAC_ADDR_LEN, TRUE, TRUE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, WARN, "set MAC addr fail 0x%x\n", rStatus); + prGlueInfo->u4ReadyFlag = 0; + } else { + ether_addr_copy(prGlueInfo->prDevHandler->dev_addr, (const u8 *)&(MacAddr.sa_data)); + ether_addr_copy(prGlueInfo->prDevHandler->perm_addr, + prGlueInfo->prDevHandler->dev_addr); + + /* card is ready */ + prGlueInfo->u4ReadyFlag = 1; +#if CFG_SHOW_MACADDR_SOURCE + DBGLOG(INIT, INFO, "MAC address: %pM ", (&MacAddr.sa_data)); +#endif + } + } + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + /* set HW checksum offload */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + UINT_32 u4SetInfoLen = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID) &u4CSUMFlags, + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(INIT, WARN, "set HW checksum offload fail 0x%x\n", rStatus); + } +#endif + + /* 4 <3> Register the card */ + DBGLOG(INIT, TRACE, "wlanNetRegister...\n"); + i4DevIdx = wlanNetRegister(prWdev); + if (i4DevIdx < 0) { + i4Status = -ENXIO; + DBGLOG(INIT, ERROR, "wlanProbe: Cannot register the net_device context to the kernel\n"); + eFailReason = NET_REGISTER_FAIL; + break; + } + + wlanRegisterNotifier(); + /* 4 <6> Initialize /proc filesystem */ +#ifdef WLAN_INCLUDE_PROC + DBGLOG(INIT, TRACE, "init procfs...\n"); + i4Status = procCreateFsEntry(prGlueInfo); + if (i4Status < 0) { + DBGLOG(INIT, ERROR, "wlanProbe: init procfs failed\n"); + eFailReason = PROC_INIT_FAIL; + break; + } +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI + prGlueInfo->rBowInfo.fgIsNetRegistered = FALSE; + prGlueInfo->rBowInfo.fgIsRegistered = FALSE; + glRegisterAmpc(prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + DBGLOG(INIT, TRACE, "wlanSubModInit...\n"); + + /* wlan is launched */ + prGlueInfo->prAdapter->fgIsWlanLaunched = TRUE; + /* if p2p module is inserted, notify tx_thread to init p2p network */ + if (rSubModHandler[P2P_MODULE].subModInit) + wlanSubModInit(prGlueInfo); + /* register set_p2p_mode handler to mtk_wmt_wifi */ + register_set_p2p_mode_handler(set_p2p_mode_handler); +#endif +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK_INIT(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock, "WLAN AP"); +#endif + } while (FALSE); + + if (i4Status != WLAN_STATUS_SUCCESS) { + switch (eFailReason) { + case PROC_INIT_FAIL: + wlanNetUnregister(prWdev); + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); + wlanAdapterStop(prAdapter); + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); + wlanNetDestroy(prWdev); + break; + case NET_REGISTER_FAIL: + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prAdapter->rTxThreadWakeLock); + wlanAdapterStop(prAdapter); + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); + wlanNetDestroy(prWdev); + break; + case ADAPTER_START_FAIL: + glBusFreeIrq(prWdev->netdev, *((P_GLUE_INFO_T *) netdev_priv(prWdev->netdev))); + KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); + wlanNetDestroy(prWdev); + break; + case BUS_SET_IRQ_FAIL: + KAL_WAKE_LOCK_DESTROY(prAdapter, &prGlueInfo->rAhbIsrWakeLock); + wlanNetDestroy(prWdev); + break; + case NET_CREATE_FAIL: + break; + case BUS_INIT_FAIL: + break; + default: + break; + } + } +#if CFG_ENABLE_WIFI_DIRECT + { + GLUE_SPIN_LOCK_DECLARATION(); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2PEnding = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + } +#endif +#if CFG_SUPPORT_AGPS_ASSIST + if (i4Status == WLAN_STATUS_SUCCESS) + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_ON, NULL, 0); +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + { + int iMetInitRet = WLAN_STATUS_FAILURE; + + if (i4Status == WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, TRACE, "init MET procfs...\n"); + iMetInitRet = kalMetInitProcfs(prGlueInfo); + if (iMetInitRet < 0) + DBGLOG(INIT, ERROR, "wlanProbe: init MET procfs failed\n"); + } + } +#endif + if (i4Status == WLAN_STATUS_SUCCESS) { + /*Init performance monitor structure */ + kalPerMonInit(prGlueInfo); + /* probe ok */ + DBGLOG(INIT, TRACE, "wlanProbe ok\n"); + } else { + /* we don't care the return value of mtk_wcn_set_connsys_power_off_flag, + * because even this function returns + * error, we can also call core dump but only core dump failed. */ + if (g_IsNeedDoChipReset) + mtk_wcn_set_connsys_power_off_flag(0); + /* probe failed */ + DBGLOG(INIT, ERROR, "wlanProbe failed\n"); + } + + return i4Status; +} /* end of wlanProbe() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method to stop driver operation and release all resources. Following +* this call, no frame should go up or down through this interface. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static VOID wlanRemove(VOID) +{ +#define KAL_WLAN_REMOVE_TIMEOUT_MSEC 3000 + struct net_device *prDev = NULL; + P_WLANDEV_INFO_T prWlandevInfo = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + + DBGLOG(INIT, LOUD, "Remove wlan!\n"); + + /* 4 <0> Sanity check */ + ASSERT(u4WlanDevNum <= CFG_MAX_WLAN_DEVICES); + if (0 == u4WlanDevNum) { + DBGLOG(INIT, ERROR, "0 == u4WlanDevNum\n"); + return; + } + /* unregister set_p2p_mode handler to mtk_wmt_wifi */ + register_set_p2p_mode_handler(NULL); + + prDev = arWlanDevInfo[u4WlanDevNum - 1].prDev; + prWlandevInfo = &arWlanDevInfo[u4WlanDevNum - 1]; + + ASSERT(prDev); + if (NULL == prDev) { + DBGLOG(INIT, ERROR, "NULL == prDev\n"); + return; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (NULL == prGlueInfo) { + DBGLOG(INIT, ERROR, "NULL == prGlueInfo\n"); + free_netdev(prDev); + return; + } + + kalPerMonDestroy(prGlueInfo); +#if CFG_ENABLE_WIFI_DIRECT + /* avoid remove & p2p off command simultaneously */ + { + BOOLEAN fgIsP2POnOffing; + + GLUE_SPIN_LOCK_DECLARATION(); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2PEnding = 1; + fgIsP2POnOffing = g_u4P2POnOffing; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + DBGLOG(INIT, TRACE, "waiting for fgIsP2POnOffing...\n"); + + /* History: cannot use down() here, sometimes we cannot come back here */ + /* waiting for p2p off command finishes, we cannot skip the remove */ + while (1) { + if (fgIsP2POnOffing == 0) + break; + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2POnOffing = g_u4P2POnOffing; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + } + } +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsNetRegistered) { + bowNotifyAllLinkDisconnected(prGlueInfo->prAdapter); + /* wait 300ms for BoW module to send deauth */ + kalMsleep(300); + } +#endif + + /* 4 <1> Stopping handling interrupt and free IRQ */ + DBGLOG(INIT, TRACE, "free IRQ...\n"); + glBusFreeIrq(prDev, *((P_GLUE_INFO_T *) netdev_priv(prDev))); + + kalMemSet(&(prGlueInfo->prAdapter->rWlanInfo), 0, sizeof(WLAN_INFO_T)); + + kalSetHalted(TRUE); /* before flush_delayed_work() */ + if (fgIsWorkMcStart == TRUE) { + DBGLOG(INIT, TRACE, "flush_delayed_work...\n"); + flush_delayed_work(&workq); /* flush_delayed_work_sync is deprecated */ + } + + flush_delayed_work(&sched_workq); + + DBGLOG(INIT, INFO, "down g_halt_sem...\n"); + kalHaltLock(KAL_WLAN_REMOVE_TIMEOUT_MSEC); +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); +#endif + +/* flush_delayed_work_sync(&workq); */ +/* flush_delayed_work(&workq); */ /* flush_delayed_work_sync is deprecated */ + + /* 4 <2> Mark HALT, notify main thread to stop, and clean up queued requests */ +/* prGlueInfo->u4Flag |= GLUE_FLAG_HALT; */ + set_bit(GLUE_FLAG_HALT_BIT, &prGlueInfo->ulFlag); + DBGLOG(INIT, TRACE, "waiting for tx_thread stop...\n"); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + DBGLOG(INIT, TRACE, "wait_for_completion_interruptible\n"); + + /* wait main thread stops */ + wait_for_completion_interruptible(&prGlueInfo->rHaltComp); + + DBGLOG(INIT, TRACE, "mtk_sdiod stopped\n"); + + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rTxThreadWakeLock); + KAL_WAKE_LOCK_DESTROY(prGlueInfo->prAdapter, &prGlueInfo->rAhbIsrWakeLock); + + /* prGlueInfo->rHifInfo.main_thread = NULL; */ + prGlueInfo->main_thread = NULL; + +#if CFG_ENABLE_BT_OVER_WIFI + if (prGlueInfo->rBowInfo.fgIsRegistered) + glUnregisterAmpc(prGlueInfo); +#endif + + /* 4 <3> Remove /proc filesystem. */ +#ifdef WLAN_INCLUDE_PROC + procRemoveProcfs(); +#endif /* WLAN_INCLUDE_PROC */ + +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetRemoveProcfs(); +#endif + + /* Force to do DMA reset */ + DBGLOG(INIT, TRACE, "glResetHif\n"); + glResetHif(prGlueInfo); + + /* 4 <4> wlanAdapterStop */ + prAdapter = prGlueInfo->prAdapter; +#if CFG_SUPPORT_AGPS_ASSIST + kalIndicateAgpsNotify(prAdapter, AGPS_EVENT_WLAN_OFF, NULL, 0); +#endif + + wlanAdapterStop(prAdapter); + DBGLOG(INIT, TRACE, "Number of Stalled Packets = %d\n", prGlueInfo->i4TxPendingFrameNum); + +#if CFG_ENABLE_WIFI_DIRECT + prGlueInfo->prAdapter->fgIsWlanLaunched = FALSE; + if (prGlueInfo->prAdapter->fgIsP2PRegistered) { + DBGLOG(INIT, TRACE, "p2pNetUnregister...\n"); +#if !CFG_SUPPORT_PERSIST_NETDEV + p2pNetUnregister(prGlueInfo, FALSE); +#endif + DBGLOG(INIT, INFO, "p2pRemove...\n"); + p2pRemove(prGlueInfo); + } +#endif + + /* 4 <5> Release the Bus */ + glBusRelease(prDev); + + kalHaltUnlock(); + wlanDebugUninit(); + /* 4 <6> Unregister the card */ + wlanNetUnregister(prDev->ieee80211_ptr); + + /* 4 <7> Destroy the device */ + wlanNetDestroy(prDev->ieee80211_ptr); + prDev = NULL; + + DBGLOG(INIT, LOUD, "wlanUnregisterNotifier...\n"); + wlanUnregisterNotifier(); + + DBGLOG(INIT, INFO, "wlanRemove ok\n"); +} /* end of wlanRemove() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Entry Point */ +static int initWlan(void) +{ + int ret = 0, i; +#if DBG + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_MASK; /* enable all */ +#else + /* Initial debug level is D1 */ + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = DBG_CLASS_ERROR | DBG_CLASS_WARN | DBG_CLASS_INFO | DBG_CLASS_STATE; +#endif /* DBG */ + DBGLOG(INIT, INFO, "initWlan\n"); + + spin_lock_init(&g_p2p_lock); + + /* memory pre-allocation */ + kalInitIOBuffer(); + procInitFs(); + createWirelessDevice(); + if (gprWdev) + glP2pCreateWirelessDevice((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy)); + + ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO); + + if (ret == -EIO) { + kalUninitIOBuffer(); + return ret; + } +#if (CFG_CHIP_RESET_SUPPORT) + glResetInit(); +#endif + + /* register set_dbg_level handler to mtk_wmt_wifi */ + register_set_dbg_level_handler(set_dbg_level_handler); + + /* Set the initial DEBUG CLASS of each module */ + return ret; +} /* end of initWlan() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static VOID exitWlan(void) +{ + DBGLOG(INIT, INFO, "exitWlan\n"); + + /* unregister set_dbg_level handler to mtk_wmt_wifi */ + register_set_dbg_level_handler(NULL); + +#if CFG_CHIP_RESET_SUPPORT + glResetUninit(); +#endif + destroyWirelessDevice(); + glP2pDestroyWirelessDevice(); + + glUnregisterBus(wlanRemove); + + /* free pre-allocated memory */ + kalUninitIOBuffer(); + + DBGLOG(INIT, INFO, "exitWlan\n"); + procUninitProcFs(); + +} /* end of exitWlan() */ + +#ifdef MTK_WCN_BUILT_IN_DRIVER + +int mtk_wcn_wlan_gen2_init(void) +{ + return initWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen2_init); + +void mtk_wcn_wlan_gen2_exit(void) +{ + return exitWlan(); +} +EXPORT_SYMBOL(mtk_wcn_wlan_gen2_exit); + +#else + +module_init(initWlan); +module_exit(exitWlan); + +#endif + +MODULE_AUTHOR(NIC_AUTHOR); +MODULE_DESCRIPTION(NIC_DESC); +MODULE_SUPPORTED_DEVICE(NIC_NAME); +MODULE_LICENSE("GPL"); diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c new file mode 100644 index 0000000000000..3a257c9f85c4d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_kal.c @@ -0,0 +1,4799 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_kal.c#3 +*/ + +/*! \file gl_kal.c + \brief GLUE Layer will export the required procedures here for internal driver stack. + + This file contains all routines which are exported from GLUE Layer to internal + driver stack. +*/ + +/* +** Log: gl_kal.c +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 05 31 2012 terry.wu + * NULL + * . + * + * 03 26 2012 cp.wu + * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist + * invoke put_cred() after get_current_cred() calls. + * + * 03 07 2012 yuche.tsai + * NULL + * Fix compile error when WiFi Direct is off. + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 02 20 2012 cp.wu + * [WCXRP00001187] [MT6620 Wi-Fi][Driver][Android] Add error handling while firmware image doesn't exist + * do not need to invoke free() while firmware image file doesn't exist + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 21 2011 cp.wu + * [WCXRP00001118] [MT6620 Wi-Fi][Driver] Corner case protections to pass Monkey testing + * 1. wlanoidQueryBssIdList might be passed with a non-zero length but a NULL pointer of buffer + * add more checking for such cases + * + * 2. kalSendComplete() might be invoked with a packet belongs to P2P network right after P2P is unregistered. + * add some tweaking to protect such cases because that net device has become invalid. + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 16 2011 yuche.tsai + * NULL + * Avoid using work thread. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 23 2011 yuche.tsai + * [WCXRP00000998] [Volunteer Patch][WiFi Direct][FW] P2P Social Channel & country domain issue + * Regulation domain feature check in. + * + * 08 12 2011 cp.wu + * [WCXRP00000913] [MT6620 Wi-Fi] create repository of source code dedicated for MT6620 E6 ASIC + * load WIFI_RAM_CODE_E6 for MT6620 E6 ASIC. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 06 13 2011 eddie.chen + * [WCXRP00000779] [MT6620 Wi-Fi][DRV] Add tx rx statistics in linux and use netif_rx_ni + * Add tx rx statistics and netif_rx_ni. + * + * 04 15 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW short range mode. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated + * network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 08 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * correct i4TxPendingFrameNum decreasing. + * + * 03 23 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * apply multi-queue operation only for linux kernel > 2.6.26 + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability for compatible with linux 2.6.12. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * refix ... + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * correct compiling warning/error. + * + * 03 18 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * add more robust fault tolerance design when pre-allocation failed. (rarely happen) + * + * 03 17 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * use pre-allocated buffer for storing enhanced interrupt response as well + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similar APIs to hide the difference. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 14 2011 jeffrey.chang + * [WCXRP00000546] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] fix kernel build warning message + * fix kernel build warning message + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after + * connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 01 24 2011 cp.wu + * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving + * 1. add an extra counter for tracking pending forward frames. + * 2. notify TX service thread as well when there is pending forward frame + * 3. correct build errors leaded by introduction of Wi-Fi direct separation module + * + * 01 19 2011 cp.wu + * [WCXRP00000371] [MT6620 Wi-Fi][Driver] make linux glue layer portable for Android 2.3.1 with Linux 2.6.35.7 + * add compile option to check linux version 2.6.35 for different usage of system API to improve portability + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues + * due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field + * checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used + * to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 11 02 2010 jeffrey.chang + * [WCXRP00000145] [MT6620 Wi-Fi][Driver] fix issue of byte endian in packet classifier which discards BoW packets + * . + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 26 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000137] [MT6620 Wi-Fi] [FW] + * Support NIC capability query command + * 1) update NVRAM content template to ver 1.02 + * 2) add compile option for querying NIC capability (default: off) + * 3) modify AIS 5GHz support to run-time option, which could be turned on by registry or NVRAM setting + * 4) correct auto-rate compiler error under linux (treat warning as error) + * 5) simplify usage of NVRAM and REG_INFO_T + * 6) add version checking between driver and firmware + * + * 10 25 2010 jeffrey.chang + * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform + * Remove redundant code which cause mismatch of power control release + * + * 10 25 2010 jeffrey.chang + * [WCXRP00000129] [MT6620] [Driver] Kernel panic when rmmod module on Andriod platform + * Remove redundant GLUE_HALT condfition to avoid unmatched release of power control + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue + * refine the scan ioctl to prevent hanging of Android UI + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 06 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * if there is NVRAM, then use MAC address on NVRAM as default MAC address. + * + * 10 06 2010 cp.wu + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * code reorganization to improve isolation between GLUE and CORE layers. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + * associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 30 2010 cp.wu + * NULL + * API added: nicTxPendingPackets(), for simplifying porting layer + * + * 08 20 2010 yuche.tsai + * NULL + * Support second interface indicate when enabling P2P. + * + * 08 18 2010 yarco.yang + * NULL + * 1. Fixed HW checksum offload function not work under Linux issue. + * 2. Add debug message. + * + * 08 16 2010 jeffrey.chang + * NULL + * remove redundant code which cause kernel panic + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 jeffrey.chang + * + * add new KAL api + * + * 07 23 2010 jeffrey.chang + * + * bug fix: allocate regInfo when disabling firmware download + * + * 07 23 2010 jeffrey.chang + * + * use glue layer api to decrease or increase counter atomically + * + * 07 22 2010 jeffrey.chang + * + * modify tx thread and remove some spinlock + * + * 07 22 2010 jeffrey.chang + * + * use different spin lock for security frame + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * add spinlock for pending security frame count + * + * 07 19 2010 jeffrey.chang + * + * adjust the timer unit to microsecond + * + * 07 19 2010 jeffrey.chang + * + * timer should return value greater than zero + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 19 2010 jeffrey.chang + * + * add new kal api + * + * 07 19 2010 jeffrey.chang + * + * for linux driver migration + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 yarco.yang + * [WPD00003837][MT6620]Data Path Refine + * Merge g_arStaRec[] into adapter->arStaRec[] + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * remove unused files. + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix private ioctl for rftest + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * workaround for fixing request_firmware() failure on android 2.1 + * + * 05 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix kernel panic when debug mode enabled + * + * 05 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) Modify set mac address code + * 2) remove power management macro + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Disable network interface after disassociation + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 15 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * change firmware name + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * flush pending TX packets while unloading driver + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set driver own before handling cmd queue + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used + * 2) fix ioctl + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler + * * * * * * * * * * * * * * * * * * capability + * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add spinlock for i4TxPendingFrameNum access + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * * 2) add KAPI for handling association info + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix spinlock usage + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding firmware download KAPI + * + * 04 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Set MAC address from firmware + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1. free cmdinfo after command is emiited. + * 2. for BoW frames, user priority is extracted from sk_buff directly. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)deliver the kalOidComplete status to upper layer + * (2) fix spin lock + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * * 2) add 2 kal API for later integration + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * raising the priority of processing interrupt + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Bug fix: the tx thread will cause starvation of MMC thread, and the interrupt will never come in + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding secondary command queue for improving non-glue code portability + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download kal api + * + * 03 25 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add Bluetooth-over-Wifi frame header check + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\50 2009-09-28 20:19:08 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\49 2009-08-18 22:56:44 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\48 2009-06-23 23:18:58 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\47 2008-11-19 11:55:43 GMT mtk01088 +** fixed some lint warning, and rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\46 2008-09-02 21:07:42 GMT mtk01461 +** Remove ASSERT(pvBuf) in kalIndicateStatusAndComplete(), this parameter can be NULL +** \main\maintrunk.MT5921\45 2008-08-29 16:03:21 GMT mtk01088 +** remove non-used code for code review, add assert check +** \main\maintrunk.MT5921\44 2008-08-21 00:32:49 GMT mtk01461 +** \main\maintrunk.MT5921\43 2008-05-30 20:27:02 GMT mtk01461 +** Rename KAL function +** \main\maintrunk.MT5921\42 2008-05-30 15:47:29 GMT mtk01461 +** \main\maintrunk.MT5921\41 2008-05-30 15:13:04 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\40 2008-05-29 14:15:14 GMT mtk01084 +** remove un-used KAL function +** \main\maintrunk.MT5921\39 2008-05-03 15:17:30 GMT mtk01461 +** Move Query Media Status to GLUE +** \main\maintrunk.MT5921\38 2008-04-24 11:59:44 GMT mtk01461 +** change awake queue threshold and remove code which mark #if 0 +** \main\maintrunk.MT5921\37 2008-04-17 23:06:35 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\36 2008-04-08 15:38:56 GMT mtk01084 +** add KAL function to setting pattern search function enable/ disable +** \main\maintrunk.MT5921\35 2008-04-01 23:53:13 GMT mtk01461 +** Add comment +** \main\maintrunk.MT5921\34 2008-03-26 15:36:48 GMT mtk01461 +** Add update MAC Address for Linux +** \main\maintrunk.MT5921\33 2008-03-18 11:49:34 GMT mtk01084 +** update function for initial value access +** \main\maintrunk.MT5921\32 2008-03-18 10:25:22 GMT mtk01088 +** use kal update associate request at linux +** \main\maintrunk.MT5921\31 2008-03-06 23:43:08 GMT mtk01385 +** 1. add Query Registry Mac address function. +** \main\maintrunk.MT5921\30 2008-02-26 09:47:57 GMT mtk01084 +** modify KAL set network address/ checksum offload part +** \main\maintrunk.MT5921\29 2008-02-12 23:26:53 GMT mtk01461 +** Add debug option - Packet Order for Linux +** \main\maintrunk.MT5921\28 2008-01-09 17:54:43 GMT mtk01084 +** modify the argument of kalQueryPacketInfo() +** \main\maintrunk.MT5921\27 2007-12-24 16:02:03 GMT mtk01425 +** 1. Revise csum offload +** \main\maintrunk.MT5921\26 2007-11-30 17:03:36 GMT mtk01425 +** 1. Fix bugs +** +** \main\maintrunk.MT5921\25 2007-11-29 01:57:17 GMT mtk01461 +** Fix Windows RX multiple packet retain problem +** \main\maintrunk.MT5921\24 2007-11-20 11:24:07 GMT mtk01088 +** CR90, not doing the netif_carrier_off to let supplicant 1x pkt can be rcv at hardstattXmit +** \main\maintrunk.MT5921\23 2007-11-09 16:36:44 GMT mtk01425 +** 1. Modify for CSUM offloading with Tx Fragment +** \main\maintrunk.MT5921\22 2007-11-07 18:37:39 GMT mtk01461 +** Add Tx Fragmentation Support +** \main\maintrunk.MT5921\21 2007-11-06 19:34:06 GMT mtk01088 +** add the WPS code, indicate the mgmt frame to upper layer +** \main\maintrunk.MT5921\20 2007-11-02 01:03:21 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\19 2007-10-30 11:59:38 GMT MTK01425 +** 1. Update wlanQueryInformation +** \main\maintrunk.MT5921\18 2007-10-30 10:44:57 GMT mtk01425 +** 1. Refine multicast list code +** 2. Refine TCP/IP csum offload code +** +** Revision 1.5 2007/07/17 13:01:18 MTK01088 +** add associate req and rsp function +** +** Revision 1.4 2007/07/13 05:19:19 MTK01084 +** provide timer set functions +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include "gl_os.h" +#include "gl_wext.h" +#include "precomp.h" +#if defined(CONFIG_MTK_TC1_FEATURE) +#include +#endif +#if CFG_SUPPORT_AGPS_ASSIST +#include +#endif +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +#include +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +#if DBG +int allocatedMemSize = 0; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +/* #define MTK_DMA_BUF_MEMCPY_SUP */ +static PVOID pvIoBuffer; + +#ifdef MTK_DMA_BUF_MEMCPY_SUP +static PVOID pvIoPhyBuf; +static PVOID pvDmaBuffer; +static PVOID pvDmaPhyBuf; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + +static UINT_32 pvIoBufferSize; +static UINT_32 pvIoBufferUsage; +static struct KAL_HALT_CTRL_T rHaltCtrl = { + .lock = __SEMAPHORE_INITIALIZER(rHaltCtrl.lock, 1), + .owner = NULL, + .fgHalt = TRUE, + .fgHeldByKalIoctl = FALSE, + .u4HoldStart = 0, +}; +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT +typedef enum _ENUM_WMTHWVER_TYPE_T { + WMTHWVER_MT6620_E1 = 0x0, + WMTHWVER_MT6620_E2 = 0x1, + WMTHWVER_MT6620_E3 = 0x2, + WMTHWVER_MT6620_E4 = 0x3, + WMTHWVER_MT6620_E5 = 0x4, + WMTHWVER_MT6620_E6 = 0x5, + WMTHWVER_MT6620_MAX, + WMTHWVER_INVALID = 0xff +} ENUM_WMTHWVER_TYPE_T, *P_ENUM_WMTHWVER_TYPE_T; +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo) +{ + KAL_WAKE_LOCK_TIMEOUT(prGlueInfo->prAdapter, &(prGlueInfo->rAhbIsrWakeLock), (HZ / 10)); /* 100ms */ +} + +#if CFG_ENABLE_FW_DOWNLOAD + +static struct file *filp; +static uid_t orgfsuid; +static gid_t orgfsgid; +static mm_segment_t orgfs; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* open firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareOpen(IN P_GLUE_INFO_T prGlueInfo) +{ + UINT_8 aucFilePath[50]; + + /* FIX ME: since we don't have hotplug script in the filesystem + * , so the request_firmware() KAPI can not work properly + */ + + /* save uid and gid used for filesystem access. + * set user and group to 0(root) */ + struct cred *cred = (struct cred *)get_current_cred(); + + orgfsuid = cred->fsuid.val; + orgfsgid = cred->fsgid.val; + cred->fsuid.val = cred->fsgid.val = 0; + + ASSERT(prGlueInfo); + + orgfs = get_fs(); + set_fs(get_ds()); + + /* open the fw file */ +#if defined(MT6620) & CFG_MULTI_ECOVER_SUPPORT + switch (mtk_wcn_wmt_hwver_get()) { + case WMTHWVER_MT6620_E1: + case WMTHWVER_MT6620_E2: + case WMTHWVER_MT6620_E3: + case WMTHWVER_MT6620_E4: + case WMTHWVER_MT6620_E5: + filp = filp_open("/etc/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); + break; + + case WMTHWVER_MT6620_E6: + default: + filp = filp_open("/etc/firmware/" CFG_FW_FILENAME "_E6", O_RDONLY, 0); + break; + } +#elif defined(MT6628) +/* filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6628", O_RDONLY, 0); */ +/* filp = filp_open("/etc/firmware/"CFG_FW_FILENAME"_MT6582", O_RDONLY, 0); */ +#if 0 /* new wifi ram code mechanism, waiting firmware ready, then we can enable these code */ + kalMemZero(aucFilePath, sizeof(aucFilePath)); + kalMemCopy(aucFilePath, "/etc/firmware/" CFG_FW_FILENAME "_AD", sizeof("/etc/firmware/" CFG_FW_FILENAME "_AD")); + filp = filp_open(aucFilePath, O_RDONLY, 0); + if (!IS_ERR(filp)) + goto open_success; +#endif + kalMemZero(aucFilePath, sizeof(aucFilePath)); + kalMemCopy(aucFilePath, "/etc/firmware/" CFG_FW_FILENAME "_", strlen("/etc/firmware/" CFG_FW_FILENAME "_")); + glGetChipInfo(prGlueInfo, &aucFilePath[strlen("/etc/firmware/" CFG_FW_FILENAME "_")]); + + DBGLOG(INIT, INFO, "open file: %s\n", aucFilePath); + + filp = filp_open(aucFilePath, O_RDONLY, 0); +#else + filp = filp_open("/etc/firmware/" CFG_FW_FILENAME, O_RDONLY, 0); +#endif + if (IS_ERR(filp)) { + DBGLOG(INIT, ERROR, "Open FW image: %s failed\n", CFG_FW_FILENAME); + goto error_open; + } +#if 0 +open_success: +#endif + DBGLOG(INIT, TRACE, "Open FW image: %s done\n", CFG_FW_FILENAME); + return WLAN_STATUS_SUCCESS; + +error_open: + /* restore */ + set_fs(orgfs); + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* release firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareClose(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + if ((filp != NULL) && !IS_ERR(filp)) { + /* close firmware file */ + filp_close(filp, NULL); + + /* restore */ + set_fs(orgfs); + { + struct cred *cred = (struct cred *)get_current_cred(); + + cred->fsuid.val = orgfsuid; + cred->fsgid.val = orgfsgid; + put_cred(cred); + } + filp = NULL; + } + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* load firmware image in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalFirmwareLoad(IN P_GLUE_INFO_T prGlueInfo, OUT PVOID prBuf, IN UINT_32 u4Offset, OUT PUINT_32 pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + ASSERT(prBuf); + + /* l = filp->f_path.dentry->d_inode->i_size; */ +#if 0 + /* the object must have a read method */ + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) || (filp->f_op->read == NULL)) { + goto error_read; + } else { + filp->f_pos = u4Offset; + *pu4Size = filp->f_op->read(filp, prBuf, *pu4Size, &filp->f_pos); + } +#else + /* the object must have a read method */ + if ((filp == NULL) || IS_ERR(filp) || (filp->f_op == NULL) ) { + goto error_read; + } else { + filp->f_pos = u4Offset; + *pu4Size = vfs_read(filp, prBuf, *pu4Size, &filp->f_pos); + } +#endif + + return WLAN_STATUS_SUCCESS; + +error_read: + return WLAN_STATUS_FAILURE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to +* query firmware image size in kernel space +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ + +WLAN_STATUS kalFirmwareSize(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_32 pu4Size) +{ + ASSERT(prGlueInfo); + ASSERT(pu4Size); + + //*pu4Size = filp->f_path.dentry->d_inode->i_size; + *pu4Size = filp->f_op->llseek(filp, 0, 2); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to load firmware image +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image +* \param pu4FileLength File length and memory mapped length as well + +* \retval Map File Handle, used for unammping +*/ +/*----------------------------------------------------------------------------*/ + +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength) +{ + UINT_32 u4FwSize = 0; + PVOID prFwBuffer = NULL; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + do { + /* <1> Open firmware */ + if (kalFirmwareOpen(prGlueInfo) != WLAN_STATUS_SUCCESS) { + DBGLOG(INIT, TRACE, "kalFirmwareOpen fail!\n"); + break; + } + + /* <2> Query firmare size */ + kalFirmwareSize(prGlueInfo, &u4FwSize); + printk(KERN_ERR "%s firmware size %d\n", __FUNCTION__, u4FwSize); + /* <3> Use vmalloc for allocating large memory trunk */ + prFwBuffer = vmalloc(ALIGN_4(u4FwSize)); + /* <4> Load image binary into buffer */ + if (kalFirmwareLoad(prGlueInfo, prFwBuffer, 0, &u4FwSize) != WLAN_STATUS_SUCCESS) { + vfree(prFwBuffer); + kalFirmwareClose(prGlueInfo); + DBGLOG(INIT, TRACE, "kalFirmwareLoad fail!\n"); + break; + } + /* <5> write back info */ + *pu4FileLength = u4FwSize; + *ppvMapFileBuf = prFwBuffer; + + return prFwBuffer; + + } while (FALSE); + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to unload firmware image mapped memory +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param pvFwHandle Pointer to mapping handle +* \param pvMapFileBuf Pointer to memory-mapped firmware image +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ + +VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + + /* pvMapFileBuf might be NULL when file doesn't exist */ + if (pvMapFileBuf) + vfree(pvMapFileBuf); + + kalFirmwareClose(prGlueInfo); +} + +#endif + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to load firmware image +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param ppvMapFileBuf Pointer of pointer to memory-mapped firmware image +* \param pu4FileLength File length and memory mapped length as well + +* \retval Map File Handle, used for unammping +*/ +/*----------------------------------------------------------------------------*/ + +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength) +{ + INT_32 i4Ret = 0; + + DEBUGFUNC("kalFirmwareImageMapping"); + + ASSERT(prGlueInfo); + ASSERT(ppvMapFileBuf); + ASSERT(pu4FileLength); + + do { + GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; + + prGlueInfo->prFw = NULL; + + /* <1> Open firmware */ + i4Ret = request_firmware(&prGlueInfo->prFw, CFG_FW_FILENAME, prHifInfo->Dev); + + if (i4Ret) { + DBGLOG(INIT, TRACE, "fw %s:request failed %d\n", CFG_FW_FILENAME, i4Ret); + break; + } + *pu4FileLength = prGlueInfo->prFw->size; + *ppvMapFileBuf = prGlueInfo->prFw->data; + return prGlueInfo->prFw->data; + + } while (FALSE); + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to unload firmware image mapped memory +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* \param pvFwHandle Pointer to mapping handle +* \param pvMapFileBuf Pointer to memory-mapped firmware image +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ + +VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf) +{ + DEBUGFUNC("kalFirmwareImageUnmapping"); + + ASSERT(prGlueInfo); + ASSERT(pvMapFileBuf); + + release_firmware(prGlueInfo->prFw); + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to acquire +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[out] pu4Flags Pointer of a variable for saving IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags) +{ + unsigned long u4Flags = 0; + + ASSERT(prGlueInfo); + ASSERT(pu4Flags); + + if (rLockCategory < SPIN_LOCK_NUM) { + +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_lock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_lock_irqsave(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + *pu4Flags = u4Flags; +/* DBGLOG(INIT, TRACE, ("A+%d\n", rLockCategory)); */ + } + +} /* end of kalAcquireSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to release +* OS SPIN_LOCK. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[in] u4Flags Saved IRQ flags +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags) +{ + ASSERT(prGlueInfo); + + if (rLockCategory < SPIN_LOCK_NUM) { + /* DBGLOG(INIT, TRACE, ("A-%d %d %d\n", rLockCategory, u4MemAllocCnt, u4MemFreeCnt)); */ +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF + spin_unlock_bh(&prGlueInfo->rSpinLock[rLockCategory]); +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + spin_unlock_irqrestore(&prGlueInfo->rSpinLock[rLockCategory], u4Flags); +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + + } + +} /* end of kalReleaseSpinLock() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is provided by GLUE Layer for internal driver stack to update +* current MAC address. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pucMacAddr Pointer of current MAC address +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr) +{ + ASSERT(prGlueInfo); + ASSERT(pucMacAddr); + + if (UNEQUAL_MAC_ADDR(prGlueInfo->prDevHandler->dev_addr, pucMacAddr)) + memcpy(prGlueInfo->prDevHandler->dev_addr, pucMacAddr, PARAM_MAC_ADDR_LEN); + +} + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +/*----------------------------------------------------------------------------*/ +/*! +* \brief To query the packet information for offload related parameters. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + UINT_8 ucFlag = 0; + + ASSERT(pvPacket); + ASSERT(pucFlag); + + + if (skb->ip_summed == CHECKSUM_PARTIAL) { +#if DBG + /* Kevin: do double check, we can remove this part in Normal Driver. + * Because we register NIC feature with NETIF_F_IP_CSUM for MT5912B MAC, so + * we'll process IP packet only. + */ + if (skb->protocol != htons(ETH_P_IP)) { + /* printk("Wrong skb->protocol( = %08x) for TX Checksum Offload.\n", skb->protocol); */ + } else +#endif + ucFlag |= (TX_CS_IP_GEN | TX_CS_TCP_UDP_GEN); + } + + *pucFlag = ucFlag; + +} /* kalQueryChksumOffloadParam */ + +/* 4 2007/10/8, mikewu, this is rewritten by Mike */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief To update the checksum offload status to the packet to be indicated to OS. +* +* \param[in] pvPacket Pointer to the packet descriptor. +* \param[in] pucFlag Points to the offload related parameter. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T aeCSUM[]) +{ + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + ASSERT(pvPacket); + + if ((aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_SUCCESS || aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_SUCCESS) && + ((aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_SUCCESS) || (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_SUCCESS))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else { + skb->ip_summed = CHECKSUM_NONE; +#if DBG + if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_NONE && aeCSUM[CSUM_TYPE_IPV6] == CSUM_RES_NONE) + DBGLOG(RX, TRACE, "RX: \"non-IPv4/IPv6\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_IPV4] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad IP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_TCP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad TCP Checksum\" Packet\n"); + else if (aeCSUM[CSUM_TYPE_UDP] == CSUM_RES_FAILED) + DBGLOG(RX, TRACE, "RX: \"bad UDP Checksum\" Packet\n"); + else + /* Do nothing */ +#endif + } + +} /* kalUpdateRxCSUMOffloadParam */ +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called to free packet allocated from kalPacketAlloc. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of the packet descriptor +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) +{ + dev_kfree_skb((struct sk_buff *)pvPacket); + if (prGlueInfo) + prGlueInfo->u8SkbFreed++; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Only handles driver own creating packet (coalescing buffer). +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param u4Size Pointer of Packet Handle +* \param ppucData Status Code for OS upper layer +* +* \return NULL: Failed to allocate skb, Not NULL get skb +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PUINT_8 *ppucData) +{ + struct sk_buff *prSkb = dev_alloc_skb(u4Size); + + if (prSkb) + *ppucData = (PUINT_8) (prSkb->data); +#if DBG + { + PUINT_32 pu4Head = (PUINT_32) &prSkb->cb[0]; + *pu4Head = (UINT_32) prSkb->head; + DBGLOG(RX, TRACE, "prSkb->head = %#x, prSkb->cb = %#x\n", (UINT_32) prSkb->head, *pu4Head); + } +#endif + return (PVOID) prSkb; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Process the received packet for indicating to OS. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] pvPacket Pointer of the packet descriptor +* \param[in] pucPacketStart The starting address of the buffer of Rx packet. +* \param[in] u4PacketLen The packet length. +* \param[in] pfgIsRetain Is the packet to be retained. +* \param[in] aerCSUM The result of TCP/ IP checksum offload. +* +* \retval WLAN_STATUS_SUCCESS. +* \retval WLAN_STATUS_FAILURE. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS +kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aerCSUM[]) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + struct sk_buff *skb = (struct sk_buff *)pvPacket; + + skb->data = pucPacketStart; + skb_reset_tail_pointer(skb); /* reset tail pointer first, for 64bit kernel,we should call linux kernel API */ + skb_trim(skb, 0); /* only if skb->len > len, then skb_trim has effect */ + skb_put(skb, u4PacketLen); /* shift tail and skb->len to correct value */ + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + kalUpdateRxCSUMOffloadParam(skb, aerCSUM); +#endif + + return rStatus; +} + +#if (CONF_HIF_LOOPBACK_AUTO == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Do HIF loopback test. +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +unsigned int testmode = 0; +unsigned int testlen = 64; + +void kalDevLoopbkAuto(IN GLUE_INFO_T *GlueInfo) +{ +#define HIF_LOOPBK_AUTO_TEST_LEN 1600 +/* GL_HIF_INFO_T *HifInfo; */ + static unsigned int txcnt; + struct sk_buff *MsduInfo; + UINT_8 *Pkt; + UINT_32 RegVal; + UINT_32 PktLen = 16; + + /* Init */ + if (testmode != 0) { + PktLen = kalRandomNumber() % 1520; + if (PktLen < 64) + PktLen = 64; + } else { + PktLen = testlen++; + if (PktLen > 1520) { + testmode = 1; + PktLen = 64; + } + } + +/* PktLen = 100; */ + DBGLOG(INIT, INFO, "kalDevLoopbkAuto> Send a packet to HIF (len = %d) (total = %d)...\n", PktLen, ++txcnt); +/* HifInfo = &GlueInfo->rHifInfo; */ + + /* Allocate a MSDU_INFO_T */ + MsduInfo = kalPacketAlloc(GlueInfo, HIF_LOOPBK_AUTO_TEST_LEN, &Pkt); + if (MsduInfo == NULL) { + DBGLOG(INIT, WARN, "No PKT_INFO_T for sending loopback packet!\n"); + return; + } + + /* Init the packet */ + MsduInfo->dev = GlueInfo->prDevHandler; + if (MsduInfo->dev == NULL) { + DBGLOG(INIT, WARN, "MsduInfo->dev == NULL!!\n"); + kalPacketFree(GlueInfo, MsduInfo); + return; + } + + MsduInfo->len = PktLen; + kalMemSet(MsduInfo->data, 0xff, 6); + kalMemSet(MsduInfo->data + 6, 0x5a, PktLen - 6); + + /* Simulate OS to send the packet */ + wlanHardStartXmit(MsduInfo, MsduInfo->dev); + +#if 0 + PktLen += 4; + if (PktLen >= 1600) + PktLen = 16; +#endif + + /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ +/* HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(1000); */ +/* add_timer(&(HifInfo->HifTmrLoopbkFn)); */ +} + +int kalDevLoopbkThread(IN void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; + int ret; + static int test; + + while (TRUE) { + ret = wait_event_interruptible(HifInfo->HifWaitq, (HifInfo->HifLoopbkFlg != 0)); + + if (HifInfo->HifLoopbkFlg == 0xFFFFFFFF) + break; + + while (TRUE) { + /* if ((HifInfo->HifLoopbkFlg & 0x01) == 0) */ + if (GlueInfo->i4TxPendingFrameNum < 64) { + DBGLOG(INIT, INFO, "GlueInfo->i4TxPendingFrameNum = %d\n", + GlueInfo->i4TxPendingFrameNum); + kalDevLoopbkAuto(GlueInfo); + + if (testmode == 0) + kalMsleep(3000); + } else + kalMsleep(1); + } + } +} + +void kalDevLoopbkRxHandle(IN P_ADAPTER_T prAdapter, IN OUT P_SW_RFB_T prSwRfb) +{ + static unsigned int rxcnt; + UINT_32 i; + UINT_8 *Buf = prSwRfb->pucRecvBuff + sizeof(HIF_TX_HEADER_T); + P_HIF_RX_HEADER_T prHifRxHdr = prSwRfb->prHifRxHdr; + UINT_32 len = prHifRxHdr->u2PacketLen - sizeof(HIF_TX_HEADER_T); + + if (len > 1600) { + while (1) + DBGLOG(INIT, ERROR, "HIF> Loopback len > 1600!!! error!!!\n"); + } + + for (i = 0; i < 6; i++) { + if (Buf[i] != 0xff) { + while (1) { + DBGLOG(INIT, ERROR, "HIF> Loopbk dst addr error (len = %d)!\n", len); + dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); + } + } + } + + for (i = 6; i < len; i++) { + if (Buf[i] != 0x5a) { + while (1) { + DBGLOG(INIT, ERROR, "HIF> Loopbk error (len = %d)!\n", len); + dumpMemory8(prSwRfb->pucRecvBuff, prHifRxHdr->u2PacketLen); + } + } + } + + DBGLOG(INIT, INFO, "HIF> Loopbk OK (len = %d) (total = %d)!\n", len, ++rxcnt); +} +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate an array of received packets is available for higher +* level protocol uses. +* +* \param[in] prGlueInfo Pointer to the Adapter structure. +* \param[in] apvPkts The packet array to be indicated +* \param[in] ucPktNum The number of packets to be indicated +* +* \retval TRUE Success. +* +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum) +{ + UINT_8 ucIdx = 0; + struct net_device *prNetDev = prGlueInfo->prDevHandler; + struct sk_buff *prSkb = NULL; + + ASSERT(prGlueInfo); + ASSERT(apvPkts); + +#if CFG_BOW_TEST + UINT_32 i; +#endif + + for (ucIdx = 0; ucIdx < ucPktNum; ucIdx++) { + prSkb = apvPkts[ucIdx]; +#if DBG + do { + PUINT_8 pu4Head = (PUINT_8) &prSkb->cb[0]; + UINT_32 u4HeadValue = 0; + + kalMemCopy(&u4HeadValue, pu4Head, sizeof(u4HeadValue)); + DBGLOG(RX, TRACE, "prSkb->head = %p, prSkb->cb = 0x%x\n", pu4Head, u4HeadValue); + } while (0); +#endif + + if (GLUE_GET_PKT_IS_P2P(prSkb)) { + /* P2P */ +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + prNetDev = kalP2PGetDevHdlr(prGlueInfo); + /* prNetDev->stats.rx_bytes += prSkb->len; */ + /* prNetDev->stats.rx_packets++; */ + prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.rx_packets++; + +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } else if (GLUE_GET_PKT_IS_PAL(prSkb)) { + /* BOW */ +#if CFG_ENABLE_BT_OVER_WIFI && CFG_BOW_SEPARATE_DATA_PATH + if (prGlueInfo->rBowInfo.fgIsNetRegistered) + prNetDev = prGlueInfo->rBowInfo.prDevHandler; +#else + prNetDev = prGlueInfo->prDevHandler; +#endif + } else { + /* AIS */ + prNetDev = prGlueInfo->prDevHandler; + prGlueInfo->rNetDevStats.rx_bytes += prSkb->len; + prGlueInfo->rNetDevStats.rx_packets++; + + } + + /* check if the "unicast" packet is from us */ + if (kalMemCmp(prSkb->data, prSkb->data + 6, 6) == 0) { + /* we will filter broadcast/multicast packet sent from us in hardware */ + /* source address = destination address ? */ + DBGLOG(RX, EVENT, + "kalRxIndicatePkts got from us!!! Drop it! ([ %pM ] len %d)\n", + prSkb->data, prSkb->len); + wlanReturnPacket(prGlueInfo->prAdapter, prSkb); + continue; + } +#if (CFG_SUPPORT_TDLS == 1) + if (TdlsexRxFrameDrop(prGlueInfo, prSkb->data) == TRUE) { + /* drop the received TDLS action frame */ + DBGLOG(TDLS, WARN, + " %s: drop a received packet from %pM %u\n", + __func__, prSkb->data, + (UINT32) ((P_ADAPTER_T) (prGlueInfo->prAdapter))->rRxCtrl.rFreeSwRfbList.u4NumElem); + wlanReturnPacket(prGlueInfo->prAdapter, prSkb); + continue; + } + + /* + get a TDLS request/response/confirm, we need to parse the HT IE + because older supplicant does not pass HT IE to us + */ + TdlsexRxFrameHandle(prGlueInfo, prSkb->data, prSkb->len); +#endif /* CFG_SUPPORT_TDLS */ + + STATS_RX_PKT_INFO_DISPLAY(prSkb->data); + + //prNetDev->last_rx = jiffies; + prSkb->protocol = eth_type_trans(prSkb, prNetDev); + prSkb->dev = prNetDev; + /* DBGLOG_MEM32(RX, TRACE, (PUINT_32)prSkb->data, prSkb->len); */ + DBGLOG(RX, TRACE, "kalRxIndicatePkts len = %d\n", prSkb->len); + +#if CFG_BOW_TEST + DBGLOG(BOW, TRACE, "Rx sk_buff->len: %d\n", prSkb->len); + DBGLOG(BOW, TRACE, "Rx sk_buff->data_len: %d\n", prSkb->data_len); + DBGLOG(BOW, TRACE, "Rx sk_buff->data:\n"); + + for (i = 0; i < prSkb->len; i++) { + DBGLOG(BOW, TRACE, "%4x", prSkb->data[i]); + + if ((i + 1) % 16 == 0) + DBGLOG(BOW, TRACE, "\n"); + } + + DBGLOG(BOW, TRACE, "\n"); +#endif + + if (!in_interrupt()) + netif_rx_ni(prSkb); /* only in non-interrupt context */ + else + netif_rx(prSkb); + + wlanReturnPacket(prGlueInfo->prAdapter, NULL); + } + + kalPerMonStart(prGlueInfo); + + return WLAN_STATUS_SUCCESS; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Called by driver to indicate event to upper layer, for example, the wpa +* supplicant or wireless tools. +* +* \param[in] pvAdapter Pointer to the adapter descriptor. +* \param[in] eStatus Indicated status. +* \param[in] pvBuf Indicated message buffer. +* \param[in] u4BufLen Indicated message buffer size. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 ScanCnt = 0, ScanDoneFailCnt = 0; +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen) +{ + UINT_32 bufLen; + P_PARAM_STATUS_INDICATION_T pStatus = (P_PARAM_STATUS_INDICATION_T) pvBuf; + P_PARAM_AUTH_EVENT_T pAuth = (P_PARAM_AUTH_EVENT_T) pStatus; + P_PARAM_PMKID_CANDIDATE_LIST_T pPmkid = (P_PARAM_PMKID_CANDIDATE_LIST_T) (pStatus + 1); + PARAM_MAC_ADDRESS arBssid; + struct cfg80211_scan_request *prScanRequest = NULL; + PARAM_SSID_T ssid; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_bss *bss; + UINT_8 ucChannelNum; + P_BSS_DESC_T prBssDesc = NULL; + struct cfg80211_scan_info info = { + .aborted = false, + }; + + GLUE_SPIN_LOCK_DECLARATION(); + + kalMemZero(arBssid, MAC_ADDR_LEN); + + ASSERT(prGlueInfo); + + switch (eStatus) { + case WLAN_STATUS_ROAM_OUT_FIND_BEST: + case WLAN_STATUS_MEDIA_CONNECT: + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_CONNECTED; + + /* indicate assoc event */ + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQueryBssid, &arBssid[0], sizeof(arBssid), &bufLen); + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, arBssid, bufLen); + + /* switch netif on */ + netif_carrier_on(prGlueInfo->prDevHandler); + + do { + /* print message on console */ + wlanQueryInformation(prGlueInfo->prAdapter, wlanoidQuerySsid, &ssid, sizeof(ssid), &bufLen); + + ssid.aucSsid[(ssid.u4SsidLen >= PARAM_MAX_LEN_SSID) ? + (PARAM_MAX_LEN_SSID - 1) : ssid.u4SsidLen] = '\0'; + DBGLOG(AIS, INFO, " %s netif_carrier_on [ssid:%s %pM ]\n", + prGlueInfo->prDevHandler->name, ssid.aucSsid, arBssid); + } while (0); + + if (prGlueInfo->fgIsRegistered == TRUE) { + struct cfg80211_bss *bss_others = NULL; + UINT_8 ucLoopCnt = 15; /* only loop 15 times to avoid dead loop */ + + /* retrieve channel */ + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + NL80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, + NL80211_BAND_5GHZ)); + } + + /* ensure BSS exists */ + bss = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), prChannel, arBssid, + ssid.aucSsid, ssid.u4SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + + if (bss == NULL) { + /* create BSS on-the-fly */ + prBssDesc = + wlanGetTargetBssDescByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prBssDesc != NULL) { + bss = cfg80211_inform_bss(priv_to_wiphy(prGlueInfo), prChannel, + CFG80211_BSS_FTYPE_PRESP, + arBssid, 0, /* TSF */ + WLAN_CAPABILITY_ESS, + prBssDesc->u2BeaconInterval, /* beacon interval */ + prBssDesc->aucIEBuf, /* IE */ + prBssDesc->u2IELength, /* IE Length */ + RCPI_TO_dBm(prBssDesc->ucRCPI) * 100, /* MBM */ + GFP_KERNEL); + } + } + /* remove all bsses that before and only channel different with the current connected one + if without this patch, UI will show channel A is connected even if AP has change channel + from A to B */ + while (ucLoopCnt--) { + bss_others = cfg80211_get_bss(priv_to_wiphy(prGlueInfo), NULL, arBssid, + ssid.aucSsid, ssid.u4SsidLen, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); + if (bss && bss_others && bss_others != bss) { + DBGLOG(SCN, INFO, "remove BSSes that only channel different\n"); + cfg80211_unlink_bss(priv_to_wiphy(prGlueInfo), bss_others); + } else + break; + } + + /* CFG80211 Indication */ + if (eStatus == WLAN_STATUS_ROAM_OUT_FIND_BEST) { + /*cfg80211_roamed_bss(prGlueInfo->prDevHandler, + bss, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, prGlueInfo->u4RspIeLength, GFP_KERNEL); + */ + struct cfg80211_roam_info roam_info = { + .bss = bss, + .req_ie = prGlueInfo->aucReqIe, + .req_ie_len = prGlueInfo->u4ReqIeLength, + .resp_ie = prGlueInfo->aucRspIe, + .resp_ie_len = prGlueInfo->u4RspIeLength + }; + cfg80211_roamed(prGlueInfo->prDevHandler, + &roam_info, + GFP_KERNEL); + } else { + /* to support user space roaming, cfg80211 will change the sme_state to connecting + before reassociate */ + cfg80211_connect_result(prGlueInfo->prDevHandler, + arBssid, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_SUCCESS, GFP_KERNEL); + } + } + + break; + + case WLAN_STATUS_MEDIA_DISCONNECT: + case WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY: + /* indicate disassoc event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWAP, NULL, 0); + /* For CR 90 and CR99, While supplicant do reassociate, driver will do netif_carrier_off first, + after associated success, at joinComplete(), do netif_carier_on, + but for unknown reason, the supplicant 1x pkt will not called the driver + hardStartXmit, for template workaround these bugs, add this compiling flag + */ + /* switch netif off */ + + DBGLOG(AIS, INFO, "[wifi] %s netif_carrier_off\n", + prGlueInfo->prDevHandler->name); + + netif_carrier_off(prGlueInfo->prDevHandler); + + if (prGlueInfo->fgIsRegistered == TRUE) { + P_WIFI_VAR_T prWifiVar = &prGlueInfo->prAdapter->rWifiVar; + UINT_16 u2DeauthReason = prWifiVar->arBssInfo[NETWORK_TYPE_AIS_INDEX].u2DeauthReason; + /* CFG80211 Indication */ + DBGLOG(AIS, INFO, "[wifi] %s cfg80211_disconnected\n", prGlueInfo->prDevHandler->name); + cfg80211_disconnected(prGlueInfo->prDevHandler, u2DeauthReason, NULL, 0, false, GFP_KERNEL); + } + + prGlueInfo->eParamMediaStateIndicated = PARAM_MEDIA_STATE_DISCONNECTED; + + break; + + case WLAN_STATUS_SCAN_COMPLETE: + /* indicate scan complete event */ + wext_indicate_wext_event(prGlueInfo, SIOCGIWSCAN, NULL, 0); + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prScanRequest != NULL) { + prScanRequest = prGlueInfo->prScanRequest; + prGlueInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 2. then CFG80211 Indication */ + DBGLOG(SCN, TRACE, "[ais] scan complete %p %d %d\n", prScanRequest, ScanCnt, ScanDoneFailCnt); + + if (prScanRequest != NULL) + cfg80211_scan_done(prScanRequest, &info); + break; + case WLAN_STATUS_CONNECT_INDICATION: + /* indicate AIS Jion fail event + if (prGlueInfo->prDevHandler->ieee80211_ptr->sme_state == CFG80211_SME_CONNECTING) */ + cfg80211_connect_result(prGlueInfo->prDevHandler, + prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo.prTargetBssDesc->aucBSSID, + prGlueInfo->aucReqIe, + prGlueInfo->u4ReqIeLength, + prGlueInfo->aucRspIe, + prGlueInfo->u4RspIeLength, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); + break; + +#if 0 + case WLAN_STATUS_MSDU_OK: + if (netif_running(prGlueInfo->prDevHandler)) + netif_wake_queue(prGlueInfo->prDevHandler); + break; +#endif + + case WLAN_STATUS_MEDIA_SPECIFIC_INDICATION: + if (pStatus) { + switch (pStatus->eStatusType) { + case ENUM_STATUS_TYPE_AUTHENTICATION: + /* + printk(KERN_NOTICE "ENUM_STATUS_TYPE_AUTHENTICATION: L(%ld) [ %pM ] F:%lx\n", + pAuth->Request[0].Length, + pAuth->Request[0].Bssid, + pAuth->Request[0].Flags); + */ + /* indicate (UC/GC) MIC ERROR event only */ + if ((pAuth->arRequest[0].u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) || + (pAuth->arRequest[0].u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR)) { + cfg80211_michael_mic_failure(prGlueInfo->prDevHandler, NULL, + (pAuth->arRequest[0].u4Flags == + PARAM_AUTH_REQUEST_PAIRWISE_ERROR) ? + NL80211_KEYTYPE_PAIRWISE : NL80211_KEYTYPE_GROUP, + 0, NULL, GFP_KERNEL); + wext_indicate_wext_event(prGlueInfo, IWEVMICHAELMICFAILURE, + (unsigned char *)&pAuth->arRequest[0], + pAuth->arRequest[0].u4Length); + } + break; + + case ENUM_STATUS_TYPE_CANDIDATE_LIST: + /* + printk(KERN_NOTICE "Param_StatusType_PMKID_CandidateList: Ver(%ld) Num(%ld)\n", + pPmkid->u2Version, + pPmkid->u4NumCandidates); + if (pPmkid->u4NumCandidates > 0) { + printk(KERN_NOTICE "candidate[ %pM ] preAuth Flag:%lx\n", + pPmkid->arCandidateList[0].rBSSID, + pPmkid->arCandidateList[0].fgFlags); + } + */ + { + UINT_32 i = 0; + /*struct net_device *prDev = prGlueInfo->prDevHandler; */ + P_PARAM_PMKID_CANDIDATE_T prCand = NULL; + /* indicate pmk candidate via cfg80211 to supplicant, + the second parameter is 1000 for + cfg80211_pmksa_candidate_notify, because wpa_supplicant defined it. */ + for (i = 0; i < pPmkid->u4NumCandidates; i++) { + prCand = &pPmkid->arCandidateList[i]; + cfg80211_pmksa_candidate_notify(prGlueInfo->prDevHandler, 1000, + prCand->arBSSID, prCand->u4Flags, + GFP_KERNEL); + + wext_indicate_wext_event(prGlueInfo, + IWEVPMKIDCAND, + (unsigned char *)prCand, + pPmkid->u4NumCandidates); + } + } + break; + + default: + /* case ENUM_STATUS_TYPE_MEDIA_STREAM_MODE */ + /* + printk(KERN_NOTICE "unknown media specific indication type:%x\n", + pStatus->StatusType); + */ + break; + } + } else { + /* + printk(KERN_WARNING "media specific indication buffer NULL\n"); + */ + } + break; + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + case WLAN_STATUS_BWCS_UPDATE: + { + wext_indicate_wext_event(prGlueInfo, IWEVCUSTOM, pvBuf, sizeof(PTA_IPC_T)); + } + + break; + +#endif + + default: + /* + printk(KERN_WARNING "unknown indication:%lx\n", eStatus); + */ + break; + } +} /* kalIndicateStatusAndComplete */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to update the (re)association request +* information to the structure used to query and set +* OID_802_11_ASSOCIATION_INFORMATION. +* +* \param[in] prGlueInfo Pointer to the Glue structure. +* \param[in] pucFrameBody Pointer to the frame body of the last (Re)Association +* Request frame from the AP. +* \param[in] u4FrameBodyLen The length of the frame body of the last +* (Re)Association Request frame. +* \param[in] fgReassocRequest TRUE, if it is a Reassociation Request frame. +* +* \return (none) +* +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) +{ + PUINT_8 cp; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4ReqIeLength = 0; + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + wext_indicate_wext_event(prGlueInfo, IWEVASSOCREQIE, cp, u4FrameBodyLen); + + if (u4FrameBodyLen <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4ReqIeLength = u4FrameBodyLen; + kalMemCopy(prGlueInfo->aucReqIe, cp, u4FrameBodyLen); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This routine is called to update the (re)association +* response information to the structure used to reply with +* cfg80211_connect_result +* +* @param prGlueInfo Pointer to adapter descriptor +* @param pucFrameBody Pointer to the frame body of the last (Re)Association +* Response frame from the AP +* @param u4FrameBodyLen The length of the frame body of the last +* (Re)Association Response frame +* +* @return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen) +{ + UINT_32 u4IEOffset = 6; /* cap_info, status_code & assoc_id */ + UINT_32 u4IELength = u4FrameBodyLen - u4IEOffset; + + ASSERT(prGlueInfo); + + /* reset */ + prGlueInfo->u4RspIeLength = 0; + + if (u4IELength <= CFG_CFG80211_IE_BUF_LEN) { + prGlueInfo->u4RspIeLength = u4IELength; + kalMemCopy(prGlueInfo->aucRspIe, pucFrameBody + u4IEOffset, u4IELength); + } + +} /* kalUpdateReAssocRspInfo */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket) +{ + + struct net_device *prDev = NULL; + struct sk_buff *prSkb = NULL; + UINT_16 u2QueueIdx = 0; + UINT_8 ucNetworkType = 0; + BOOLEAN fgIsValidDevice = TRUE; + + ASSERT(pvPacket); + ASSERT(prGlueInfo->i4TxPendingFrameNum); + + prSkb = (struct sk_buff *)pvPacket; + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (GLUE_GET_PKT_IS_PAL(prSkb)) { + ucNetworkType = NETWORK_TYPE_BOW_INDEX; + } else if (GLUE_GET_PKT_IS_P2P(prSkb)) { + ucNetworkType = NETWORK_TYPE_P2P_INDEX; + +#if CFG_ENABLE_WIFI_DIRECT + /* in case packet was sent after P2P device is unregistered */ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) + fgIsValidDevice = FALSE; +#endif + } else { + ucNetworkType = NETWORK_TYPE_AIS_INDEX; + } + + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + if (u2QueueIdx < CFG_MAX_TXQ_NUM) + GLUE_DEC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); + prDev = prSkb->dev; + + ASSERT(prDev); + + if ((fgIsValidDevice == TRUE) && (u2QueueIdx < CFG_MAX_TXQ_NUM)) { + if (netif_subqueue_stopped(prDev, prSkb) && + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx] <= + CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_wake_subqueue for bss: %d. Queue len: %d\n", + ucNetworkType, + prGlueInfo->ai4TxPendingFrameNumPerQueue[ucNetworkType][u2QueueIdx]); + netif_wake_subqueue(prDev, u2QueueIdx); + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + prGlueInfo->rHifInfo.HifLoopbkFlg &= ~0x01; +#endif /* CONF_HIF_LOOPBACK_AUTO */ + } + } + + dev_kfree_skb((struct sk_buff *)pvPacket); + prGlueInfo->u8SkbFreed++; + + DBGLOG(TX, EVENT, "----- pending frame %d -----\n", prGlueInfo->i4TxPendingFrameNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Copy Mac Address setting from registry. It's All Zeros in Linux. +* +* \param[in] prAdapter Pointer to the Adapter structure +* +* \param[out] paucMacAddr Pointer to the Mac Address buffer +* +* \retval WLAN_STATUS_SUCCESS +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +VOID kalQueryRegistryMacAddr(IN P_GLUE_INFO_T prGlueInfo, OUT PUINT_8 paucMacAddr) +{ + UINT_8 aucZeroMac[MAC_ADDR_LEN] = { 0, 0, 0, 0, 0, 0 } + + DEBUGFUNC("kalQueryRegistryMacAddr"); + + ASSERT(prGlueInfo); + ASSERT(paucMacAddr); + + kalMemCopy((PVOID) paucMacAddr, (PVOID) aucZeroMac, MAC_ADDR_LEN); + +} /* end of kalQueryRegistryMacAddr() */ + +#if CFG_SUPPORT_EXT_CONFIG +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read external configuration, ex. NVRAM or file +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + /* External data is given from user space by ioctl or /proc, not read by + driver. + */ + if (0 != prGlueInfo->u4ExtCfgLength) + DBGLOG(INIT, TRACE, "Read external configuration data -- OK\n"); + else + DBGLOG(INIT, TRACE, "Read external configuration data -- fail\n"); + + return prGlueInfo->u4ExtCfgLength; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This inline function is to extract some packet information, including +* user priority, packet length, destination address, 802.1x and BT over Wi-Fi +* or not. +* +* @param prGlueInfo Pointer to the glue structure +* @param prNdisPacket Packet descriptor +* @param pucPriorityParam User priority +* @param pu4PacketLen Packet length +* @param pucEthDestAddr Destination address +* @param pfgIs1X 802.1x packet or not +* @param pfgIsPAL BT over Wi-Fi packet or not +* @prGenUse General used param +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, + OUT PVOID prGenUse) +{ + + UINT_32 u4PacketLen; + + UINT_8 ucUserPriority = USER_PRIORITY_DEFAULT; /* Default */ + UINT_16 u2EtherTypeLen; + struct sk_buff *prSkb = (struct sk_buff *)prPacket; + PUINT_8 aucLookAheadBuf = NULL; + + DEBUGFUNC("kalQoSFrameClassifierAndPacketInfo"); + + u4PacketLen = prSkb->len; + + if (u4PacketLen < ETH_HLEN) { + DBGLOG(TX, WARN, "Invalid Ether packet length: %u\n", (UINT_32) u4PacketLen); + return FALSE; + } + + aucLookAheadBuf = prSkb->data; + + *pfgIs1X = FALSE; + *pfgIsPAL = FALSE; + + /* 4 <3> Obtain the User Priority for WMM */ + u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]); + + if ((u2EtherTypeLen == ETH_P_IP) && (u4PacketLen >= LOOK_AHEAD_LEN)) { + PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucIpVersion; + + ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if (ucIpVersion == IPVERSION) { + UINT_8 ucIpTos; + /* Get the DSCP value from the header of IP packet. */ + ucIpTos = pucIpHdr[1]; + ucUserPriority = ((ucIpTos & IPTOS_PREC_MASK) >> IPTOS_PREC_OFFSET); + } + + /* TODO(Kevin): Add TSPEC classifier here */ + } else if (u2EtherTypeLen == ETH_P_1X || u2EtherTypeLen == ETH_P_PRE_1X) { /* For Port Control */ + PUINT_8 pucEapol = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucEapolType = pucEapol[1]; + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + /* + * generate a seq number used to trace security frame TX + */ + if (prGenUse) + *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); + + switch (ucEapolType) { + case 0: /* eap packet */ + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 1: /* eapol start */ + DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 3: /* key */ + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x... seqNo %d\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + } + *pfgIs1X = TRUE; + } +#if CFG_SUPPORT_WAPI + else if (u2EtherTypeLen == ETH_WPI_1X) { + PUINT_8 pucEthBody = &aucLookAheadBuf[ETH_HLEN]; + UINT_8 ucSubType = pucEthBody[3]; /* sub type filed*/ + UINT_16 u2Length = *(PUINT_16)&pucEthBody[6]; + UINT_16 u2Seq = *(PUINT_16)&pucEthBody[8]; + + DBGLOG(TX, INFO, " WAPI: subType %d, Len %d, Seq %d\n", + ucSubType, u2Length, u2Seq); + *pfgIs1X = TRUE; + } +#endif +#if (CFG_SUPPORT_TDLS == 1) + else if (u2EtherTypeLen == TDLS_FRM_PROT_TYPE) { + /* TDLS case */ + TDLSEX_UP_ASSIGN(ucUserPriority); + } +#endif /* CFG_SUPPORT_TDLS */ + else if (u2EtherTypeLen <= 1500) { /* 802.3 Frame */ + UINT_8 ucDSAP, ucSSAP, ucControl; + UINT_8 aucOUI[3]; + + ucDSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET]; + ucSSAP = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 1]; + ucControl = *(PUINT_8) &aucLookAheadBuf[ETH_LLC_OFFSET + 2]; + + aucOUI[0] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET]; + aucOUI[1] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 1]; + aucOUI[2] = *(PUINT_8) &aucLookAheadBuf[ETH_SNAP_OFFSET + 2]; + + if (ucDSAP == ETH_LLC_DSAP_SNAP && + ucSSAP == ETH_LLC_SSAP_SNAP && + ucControl == ETH_LLC_CONTROL_UNNUMBERED_INFORMATION && + aucOUI[0] == ETH_SNAP_BT_SIG_OUI_0 && + aucOUI[1] == ETH_SNAP_BT_SIG_OUI_1 && aucOUI[2] == ETH_SNAP_BT_SIG_OUI_2) { + + UINT_16 tmp = + ((aucLookAheadBuf[ETH_SNAP_OFFSET + 3] << 8) | aucLookAheadBuf[ETH_SNAP_OFFSET + 4]); + + *pfgIsPAL = TRUE; + ucUserPriority = (UINT_8) prSkb->priority; + + if (tmp == BOW_PROTOCOL_ID_SECURITY_FRAME) { + PUINT_8 pucEapol = &aucLookAheadBuf[ETH_SNAP_OFFSET + 5]; + UINT_8 ucEapolType = pucEapol[1]; + UINT_16 u2KeyInfo = pucEapol[5]<<8 | pucEapol[6]; + if (prGenUse) + *(UINT_8 *)prGenUse = nicIncreaseCmdSeqNum(prGlueInfo->prAdapter); + + switch (ucEapolType) { + case 0: /* eap packet */ + DBGLOG(TX, INFO, " EAP Packet: code %d, id %d, type %d, seqNo %d\n", + pucEapol[4], pucEapol[5], pucEapol[7], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 1: /* eapol start */ + DBGLOG(TX, INFO, " EAPOL: start, seqNo %d\n", + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + case 3: /* key */ + DBGLOG(TX, INFO, + " EAPOL: key, KeyInfo 0x%04x, Nonce %02x%02x%02x%02x%02x%02x%02x%02x seqNo %d\n", + u2KeyInfo, pucEapol[17], pucEapol[18], pucEapol[19], pucEapol[20], + pucEapol[21], pucEapol[22], pucEapol[23], pucEapol[24], + prGenUse ? *(UINT_8 *)prGenUse : 0); + break; + } + *pfgIs1X = TRUE; + } + } + } + /* 4 <4> Return the value of Priority Parameter. */ + *pucPriorityParam = ucUserPriority; + + /* 4 <5> Retrieve Packet Information - DA */ + /* Packet Length/ Destination Address */ + *pu4PacketLen = u4PacketLen; + + kalMemCopy(pucEthDestAddr, aucLookAheadBuf, PARAM_MAC_ADDR_LEN); + + /* <6> Network type */ +#if CFG_ENABLE_BT_OVER_WIFI + if (*pfgIsPAL == TRUE) { + *pucNetworkType = NETWORK_TYPE_BOW_INDEX; + } else +#endif + { +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered && GLUE_GET_PKT_IS_P2P(prPacket)) { + *pucNetworkType = NETWORK_TYPE_P2P_INDEX; + } else +#endif + { + *pucNetworkType = NETWORK_TYPE_AIS_INDEX; + } + } + return TRUE; +} /* end of kalQoSFrameClassifier() */ + +VOID +kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus) +{ + + ASSERT(prGlueInfo); + /* remove timeout check timer */ + wlanoidClearTimeoutCheck(prGlueInfo->prAdapter); + + /* if (prGlueInfo->u4TimeoutFlag != 1) { */ + prGlueInfo->rPendStatus = rOidStatus; + DBGLOG(OID, TEMP, "kalOidComplete, caller: %p\n", __builtin_return_address(0)); + complete(&prGlueInfo->rPendComp); + prGlueInfo->u4OidCompleteFlag = 1; + /* } */ + /* else let it timeout on kalIoctl entry */ +} + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + /* if (prGlueInfo->u4TimeoutFlag != 1) { */ + /* clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->u4Flag); */ + if (prGlueInfo->u4OidCompleteFlag != 1) { + DBGLOG(OID, TEMP, "kalOidClearance, caller: %p\n", __builtin_return_address(0)); + complete(&prGlueInfo->rPendComp); + } + /* } */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is used to transfer linux ioctl to OID, and we +* need to specify the behavior of the OID by ourself +* +* @param prGlueInfo Pointer to the glue structure +* @param pvInfoBuf Data buffer +* @param u4InfoBufLen Data buffer length +* @param fgRead Is this a read OID +* @param fgWaitResp does this OID need to wait for values +* @param fgCmd does this OID compose command packet +* @param pu4QryInfoLen The data length of the return values +* +* @retval TRUE Success to extract information +* @retval FALSE Fail to extract correct information +*/ +/*----------------------------------------------------------------------------*/ + +/* todo: enqueue the i/o requests for multiple processes access */ +/* */ +/* currently, return -1 */ +/* */ + +/* static GL_IO_REQ_T OidEntry; */ + +WLAN_STATUS +kalIoctl(IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen) +{ + P_GL_IO_REQ_T prIoReq = NULL; + WLAN_STATUS ret = WLAN_STATUS_SUCCESS; + + if (fgIsResetting == TRUE) + return WLAN_STATUS_SUCCESS; + + /* GLUE_SPIN_LOCK_DECLARATION(); */ + ASSERT(prGlueInfo); + + /* <1> Check if driver is halt */ + /* if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { */ + /* return WLAN_STATUS_ADAPTER_NOT_READY; */ + /* } */ + + /* if wait longer than double OID timeout timer, then will show backtrace who held halt lock. + at this case, we will return kalIoctl failure because tx_thread may be hung */ + if (kalHaltLock(2 * WLAN_OID_TIMEOUT_THRESHOLD)) + return WLAN_STATUS_FAILURE; + + if (kalIsHalted()) { + kalHaltUnlock(); + return WLAN_STATUS_ADAPTER_NOT_READY; + } + + if (down_interruptible(&prGlueInfo->ioctl_sem)) { + kalHaltUnlock(); + return WLAN_STATUS_FAILURE; + } + + /* <2> TODO: thread-safe */ + + /* <3> point to the OidEntry of Glue layer */ + + prIoReq = &(prGlueInfo->OidEntry); + + ASSERT(prIoReq); + + /* <4> Compose the I/O request */ + prIoReq->prAdapter = prGlueInfo->prAdapter; + prIoReq->pfnOidHandler = pfnOidHandler; + prIoReq->pvInfoBuf = pvInfoBuf; + prIoReq->u4InfoBufLen = u4InfoBufLen; + prIoReq->pu4QryInfoLen = pu4QryInfoLen; + prIoReq->fgRead = fgRead; + prIoReq->fgWaitResp = fgWaitResp; + prIoReq->rStatus = WLAN_STATUS_FAILURE; +#if CFG_ENABLE_WIFI_DIRECT + prIoReq->fgIsP2pOid = fgIsP2pOid; +#endif + + /* <5> Reset the status of pending OID */ + prGlueInfo->rPendStatus = WLAN_STATUS_FAILURE; + /* prGlueInfo->u4TimeoutFlag = 0; */ + /* prGlueInfo->u4OidCompleteFlag = 0; */ + + /* <6> Check if we use the command queue */ + prIoReq->u4Flag = fgCmd; + + /* <7> schedule the OID bit */ + set_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag); + + /* <8> Wake up tx thread to handle kick start the I/O request */ + wake_up_interruptible(&prGlueInfo->waitq); + + /* <9> Block and wait for event or timeout, current the timeout is 5 secs */ + /* if (wait_for_completion_interruptible_timeout(&prGlueInfo->rPendComp, 5 * KAL_HZ)) { */ + /* if (!wait_for_completion_interruptible(&prGlueInfo->rPendComp)) { */ + DBGLOG(OID, TEMP, "kalIoctl: before wait, caller: %p\n", __builtin_return_address(0)); + wait_for_completion(&prGlueInfo->rPendComp); { + /* Case 1: No timeout. */ + /* if return WLAN_STATUS_PENDING, the status of cmd is stored in prGlueInfo */ + if (prIoReq->rStatus == WLAN_STATUS_PENDING) + ret = prGlueInfo->rPendStatus; + else + ret = prIoReq->rStatus; + } +#if 0 + else { + /* Case 2: timeout */ + /* clear pending OID's cmd in CMD queue */ + if (fgCmd) { + prGlueInfo->u4TimeoutFlag = 1; + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + } + ret = WLAN_STATUS_FAILURE; + } +#endif + DBGLOG(OID, TEMP, "kalIoctl: done\n"); + up(&prGlueInfo->ioctl_sem); + kalHaltUnlock(); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending security frames +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear pending security frames +* belongs to dedicated network type +* +* \param prGlueInfo Pointer of GLUE Data Structure +* \param eNetworkTypeIdx Network Type Index +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending security frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME && prCmdInfo->eNetworkType == eNetworkTypeIdx) { + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending management frames +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear all pending management frames +* belongs to dedicated network type +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* Clear pending management frames in prGlueInfo->rCmdQueue */ + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + + if (prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME && + prCmdInfo->eNetworkType == eNetworkTypeIdx) { + wlanReleaseCommand(prGlueInfo->prAdapter, prCmdInfo); + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } else { + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + } + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} /* kalClearMgmtFramesByNetType */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief This function is a kernel thread function for handling command packets +* Tx requests and interrupt events +* +* @param data data pointer to private data of tx_thread +* +* @retval If the function succeeds, the return value is 0. +* Otherwise, an error code is returned. +* +*/ +/*----------------------------------------------------------------------------*/ + +int tx_thread(void *data) +{ + struct net_device *dev = data; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(dev)); + + P_QUE_ENTRY_T prQueueEntry = NULL; + P_GL_IO_REQ_T prIoReq = NULL; + P_QUE_T prTxQueue = NULL; + P_QUE_T prCmdQue = NULL; + + int ret = 0; + + BOOLEAN fgNeedHwAccess = FALSE; + + struct sk_buff *prSkb = NULL; + + /* for spin lock acquire and release */ + GLUE_SPIN_LOCK_DECLARATION(); + + prTxQueue = &prGlueInfo->rTxQueue; + prCmdQue = &prGlueInfo->rCmdQueue; + + current->flags |= PF_NOFREEZE; + + DBGLOG(INIT, INFO, "tx_thread starts running...\n"); + + while (TRUE) { + +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); +#endif + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); + DBGLOG(INIT, INFO, "tx_thread should stop now...\n"); + break; + } + + /* + * sleep on waitqueue if no events occurred. Event contain (1) GLUE_FLAG_INT + * (2) GLUE_FLAG_OID (3) GLUE_FLAG_TXREQ (4) GLUE_FLAG_HALT + * + */ + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); + + ret = wait_event_interruptible(prGlueInfo->waitq, (prGlueInfo->ulFlag != 0)); + + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); + +/* #if (CONF_HIF_LOOPBACK_AUTO == 1) */ +/* if (test_and_clear_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &prGlueInfo->u4Flag)) { */ +/* kalDevLoopbkAuto(prGlueInfo); */ +/* } */ +/* #endif */ /* CONF_HIF_LOOPBACK_AUTO */ + +#if CFG_DBG_GPIO_PINS + /* TX thread Wake up */ + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_LOW); +#endif +#if CFG_ENABLE_WIFI_DIRECT + /*run p2p multicast list work. */ + if (test_and_clear_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag)) + p2pSetMulticastListWorkQueueWrapper(prGlueInfo); + + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag)) { + p2pFuncUpdateMgmtFrameRegister(prGlueInfo->prAdapter, + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter); + } +#endif + if (test_and_clear_bit(GLUE_FLAG_FRAME_FILTER_AIS_BIT, &prGlueInfo->ulFlag)) { + P_AIS_FSM_INFO_T prAisFsmInfo = (P_AIS_FSM_INFO_T) NULL; + /* printk("prGlueInfo->u4OsMgmtFrameFilter = %x", prGlueInfo->u4OsMgmtFrameFilter); */ + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + prAisFsmInfo->u4AisPacketFilter = prGlueInfo->u4OsMgmtFrameFilter; + } + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &(prGlueInfo->prAdapter)->rTxThreadWakeLock); + DBGLOG(INIT, INFO, "<1>tx_thread should stop now...\n"); + break; + } + + fgNeedHwAccess = FALSE; + + /* Handle Interrupt */ + if (test_and_clear_bit(GLUE_FLAG_INT_BIT, &prGlueInfo->ulFlag)) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + + /* the Wi-Fi interrupt is already disabled in mmc thread, + so we set the flag only to enable the interrupt later */ + prGlueInfo->prAdapter->fgIsIntEnable = FALSE; + /* wlanISR(prGlueInfo->prAdapter, TRUE); */ + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + /* Should stop now... skip pending interrupt */ + DBGLOG(INIT, INFO, "ignore pending interrupt\n"); + } else { + prGlueInfo->TaskIsrCnt++; + wlanIST(prGlueInfo->prAdapter); + } + } + + /* transfer ioctl to OID request */ +#if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "<2>tx_thread should stop now...\n"); + break; + } +#endif + + do { + if (test_and_clear_bit(GLUE_FLAG_OID_BIT, &prGlueInfo->ulFlag)) { + /* get current prIoReq */ + prGlueInfo->u4OidCompleteFlag = 0; + + prIoReq = &(prGlueInfo->OidEntry); +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE && prIoReq->fgIsP2pOid == TRUE) { + /* if this Oid belongs to p2p and p2p module is removed + * do nothing, + */ + } else +#endif + { + if (FALSE == prIoReq->fgRead) { + prIoReq->rStatus = wlanSetInformation(prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } else { + prIoReq->rStatus = wlanQueryInformation(prIoReq->prAdapter, + prIoReq->pfnOidHandler, + prIoReq->pvInfoBuf, + prIoReq->u4InfoBufLen, + prIoReq->pu4QryInfoLen); + } + + if (prIoReq->rStatus != WLAN_STATUS_PENDING) { + DBGLOG(OID, TEMP, "tx_thread, complete\n"); + complete(&prGlueInfo->rPendComp); + } else { + wlanoidTimeoutCheck(prGlueInfo->prAdapter, prIoReq->pfnOidHandler); + } + } + } + + } while (FALSE); + + /* + * + * if TX request, clear the TXREQ flag. TXREQ set by kalSetEvent/GlueSetEvent + * indicates the following requests occur + * + */ +#if 0 + if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) { + DBGLOG(INIT, INFO, "<3>tx_thread should stop now...\n"); + break; + } +#endif + + if (test_and_clear_bit(GLUE_FLAG_TXREQ_BIT, &prGlueInfo->ulFlag)) { + /* Process Mailbox Messages */ + wlanProcessMboxMessage(prGlueInfo->prAdapter); + + /* Process CMD request */ + do { + if (prCmdQue->u4NumElem > 0) { + if (fgNeedHwAccess == FALSE) { + fgNeedHwAccess = TRUE; + + wlanAcquirePowerControl(prGlueInfo->prAdapter); + } + wlanProcessCommandQueue(prGlueInfo->prAdapter, prCmdQue); + } + } while (FALSE); + + /* Handle Packet Tx */ + { + while (QUEUE_IS_NOT_EMPTY(prTxQueue)) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQueue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + ASSERT(prQueueEntry); + if (NULL == prQueueEntry) + break; + + prSkb = (struct sk_buff *)GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + ASSERT(prSkb); + if (NULL == prSkb) { + DBGLOG(INIT, ERROR, "prSkb == NULL!\n"); + continue; + } +#if (CFG_SUPPORT_TDLS_DBG == 1) + UINT8 *pkt = prSkb->data; + UINT16 u2Identifier; + + if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) { + /* ip */ + u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19)); + DBGLOG(INIT, LOUD, " %d\n", u2Identifier); + } +#endif + if (wlanEnqueueTxPacket(prGlueInfo->prAdapter, + (P_NATIVE_PACKET) prSkb) == WLAN_STATUS_RESOURCES) { + /* no available entry in rFreeMsduInfoList */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_HEAD(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + break; + } + } + + if (wlanGetTxPendingFrameCount(prGlueInfo->prAdapter) > 0) { + /* send packets to HIF here */ + wlanTxPendingPackets(prGlueInfo->prAdapter, &fgNeedHwAccess); + } + } + + } + + /* Process RX, In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't need to free sk_buff by ourself */ + + /* In linux, we don't do reset */ + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); + + /* handle cnmTimer time out */ + if (test_and_clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag)) + wlanTimerTimeoutCheck(prGlueInfo->prAdapter); +#if CFG_DBG_GPIO_PINS + /* TX thread go to sleep */ + if (!prGlueInfo->ulFlag) + mtk_wcn_stp_debug_gpio_assert(IDX_TX_THREAD, DBG_TIE_HIGH); +#endif + } + +#if 0 + if (fgNeedHwAccess == TRUE) + wlanReleasePowerControl(prGlueInfo->prAdapter); +#endif + + /* exit while loop, tx thread is closed so we flush all pending packets */ + /* flush the pending TX packets */ + if (prGlueInfo->i4TxPendingFrameNum > 0) + kalFlushPendingTxPackets(prGlueInfo); + + /* flush pending security frames */ + if (prGlueInfo->i4TxPendingSecurityFrameNum > 0) + kalClearSecurityFrames(prGlueInfo); + + /* remove pending oid */ + wlanReleasePendingOid(prGlueInfo->prAdapter, 0); + + /* In linux, we don't need to free sk_buff by ourself */ + + DBGLOG(INIT, INFO, "mtk_sdiod stops\n"); + complete(&prGlueInfo->rHaltComp); + + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to check if card is removed +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval TRUE: card is removed +* FALSE: card is still attached +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsCardRemoved(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return FALSE; + /* Linux MMC doesn't have removal notification yet */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This routine is used to send command to firmware for overriding netweork address + * + * \param pvGlueInfo Pointer of GLUE Data Structure + + * \retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr) +{ + ASSERT(prGlueInfo); + + if (prGlueInfo->fgIsMacAddrOverride == FALSE) { +#if !defined(CONFIG_X86) +#if !defined(CONFIG_MTK_TC1_FEATURE) + UINT_32 i; +#endif + BOOLEAN fgIsReadError = FALSE; + +#if !defined(CONFIG_MTK_TC1_FEATURE) + for (i = 0; i < MAC_ADDR_LEN; i += 2) { + if (kalCfgDataRead16(prGlueInfo, + OFFSET_OF(WIFI_CFG_PARAM_STRUCT, aucMacAddress) + i, + (PUINT_16) (((PUINT_8) prMacAddr) + i)) == FALSE) { + fgIsReadError = TRUE; + break; + } + } +#else + TC1_FAC_NAME(FacReadWifiMacAddr) ((unsigned char *)prMacAddr); +#endif + + if (fgIsReadError == TRUE) + return FALSE; + else + return TRUE; +#else + /* x86 Linux doesn't need to override network address so far */ + return FALSE; +#endif + } else { + COPY_MAC_ADDR(prMacAddr, prGlueInfo->rMacAddrOverride); + + return TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to flush pending TX packets in glue layer +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prTxQue; + P_QUE_ENTRY_T prQueueEntry; + PVOID prPacket; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prTxQue = &(prGlueInfo->rTxQueue); + + if (prGlueInfo->i4TxPendingFrameNum) { + while (TRUE) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_REMOVE_HEAD(prTxQue, prQueueEntry, P_QUE_ENTRY_T); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + if (prQueueEntry == NULL) + break; + + prPacket = GLUE_GET_PKT_DESCRIPTOR(prQueueEntry); + + kalSendComplete(prGlueInfo, prPacket, WLAN_STATUS_NOT_ACCEPTED); + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is get indicated media state +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->eParamMediaStateIndicated; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to set indicated media state +* +* \param pvGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate) +{ + ASSERT(prGlueInfo); + + prGlueInfo->eParamMediaStateIndicated = eParamMediaStateIndicate; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to clear pending OID staying in command queue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + QUE_T rTempCmdQue; + P_QUE_T prTempCmdQue = &rTempCmdQue; + P_QUE_ENTRY_T prQueueEntry = (P_QUE_ENTRY_T) NULL; + P_CMD_INFO_T prCmdInfo = (P_CMD_INFO_T) NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + prCmdQue = &prGlueInfo->rCmdQueue; + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_MOVE_ALL(prTempCmdQue, prCmdQue); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + while (prQueueEntry) { + + if (((P_CMD_INFO_T) prQueueEntry)->fgIsOid) { + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + break; + } + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + + QUEUE_REMOVE_HEAD(prTempCmdQue, prQueueEntry, P_QUE_ENTRY_T); + } + + QUEUE_CONCATENATE_QUEUES(prCmdQue, prTempCmdQue); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + + if (prCmdInfo) { + if (prCmdInfo->pfCmdTimeoutHandler) + prCmdInfo->pfCmdTimeoutHandler(prGlueInfo->prAdapter, prCmdInfo); + else + kalOidComplete(prGlueInfo, prCmdInfo->fgSetQuery, 0, WLAN_STATUS_NOT_ACCEPTED); + + prGlueInfo->u4OidCompleteFlag = 1; + cmdBufFreeCmdInfo(prGlueInfo->prAdapter, prCmdInfo); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to insert command into prCmdQueue +* +* \param prGlueInfo Pointer of GLUE Data Structure +* prQueueEntry Pointer of queue entry to be inserted +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry) +{ + P_QUE_T prCmdQue; + P_CMD_INFO_T prCmdInfo; + P_MSDU_INFO_T prMsduInfo; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + ASSERT(prQueueEntry); + + prCmdQue = &prGlueInfo->rCmdQueue; + + prCmdInfo = (P_CMD_INFO_T) prQueueEntry; + if (prCmdInfo->prPacket && prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) { + prMsduInfo = (P_MSDU_INFO_T) (prCmdInfo->prPacket); + prMsduInfo->eCmdType = prCmdInfo->eCmdType; + prMsduInfo->ucCID = prCmdInfo->ucCID; + prMsduInfo->u4InqueTime = kalGetTimeTick(); + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); + QUEUE_INSERT_TAIL(prCmdQue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_CMD_QUE); +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Handle EVENT_ID_ASSOC_INFO event packet by indicating to OS with +* proper information +* +* @param pvGlueInfo Pointer of GLUE Data Structure +* @param prAssocInfo Pointer of EVENT_ID_ASSOC_INFO Packet +* +* @return none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo) +{ + /* to do */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to get firmware load address from registry +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4LoadAddress; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to get firmware start address from registry +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rRegInfo.u4StartAddress; +} + +/*----------------------------------------------------------------------------*/ +/*! + * * @brief Notify OS with SendComplete event of the specific packet. Linux should + * * free packets here. + * * + * * @param pvGlueInfo Pointer of GLUE Data Structure + * * @param pvPacket Pointer of Packet Handle + * * @param status Status Code for OS upper layer + * * + * * @return none + * */ +/*----------------------------------------------------------------------------*/ + +/* / Todo */ +VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus) +{ + ASSERT(pvPacket); + + dev_kfree_skb((struct sk_buff *)pvPacket); + if (prGlueInfo) + prGlueInfo->u8SkbFreed++; + GLUE_DEC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); +} + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return (UINT_32) (prGlueInfo->i4TxPendingFrameNum); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to retrieve the number of pending commands +* (including MMPDU, 802.1X and command packets) +* +* \param prGlueInfo Pointer of GLUE Data Structure +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo) +{ + P_QUE_T prCmdQue; + + ASSERT(prGlueInfo); + prCmdQue = &prGlueInfo->rCmdQueue; + + return prCmdQue->u4NumElem; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Timer Initialization Procedure +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* \param[in] prTimerHandler Pointer to timer handling function, whose only +* argument is "prAdapter" +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ + +/* static struct timer_list tickfn; */ + +VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler) +{ + + ASSERT(prGlueInfo); + + timer_setup(&(prGlueInfo->tickfn), prTimerHandler, 0); +} + +/* Todo */ +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the time to do the time out check. +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* \param[in] rInterval Time out interval from current time. +* +* \retval TRUE Success. +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval) +{ + ASSERT(prGlueInfo); + del_timer_sync(&(prGlueInfo->tickfn)); + + prGlueInfo->tickfn.expires = jiffies + u4Interval * HZ / MSEC_PER_SEC; + add_timer(&(prGlueInfo->tickfn)); + + return TRUE; /* success */ +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to cancel +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval TRUE : Timer has been canceled +* FALAE : Timer doens't exist +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + clear_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + + if (del_timer_sync(&(prGlueInfo->tickfn)) >= 0) + return TRUE; + else + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is a callback function for scanning done +* +* \param[in] prGlueInfo Pointer to GLUE Data Structure +* +* \retval none +* +*/ +/*----------------------------------------------------------------------------*/ +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status) +{ + P_AIS_FSM_INFO_T prAisFsmInfo; + + ASSERT(prGlueInfo); + + prAisFsmInfo = &(prGlueInfo->prAdapter->rWifiVar.rAisFsmInfo); + /* report all queued beacon/probe response frames to upper layer */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_INFRASTRUCTURE, NULL); + cnmTimerStopTimer(prGlueInfo->prAdapter, &prAisFsmInfo->rScanDoneTimer); + + /* check for system configuration for generating error message on scan list */ + wlanCheckSystemConfiguration(prGlueInfo->prAdapter); + + kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is used to generate a random number +* +* \param none +* +* \retval UINT_32 +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalRandomNumber(VOID) +{ + UINT_32 number = 0; + + get_random_bytes(&number, 4); + + return number; +} + +/*----------------------------------------------------------------------------*/ +/*! + * \brief command timeout call-back function + * + * \param[in] prGlueInfo Pointer to the GLUE data structure. + * + * \retval (none) + */ +/*----------------------------------------------------------------------------*/ +VOID kalTimeoutHandler(struct timer_list *t) +{ + + P_GLUE_INFO_T prGlueInfo = from_timer(prGlueInfo, t, tickfn); + + ASSERT(prGlueInfo); + + /* Notify tx thread for timeout event */ + set_bit(GLUE_FLAG_TIMEOUT_BIT, &prGlueInfo->ulFlag); + wake_up_interruptible(&prGlueInfo->waitq); + +} + +VOID kalSetEvent(P_GLUE_INFO_T pr) +{ + set_bit(GLUE_FLAG_TXREQ_BIT, &pr->ulFlag); + wake_up_interruptible(&pr->waitq); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if configuration file (NVRAM/Registry) exists +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo) +{ +#if !defined(CONFIG_X86) + ASSERT(prGlueInfo); + + return prGlueInfo->fgNvramAvailable; +#else + /* there is no configuration data for x86-linux */ + return FALSE; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Registry information +* +* \param[in] +* prGlueInfo +* +* \return +* Pointer of REG_INFO_T +*/ +/*----------------------------------------------------------------------------*/ +P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return &(prGlueInfo->rRegInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve version information of corresponding configuration file +* +* \param[in] +* prGlueInfo +* +* \param[out] +* pu2Part1CfgOwnVersion +* pu2Part1CfgPeerVersion +* pu2Part2CfgOwnVersion +* pu2Part2CfgPeerVersion +* +* \return +* NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion) +{ + ASSERT(prGlueInfo); + + ASSERT(pu2Part1CfgOwnVersion); + ASSERT(pu2Part1CfgPeerVersion); + ASSERT(pu2Part2CfgOwnVersion); + ASSERT(pu2Part2CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1OwnVersion), pu2Part1CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part1PeerVersion), pu2Part1CfgPeerVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2OwnVersion), pu2Part2CfgOwnVersion); + + kalCfgDataRead16(prGlueInfo, OFFSET_OF(WIFI_CFG_PARAM_STRUCT, u2Part2PeerVersion), pu2Part2CfgPeerVersion); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the WPS is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->fgWpsActive; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief update RSSI and LinkQuality to GLUE layer +* +* \param[in] +* prGlueInfo +* eNetTypeIdx +* cRssi +* cLinkQuality +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality) +{ + struct iw_statistics *pStats = (struct iw_statistics *)NULL; + + ASSERT(prGlueInfo); + + switch (eNetTypeIdx) { + case KAL_NETWORK_TYPE_AIS_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + break; +#if CFG_ENABLE_WIFI_DIRECT +#if CFG_SUPPORT_P2P_RSSI_QUERY + case KAL_NETWORK_TYPE_P2P_INDEX: + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + break; +#endif +#endif + default: + break; + + } + + if (pStats) { + pStats->qual.qual = cLinkQuality; + pStats->qual.noise = 0; + pStats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; + pStats->qual.level = 0x100 + cRssi; + pStats->qual.updated |= IW_QUAL_LEVEL_UPDATED; + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Pre-allocate I/O buffer +* +* \param[in] +* none +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(VOID) +{ + UINT_32 u4Size; + + if (CFG_COALESCING_BUFFER_SIZE >= CFG_RX_COALESCING_BUFFER_SIZE) + u4Size = CFG_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + else + u4Size = CFG_RX_COALESCING_BUFFER_SIZE + sizeof(ENHANCE_MODE_DATA_STRUCT_T); + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + pvDmaBuffer = dma_alloc_coherent(NULL, CFG_RX_MAX_PKT_SIZE, &pvDmaPhyBuf, GFP_KERNEL); + if (pvDmaBuffer == NULL) + return FALSE; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + pvIoBuffer = kmalloc(u4Size, GFP_KERNEL); +/* pvIoBuffer = dma_alloc_coherent(NULL, u4Size, &pvIoPhyBuf, GFP_KERNEL); */ + if (pvIoBuffer) { + pvIoBufferSize = u4Size; + pvIoBufferUsage = 0; + + return TRUE; + } + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free pre-allocated I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalUninitIOBuffer(VOID) +{ + kfree(pvIoBuffer); +#ifdef MTK_DMA_BUF_MEMCPY_SUP + dma_free_coherent(NULL, CFG_RX_MAX_PKT_SIZE, pvDmaBuffer, pvDmaPhyBuf); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + /* dma_free_coherent(NULL, pvIoBufferSize, pvIoBuffer, pvIoPhyBuf); */ + + pvIoBuffer = (PVOID) NULL; + pvIoBufferSize = 0; + pvIoBufferUsage = 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatch pre-allocated I/O buffer +* +* \param[in] +* u4AllocSize +* +* \return +* PVOID for pointer of pre-allocated I/O buffer +*/ +/*----------------------------------------------------------------------------*/ +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize) +{ + PVOID ret = (PVOID) NULL; + + if (pvIoBuffer) { + if (u4AllocSize <= (pvIoBufferSize - pvIoBufferUsage)) { + ret = (PVOID) &(((PUINT_8) (pvIoBuffer))[pvIoBufferUsage]); + pvIoBufferUsage += u4AllocSize; + } + } else { + /* fault tolerance */ + ret = (PVOID) kalMemAlloc(u4AllocSize, PHY_MEM_TYPE); + } + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Release all dispatched I/O buffer +* +* \param[in] +* none +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size) +{ + if (pvIoBuffer) { + pvIoBufferUsage -= u4Size; + } else { + /* fault tolerance */ + kalMemFree(pvAddr, PHY_MEM_TYPE, u4Size); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo) +{ +#if CFG_ENABLE_WIFI_DIRECT + if (IS_NET_ACTIVE(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX) && + p2pFuncIsAPMode(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo)) + return TRUE; +#endif + + return FALSE; +} + +#ifdef MTK_DMA_BUF_MEMCPY_SUP +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function gets the physical address for Pre-allocate I/O buffer. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[out] pu4Flags Pointer of a variable for saving IRQ flags +* +* \return physical addr +*/ +/*----------------------------------------------------------------------------*/ +ULONG kalIOPhyAddrGet(IN ULONG VirtAddr) +{ + ULONG PhyAddr; + + if ((VirtAddr >= (ULONG) pvIoBuffer) && (VirtAddr <= ((ULONG) (pvIoBuffer) + pvIoBufferSize))) { + PhyAddr = (ULONG) pvIoPhyBuf; + PhyAddr += (VirtAddr - (ULONG) (pvIoBuffer)); + return PhyAddr; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function gets the physical address for Pre-allocate I/O buffer. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] rLockCategory Specify which SPIN_LOCK +* \param[out] pu4Flags Pointer of a variable for saving IRQ flags +* +* \return physical addr +*/ +/*----------------------------------------------------------------------------*/ +VOID kalDmaBufGet(OUT VOID **VirtAddr, OUT VOID **PhyAddr) +{ + *VirtAddr = pvDmaBuffer; + *PhyAddr = pvDmaPhyBuf; +} +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/*! +* \brief to check if the MFP is active or not +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->rWpaInfo.u4Mfp; +} +#endif + +struct file *kalFileOpen(const char *path, int flags, int rights) +{ + struct file *filp = NULL; + mm_segment_t oldfs; + int err = 0; + + oldfs = get_fs(); + set_fs(get_ds()); + filp = filp_open(path, flags, rights); + set_fs(oldfs); + if (IS_ERR(filp)) { + err = PTR_ERR(filp); + return NULL; + } + return filp; +} + +VOID kalFileClose(struct file *file) +{ + filp_close(file, NULL); +} + +UINT_32 kalFileRead(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) +{ + mm_segment_t oldfs; + INT_32 ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_read(file, data, size, &offset); + + set_fs(oldfs); + return ret; +} + +UINT_32 kalFileWrite(struct file *file, UINT_64 offset, UINT_8 *data, UINT_32 size) +{ + mm_segment_t oldfs; + INT_32 ret; + + oldfs = get_fs(); + set_fs(get_ds()); + + ret = vfs_write(file, data, size, &offset); + + set_fs(oldfs); + return ret; +} + +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size) +{ + struct file *file = NULL; + UINT_32 ret = -1; + UINT_32 u4Flags = 0; + + if (fgDoAppend) + u4Flags = O_APPEND; + + file = kalFileOpen(pucPath, O_WRONLY | O_CREAT | u4Flags, S_IRWXU); + if (file) { + ret = kalFileWrite(file, 0, pucData, u4Size); + kalFileClose(file); + } + + return ret; +} + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize) +{ + struct file *file = NULL; + INT_32 ret = -1; + UINT_32 u4ReadSize = 0; + + DBGLOG(INIT, LOUD, "kalReadToFile() path %s\n", pucPath); + + file = kalFileOpen(pucPath, O_RDONLY, 0); + + if ((file != NULL) && !IS_ERR(file)) { + u4ReadSize = kalFileRead(file, 0, pucData, u4Size); + kalFileClose(file); + if (pu4ReadSize) + *pu4ReadSize = u4ReadSize; + ret = 0; + } + return ret; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate BSS-INFO to NL80211 as scanning result +* +* \param[in] +* prGlueInfo +* pucBeaconProbeResp +* u4FrameLen +* +* +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucBeaconProbeResp, + IN UINT_32 u4FrameLen, IN UINT_8 ucChannelNum, IN INT_32 i4SignalStrength) +{ + struct wiphy *wiphy; + struct ieee80211_channel *prChannel = NULL; + + ASSERT(prGlueInfo); + wiphy = priv_to_wiphy(prGlueInfo); + + /* search through channel entries */ + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(wiphy, ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); + } + + if (prChannel != NULL && (prGlueInfo->prScanRequest != NULL || prGlueInfo->prSchedScanRequest != NULL)) { + struct cfg80211_bss *bss; +#if CFG_SUPPORT_TSF_USING_BOOTTIME + struct ieee80211_mgmt *prMgmtFrame = (struct ieee80211_mgmt *)pucBeaconProbeResp; + + prMgmtFrame->u.beacon.timestamp = kalGetBootTime(); +#endif + ScanCnt++; + + /* indicate to NL80211 subsystem */ + bss = cfg80211_inform_bss_frame(wiphy, + prChannel, + (struct ieee80211_mgmt *)pucBeaconProbeResp, + u4FrameLen, i4SignalStrength * 100, GFP_KERNEL); + + if (!bss) { + ScanDoneFailCnt++; + DBGLOG(SCN, WARN, "inform bss to cfg80211 failed, bss channel %d, rcpi %d\n", + ucChannelNum, i4SignalStrength); + } else { + cfg80211_put_bss(wiphy, bss); + DBGLOG(SCN, TRACE, "inform bss to cfg80211, bss channel %d, rcpi %d\n", + ucChannelNum, i4SignalStrength); + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel ready +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + /* ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); */ + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_ready_on_channel(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, u4DurationMs, + GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate channel expiration +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum) +{ + struct ieee80211_channel *prChannel = NULL; + enum nl80211_channel_type rChannelType; + + ucChannelNum = wlanGetChannelNumberByNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_AIS_INDEX); + + if (prGlueInfo->fgIsRegistered == TRUE) { + if (ucChannelNum <= 14) { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_2GHZ)); + } else { + prChannel = + ieee80211_get_channel(priv_to_wiphy(prGlueInfo), + ieee80211_channel_to_frequency(ucChannelNum, NL80211_BAND_5GHZ)); + } + + switch (eSco) { + case CHNL_EXT_SCN: + rChannelType = NL80211_CHAN_NO_HT; + break; + + case CHNL_EXT_SCA: + rChannelType = NL80211_CHAN_HT40MINUS; + break; + + case CHNL_EXT_SCB: + rChannelType = NL80211_CHAN_HT40PLUS; + break; + + case CHNL_EXT_RES: + default: + rChannelType = NL80211_CHAN_HT20; + break; + } + + cfg80211_remain_on_channel_expired(prGlueInfo->prDevHandler->ieee80211_ptr, u8Cookie, prChannel, + GFP_KERNEL); + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate Mgmt tx status +* +* \param[in] +* prGlueInfo +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { + DBGLOG(AIS, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + cfg80211_mgmt_tx_status(prGlueInfo->prDevHandler->ieee80211_ptr, + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + } while (FALSE); + +} /* kalIndicateMgmtTxStatus */ + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ +#define DBG_MGMT_FRAME_INDICATION 1 + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; +#if DBG_MGMT_FRAME_INDICATION + P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; +#endif + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; + +#if DBG_MGMT_FRAME_INDICATION + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + + switch (prWlanHeader->u2FrameCtrl) { + case MAC_FRAME_PROBE_REQ: + DBGLOG(AIS, TRACE, "RX Probe Req at channel %d ", ucChnlNum); + break; + case MAC_FRAME_PROBE_RSP: + DBGLOG(AIS, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); + break; + case MAC_FRAME_ACTION: + DBGLOG(AIS, TRACE, "RX Action frame at channel %d ", ucChnlNum); + break; + default: + DBGLOG(AIS, TRACE, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); + break; + } + +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + cfg80211_rx_mgmt(prGlueInfo->prDevHandler->ieee80211_ptr, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_KERNEL); + } while (FALSE); + +} /* kalIndicateRxMgmtFrame */ + +#if CFG_SUPPORT_AGPS_ASSIST +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen) +{ + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + struct sk_buff *skb = cfg80211_testmode_alloc_event_skb(priv_to_wiphy(prGlueInfo), + dataLen, GFP_KERNEL); + if (!skb) { + DBGLOG(AIS, ERROR, "kalIndicateAgpsNotify: alloc skb failed\n"); + return FALSE; + } + + /* DBGLOG(CCX, INFO, ("WLAN_STATUS_AGPS_NOTIFY, cmd=%d\n", cmd)); */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_CMD, sizeof(cmd), &cmd) < 0)) + goto nla_put_failure; + if (dataLen > 0 && data && unlikely(nla_put(skb, MTK_ATTR_AGPS_DATA, dataLen, data) < 0)) + goto nla_put_failure; + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFINDEX, sizeof(UINT_32), &prGlueInfo->prDevHandler->ifindex) < 0)) + goto nla_put_failure; + /* currently, the ifname maybe wlan0, p2p0, so the maximum name length will be 5 bytes */ + if (unlikely(nla_put(skb, MTK_ATTR_AGPS_IFNAME, 5, prGlueInfo->prDevHandler->name) < 0)) + goto nla_put_failure; + cfg80211_testmode_event(skb, GFP_KERNEL); + return TRUE; + +nla_put_failure: + kfree_skb(skb); + return FALSE; +} +#endif + +#if (CFG_SUPPORT_MET_PROFILING == 1) +#define PROC_MET_PROF_CTRL "met_ctrl" +#define PROC_MET_PROF_PORT "met_port" + +struct proc_dir_entry *pMetProcDir; +void *pMetGlobalData = NULL; +static unsigned long __read_mostly tracing_mark_write_addr; + +static inline void __mt_update_tracing_mark_write_addr(void) +{ + if (unlikely(0 == tracing_mark_write_addr)) + tracing_mark_write_addr = kallsyms_lookup_name("tracing_mark_write"); +} + +VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb) +{ + UINT_8 ucIpVersion; + UINT_16 u2UdpSrcPort; + UINT_16 u2RtpSn; + PUINT_8 pucEthHdr = prSkb->data; + PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; + + /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ + /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ + /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ + /* printk("MET_PROF: MET enable=%d(HardXmit)\n", prGlueInfo->u8MetProfEnable); */ + if (prGlueInfo->u8MetProfEnable == 1) { + u2UdpSrcPort = prGlueInfo->u16MetUdpPort; + if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { + /* IP */ + pucIpHdr = pucEthHdr + ETH_HLEN; + ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { + /* UDP */ + pucUdpHdr = pucIpHdr + IP_HEADER_LEN; + /* check UDP port number */ + if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { + /* RTP */ + pucRtpHdr = pucUdpHdr + 8; + u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; + /* trace_printk("S|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); + //frm_sequence); */ +#ifdef CONFIG_TRACING + __mt_update_tracing_mark_write_addr(); + if (tracing_mark_write_addr != 0) { + event_trace_printk(tracing_mark_write_addr, "S|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", u2RtpSn); + } +#endif + } + } + } + } +} + +VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo) +{ + UINT_8 ucIpVersion; + UINT_16 u2UdpSrcPort; + UINT_16 u2RtpSn; + struct sk_buff *prSkb = (struct sk_buff *)prMsduInfo->prPacket; + PUINT_8 pucEthHdr = prSkb->data; + PUINT_8 pucIpHdr, pucUdpHdr, pucRtpHdr; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + /* | Ethernet(14) | IP(20) | UDP(8)| RTP(12) | */ + /* UDP==> |SRC_PORT(2)|DST_PORT(2)|LEN(2)|CHKSUM(2)| */ + /* RTP==> |CTRL(2)|SEQ(2)|TimeStamp(4)|... */ + /* printk("MET_PROF: MET enable=%d(TxMsdu)\n", prGlueInfo->u8MetProfEnable); */ + if (prGlueInfo->u8MetProfEnable == 1) { + u2UdpSrcPort = prGlueInfo->u16MetUdpPort; + if ((*(pucEthHdr + 12) == 0x08) && (*(pucEthHdr + 13) == 0x00)) { + /* IP */ + pucIpHdr = pucEthHdr + ETH_HLEN; + ucIpVersion = (*pucIpHdr & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET; + if ((ucIpVersion == IPVERSION) && (pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP)) { + /* UDP */ + pucUdpHdr = pucIpHdr + IP_HEADER_LEN; + /* check UDP port number */ + if (((UINT_16) pucUdpHdr[0] << 8 | (UINT_16) pucUdpHdr[1]) == u2UdpSrcPort) { + /* RTP */ + pucRtpHdr = pucUdpHdr + 8; + u2RtpSn = (UINT_16) pucRtpHdr[2] << 8 | pucRtpHdr[3]; + /* trace_printk("F|%d|%s|%d\n", current->tgid, "WIFI-CHIP", u2RtpSn); + //frm_sequence); */ +#ifdef CONFIG_TRACING + __mt_update_tracing_mark_write_addr(); + if (tracing_mark_write_addr != 0) { + event_trace_printk(tracing_mark_write_addr, "F|%d|%s|%d\n", + current->tgid, "WIFI-CHIP", u2RtpSn); + } +#endif + } + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for adjusting Debug Level to turn on/off debugging message. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t kalMetCtrlWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u8MetProfEnable; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, u4CopySize)) + return -1; + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u8MetProfEnable) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC Enable=%d\n", u8MetProfEnable); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u8MetProfEnable = (UINT_8) u8MetProfEnable; + } + return count; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for adjusting Debug Level to turn on/off debugging message. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static ssize_t kalMetPortWriteProcfs(struct file *file, const char __user *buffer, size_t count, loff_t *off) +{ + char acBuf[128 + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + int u16MetUdpPort; + + IN P_GLUE_INFO_T prGlueInfo; + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, u4CopySize)) + return -1; + acBuf[u4CopySize] = '\0'; + + if (sscanf(acBuf, " %d", &u16MetUdpPort) == 1) + DBGLOG(INIT, INFO, "MET_PROF: Write MET PROC UDP_PORT=%d\n", u16MetUdpPort); + if (pMetGlobalData != NULL) { + prGlueInfo = (P_GLUE_INFO_T) pMetGlobalData; + prGlueInfo->u16MetUdpPort = (UINT_16) u16MetUdpPort; + } + return count; +} + +const struct file_operations rMetProcCtrlFops = { +.write = kalMetCtrlWriteProcfs +}; + +const struct file_operations rMetProcPortFops = { +.write = kalMetPortWriteProcfs +}; + +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo) +{ + /* struct proc_dir_entry *pMetProcDir; */ + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, INFO, "init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + /* + * Directory: Root (/proc/net/wlan0) + */ + pMetProcDir = proc_mkdir("wlan0", init_net.proc_net); + if (pMetProcDir == NULL) + return -ENOENT; + /* + /proc/net/wlan0 + |-- met_ctrl (PROC_MET_PROF_CTRL) + |-- met_port (PROC_MET_PROF_PORT) + */ + /* proc_create(PROC_MET_PROF_CTRL, 0x0644, pMetProcDir, &rMetProcFops); */ + proc_create(PROC_MET_PROF_CTRL, 0, pMetProcDir, &rMetProcCtrlFops); + proc_create(PROC_MET_PROF_PORT, 0, pMetProcDir, &rMetProcPortFops); + + pMetGlobalData = (void *)prGlueInfo; + + return 0; +} + +int kalMetRemoveProcfs(void) +{ + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + DBGLOG(INIT, WARN, "remove proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + remove_proc_entry(PROC_MET_PROF_CTRL, pMetProcDir); + remove_proc_entry(PROC_MET_PROF_PORT, pMetProcDir); + /* remove root directory (proc/net/wlan0) */ + remove_proc_entry("wlan0", init_net.proc_net); + /* clear MetGlobalData */ + pMetGlobalData = NULL; + + return 0; +} +#endif +UINT_64 kalGetBootTime(void) +{ + struct timespec ts; + UINT_64 bootTime = 0; + + get_monotonic_boottime(&ts); + /* we assign ts.tv_sec to bootTime first, then multiply USEC_PER_SEC + this will prevent multiply result turn to a negative value on 32bit system */ + bootTime = ts.tv_sec; + bootTime *= USEC_PER_SEC; + bootTime += ts.tv_nsec / NSEC_PER_USEC; + return bootTime; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan results are avilable +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + cfg80211_sched_scan_results(priv_to_wiphy(prGlueInfo),0); + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To indicate scheduled scan has been stopped +* +* \param[in] +* prGlueInfo +* +* \return +* None +*/ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo) +{ + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prGlueInfo); + + /* 1. reset first for newly incoming request */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prSchedScanRequest != NULL) + prGlueInfo->prSchedScanRequest = NULL; + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + DBGLOG(SCN, INFO, "cfg80211_sched_scan_stopped send event\n"); + + /* 2. indication to cfg80211 */ + /* 20150205 change cfg80211_sched_scan_stopped to work queue to use K thread to send event instead of Tx thread + due to sched_scan_mtx dead lock issue by Tx thread serves oid cmds and send event in the same time */ + DBGLOG(SCN, TRACE, "start work queue to send event\n"); + schedule_delayed_work(&sched_workq, 0); + DBGLOG(SCN, TRACE, "tx_thread return from kalSchedScanStoppped\n"); + +} + +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +/* if SPM is not implement this function, we will use this default one */ +wake_reason_t __weak slp_get_wake_reason(VOID) +{ + return WR_NONE; +} +/* if SPM is not implement this function, we will use this default one */ +UINT_32 __weak spm_get_last_wakeup_src(VOID) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To check if device if wake up by wlan +* +* \param[in] +* prAdapter +* +* \return +* TRUE: wake up by wlan; otherwise, FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter) +{ + /* SUSPEND_FLAG_FOR_WAKEUP_REASON is set means system has suspended, but may be failed + duo to some driver suspend failed. so we need help of function slp_get_wake_reason */ + if (test_and_clear_bit(SUSPEND_FLAG_FOR_WAKEUP_REASON, &prAdapter->ulSuspendFlag) == 0) + return FALSE; + /* if slp_get_wake_reason or spm_get_last_wakeup_src is NULL, it means SPM module didn't implement + it. then we should return FALSE always. otherwise, if slp_get_wake_reason returns WR_WAKE_SRC, + then it means the host is suspend successfully. */ + if (slp_get_wake_reason() != WR_WAKE_SRC) + return FALSE; + /* spm_get_last_wakeup_src will returns the last wakeup source, + WAKE_SRC_CONN2AP is connsys */ + return !!(spm_get_last_wakeup_src() & WAKE_SRC_CONN2AP); +} +#endif + +INT_32 kalHaltLock(UINT_32 waitMs) +{ + INT_32 i4Ret = 0; + + if (waitMs) { + i4Ret = down_timeout(&rHaltCtrl.lock, MSEC_TO_JIFFIES(waitMs)); + if (!i4Ret) + goto success; + if (i4Ret != -ETIME) + return i4Ret; + if (rHaltCtrl.fgHeldByKalIoctl) { + P_GLUE_INFO_T prGlueInfo = NULL; + + wlanExportGlueInfo(&prGlueInfo); + + DBGLOG(INIT, ERROR, + "kalIoctl was executed longer than %u ms, show backtrace of tx_thread!\n", + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + if (prGlueInfo) + show_stack(prGlueInfo->main_thread, NULL); + } else { + DBGLOG(INIT, ERROR, "halt lock held by %s pid %d longer than %u ms!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid, + kalGetTimeTick() - rHaltCtrl.u4HoldStart); + show_stack(rHaltCtrl.owner, NULL); + } + return i4Ret; + } + down(&rHaltCtrl.lock); +success: + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +INT_32 kalHaltTryLock(VOID) +{ + INT_32 i4Ret = 0; + + i4Ret = down_trylock(&rHaltCtrl.lock); + if (i4Ret) + return i4Ret; + rHaltCtrl.owner = current; + rHaltCtrl.u4HoldStart = kalGetTimeTick(); + return 0; +} + +VOID kalHaltUnlock(VOID) +{ + if (kalGetTimeTick() - rHaltCtrl.u4HoldStart > WLAN_OID_TIMEOUT_THRESHOLD * 2 && + rHaltCtrl.owner) + DBGLOG(INIT, ERROR, "process %s pid %d hold halt lock longer than 4s!\n", + rHaltCtrl.owner->comm, rHaltCtrl.owner->pid); + rHaltCtrl.owner = NULL; + up(&rHaltCtrl.lock); +} + +VOID kalSetHalted(BOOLEAN fgHalt) +{ + rHaltCtrl.fgHalt = fgHalt; +} + +BOOLEAN kalIsHalted(VOID) +{ + return rHaltCtrl.fgHalt; +} +VOID kalPerMonDump(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, WARN, "ulPerfMonFlag:0x%lx\n", prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "ulLastTxBytes:%ld\n", prPerMonitor->ulLastTxBytes); + DBGLOG(SW4, WARN, "ulLastRxBytes:%ld\n", prPerMonitor->ulLastRxBytes); + DBGLOG(SW4, WARN, "ulP2PLastTxBytes:%ld\n", prPerMonitor->ulP2PLastTxBytes); + DBGLOG(SW4, WARN, "ulP2PLastRxBytes:%ld\n", prPerMonitor->ulP2PLastRxBytes); + DBGLOG(SW4, WARN, "ulThroughput:%ld\n", prPerMonitor->ulThroughput); + DBGLOG(SW4, WARN, "u4UpdatePeriod:%d\n", prPerMonitor->u4UpdatePeriod); + DBGLOG(SW4, WARN, "u4TarPerfLevel:%d\n", prPerMonitor->u4TarPerfLevel); + DBGLOG(SW4, WARN, "u4CurrPerfLevel:%d\n", prPerMonitor->u4CurrPerfLevel); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.tx_bytes); + DBGLOG(SW4, WARN, "netStats tx_bytes:%ld\n", prGlueInfo->rNetDevStats.rx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes); + DBGLOG(SW4, WARN, "p2p netStats tx_bytes:%ld\n", prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes); +} + +inline INT32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, INFO, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) + DBGLOG(SW4, WARN, "abnormal, perf monitory already running\n"); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); + KAL_SET_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); + prPerMonitor->u4UpdatePeriod = 1000; + cnmTimerInitTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + (PFN_MGMT_TIMEOUT_FUNC) kalPerMonHandler, (ULONG) NULL); + DBGLOG(SW4, INFO, "exit %s\n", __func__); + return 0; +} + +inline INT32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "need to stop before disable\n"); + kalPerMonStop(prGlueInfo); + } + KAL_SET_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + + DBGLOG(SW4, INFO, "enter %s\n", __func__); + KAL_CLR_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) + return 0; + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitor already running\n"); + return 0; + } + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + KAL_SET_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); + KAL_CLR_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, INFO, "perf monitor started\n"); + return 0; +} + +inline INT32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo) +{ + struct GL_PER_MON_T *prPerMonitor; + + prPerMonitor = &prGlueInfo->prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter %s\n", __func__); + + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory disabled\n"); + return 0; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + DBGLOG(SW4, TRACE, "perf monitory already stopped\n"); + return 0; + } + + KAL_SET_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag); + if (KAL_TEST_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + cnmTimerStopTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer); + KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); + prPerMonitor->ulLastRxBytes = 0; + prPerMonitor->ulLastTxBytes = 0; + prPerMonitor->ulP2PLastRxBytes = 0; + prPerMonitor->ulP2PLastTxBytes = 0; + prPerMonitor->ulThroughput = 0; + prPerMonitor->u4CurrPerfLevel = 0; + prPerMonitor->u4TarPerfLevel = 0; + /*Cancel CPU performance mode request*/ + kalBoostCpu(0); + } + DBGLOG(SW4, TRACE, "exit %s\n", __func__); + return 0; +} + +inline INT32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo) +{ + kalPerMonDisable(prGlueInfo); + return 0; +} + +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam) +{ + /*Calculate current throughput*/ + struct GL_PER_MON_T *prPerMonitor; + + LONG latestTxBytes, latestRxBytes, txDiffBytes, rxDiffBytes; + LONG p2pLatestTxBytes, p2pLatestRxBytes, p2pTxDiffBytes, p2pRxDiffBytes; + P_GLUE_INFO_T prGlueInfo = prAdapter->prGlueInfo; + + if ((prGlueInfo->ulFlag & GLUE_FLAG_HALT) || (!prAdapter->fgIsP2PRegistered)) + return; + + prPerMonitor = &prAdapter->rPerMonitor; + DBGLOG(SW4, TRACE, "enter kalPerMonHandler\n"); + if (KAL_TEST_BIT(PERF_MON_DISABLE_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "perf monitory disabled, omit timeout event\n"); + return; + } + + if (KAL_TEST_BIT(PERF_MON_STOP_BIT_OFF, prPerMonitor->ulPerfMonFlag)) { + KAL_CLR_BIT(PERF_MON_RUNNING_BIT_OFF, prPerMonitor->ulPerfMonFlag); + DBGLOG(SW4, WARN, "perf monitory stopped, omit timeout event\n"); + return; + } + latestTxBytes = prGlueInfo->rNetDevStats.tx_bytes; + latestRxBytes = prGlueInfo->rNetDevStats.rx_bytes; + p2pLatestTxBytes = prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes; + p2pLatestRxBytes = prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes; + if (0 == prPerMonitor->ulLastRxBytes && + 0 == prPerMonitor->ulLastTxBytes && + 0 == prPerMonitor->ulP2PLastRxBytes && + 0 == prPerMonitor->ulP2PLastTxBytes) { + prPerMonitor->ulThroughput = 0; + } else { + txDiffBytes = latestTxBytes - prPerMonitor->ulLastTxBytes; + rxDiffBytes = latestRxBytes - prPerMonitor->ulLastRxBytes; + if (0 > txDiffBytes) + txDiffBytes = -(txDiffBytes); + if (0 > rxDiffBytes) + rxDiffBytes = -(rxDiffBytes); + + p2pTxDiffBytes = p2pLatestTxBytes - prPerMonitor->ulP2PLastTxBytes; + p2pRxDiffBytes = p2pLatestRxBytes - prPerMonitor->ulP2PLastRxBytes; + if (0 > p2pTxDiffBytes) + p2pTxDiffBytes = -(p2pTxDiffBytes); + if (0 > p2pRxDiffBytes) + p2pRxDiffBytes = -(p2pRxDiffBytes); + + prPerMonitor->ulThroughput = txDiffBytes + rxDiffBytes + p2pTxDiffBytes + p2pRxDiffBytes; + prPerMonitor->ulThroughput *= 1000; + prPerMonitor->ulThroughput /= prPerMonitor->u4UpdatePeriod; + prPerMonitor->ulThroughput <<= 3; + } + /*start the timer again to make sure we can cancel performance mode request in the end*/ + cnmTimerStartTimer(prGlueInfo->prAdapter, &prPerMonitor->rPerfMonTimer, prPerMonitor->u4UpdatePeriod); + + prPerMonitor->ulLastTxBytes = latestTxBytes; + prPerMonitor->ulLastRxBytes = latestRxBytes; + prPerMonitor->ulP2PLastTxBytes = p2pLatestTxBytes; + prPerMonitor->ulP2PLastRxBytes = p2pLatestRxBytes; + + if (prPerMonitor->ulThroughput < THROUGHPUT_L1_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 0; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L2_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 1; + else if (prPerMonitor->ulThroughput < THROUGHPUT_L3_THRESHOLD) + prPerMonitor->u4TarPerfLevel = 2; + else + prPerMonitor->u4TarPerfLevel = 3; + if (prPerMonitor->u4TarPerfLevel != prPerMonitor->u4CurrPerfLevel) { + if (0 == prPerMonitor->u4TarPerfLevel) { + /*cancel CPU performance mode request*/ + kalPerMonStop(prGlueInfo); + } else{ + DBGLOG(SW4, TRACE, "throughput:%ld bps\n", prPerMonitor->ulThroughput); + /*adjust CPU core number to prPerMonitor->u4TarPerfLevel+1*/ + kalBoostCpu(prPerMonitor->u4TarPerfLevel+1); + /*start the timer again to make sure we can cancel performance mode request in the end*/ + cnmTimerStartTimer(prGlueInfo->prAdapter, + &prPerMonitor->rPerfMonTimer, + prPerMonitor->u4UpdatePeriod); + } + } + prPerMonitor->u4CurrPerfLevel = prPerMonitor->u4TarPerfLevel; + DBGLOG(SW4, TRACE, "exit kalPerMonHandler\n"); +} + +INT32 __weak kalBoostCpu(UINT_32 core_num) +{ + DBGLOG(SW4, WARN, "enter weak kalBoostCpu, core_num:%d\n", core_num); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c new file mode 100644 index 0000000000000..2d96315389429 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p.c @@ -0,0 +1,4671 @@ +/* +** Id: @(#) gl_p2p.c@@ +*/ + +/*! \file gl_p2p.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_p2p.c +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 17 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** FPB from ALPS.JB to phase 2 release. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 01 09 2012 terry.wu + * [WCXRP00001166] [Wi-Fi] [Driver] cfg80211 integration for p2p newtork + * cfg80211 integration for p2p network. + * + * 12 19 2011 terry.wu + * [WCXRP00001142] [Wi-Fi] [P2P Driver] XOR local admin bit to generate p2p net device MAC + * XOR local administrated bit to generate net device MAC of p2p network. + * + * 12 02 2011 yuche.tsai + * NULL + * Fix possible KE when unload p2p. + * + * 11 24 2011 yuche.tsai + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 16 2011 yuche.tsai + * [WCXRP00001107] [Volunteer Patch][Driver] Large Network Type index assert in FW issue. + * Avoid using work thread in set p2p multicast address callback. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix default device name issue. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service + * discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 11 07 2011 yuche.tsai + * NULL + * [ALPS 00087243] KE in worker thread. + * The multicast address list is scheduled in worker thread. + * Before the worker thread is excuted, if P2P is unloaded, a KE may occur. + * + * 10 26 2011 terry.wu + * [WCXRP00001066] [MT6620 Wi-Fi] [P2P Driver] Fix P2P Oid Issue + * Fix some P2P OID functions didn't raise its flag "fgIsP2pOid" issue. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * . + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * Support Channel Query. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 26 2011 yuche.tsai + * NULL + * Fix bug of parsing secondary device list type issue. + * + * 08 24 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Abort. + * + * 08 23 2011 yuche.tsai + * NULL + * Fix multicast address list issue of P2P. + * + * 08 22 2011 chinglan.wang + * NULL + * Fix invitation indication bug.. + * + * 08 16 2011 cp.wu + * [WCXRP00000934] [MT6620 Wi-Fi][Driver][P2P] Wi-Fi hot spot with auto sparse channel residence + * auto channel decision for 2.4GHz hot spot mode + * + * 08 16 2011 chinglan.wang + * NULL + * Add the group id information in the invitation indication. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 08 05 2011 yuche.tsai + * [WCXRP00000856] [Volunteer Patch][WiFi Direct][Driver] MT6620 WiFi Direct IOT Issue with BCM solution. + * Add Password ID check for quick connection. + * Also modify some connection policy. + * + * 07 18 2011 chinglan.wang + * NULL + * Add IOC_P2P_GO_WSC_IE (p2p capability). + * + * 06 14 2011 yuche.tsai + * NULL + * Add compile flag to disable persistent group support. + * + * 05 04 2011 chinglan.wang + * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver + * . + * + * 05 02 2011 yuche.tsai + * [WCXRP00000693] [Volunteer Patch][MT6620][Driver] Clear Formation Flag after TX lifetime timeout. + * Clear formation flag after formation timeout. + * + * 04 22 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * . + * + * 04 21 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * 1. Revise P2P power mode setting. + * 2. Revise fast-PS for concurrent + * + * 04 19 2011 wh.su + * NULL + * Adding length check before doing WPA RSN IE parsing for scan results indicate. + * + * 04 14 2011 yuche.tsai + * [WCXRP00000646] [Volunteer Patch][MT6620][FW/Driver] Sigma Test Modification for some test case. + * Connection flow refine for Sigma test. + * + * 04 08 2011 yuche.tsai + * [WCXRP00000624] [Volunteer Patch][MT6620][Driver] Add device discoverability support for GO. + * Add device discoverability support. + * + * 04 08 2011 george.huang + * [WCXRP00000621] [MT6620 Wi-Fi][Driver] Support P2P supplicant to set power mode + * separate settings of P2P and AIS + * + * 04 07 2011 terry.wu + * [WCXRP00000619] [MT6620 Wi-Fi][Driver] fix kernel panic may occur when removing wlan + * Fix kernel panic may occur when removing wlan driver. + * + * 03 31 2011 wh.su + * [WCXRP00000614] [MT6620 Wi-Fi][Driver] P2P: Update beacon content while setting WSC IE + * Update the wsc ie to beacon content. + * + * 03 25 2011 wh.su + * NULL + * add the sample code for set power mode and get power mode. + * + * 03 25 2011 yuche.tsai + * NULL + * Improve some error handleing. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 22 2011 yuche.tsai + * [WCXRP00000584] [Volunteer Patch][MT6620][Driver] Add beacon timeout support for WiFi Direct. + * Modify formation policy. + * + * 03 22 2011 yuche.tsai + * NULL + * Modify formation policy setting. + * + * 03 18 2011 yuche.tsai + * [WCXRP00000574] [Volunteer Patch][MT6620][Driver] Modify P2P FSM Connection Flow + * Modify connection flow after Group Formation Complete, or device connect to a GO. + * Instead of request channel & connect directly, we use scan to allocate channel bandwidth & connect after RX BCN. + * + * 03 15 2011 wh.su + * [WCXRP00000563] [MT6620 Wi-Fi] [P2P] Set local config method while set password Id ready + * set lccal config method method while set password Id ready. + * + * 03 15 2011 yuche.tsai + * [WCXRP00000560] [Volunteer Patch][MT6620][Driver] P2P Connection from UI using KEY/DISPLAY issue + * Fix some configure method issue. + * + * 03 15 2011 jeffrey.chang + * [WCXRP00000558] [MT6620 Wi-Fi][MT6620 Wi-Fi][Driver] refine the queue selection algorithm for WMM + * refine queue_select function + * + * 03 13 2011 wh.su + * [WCXRP00000530] [MT6620 Wi-Fi] [Driver] skip doing p2pRunEventAAAComplete after send assoc response Tx Done + * add code for avoid compiling warning. + * + * 03 10 2011 yuche.tsai + * NULL + * Add P2P API. + * + * 03 10 2011 terry.wu + * [WCXRP00000505] [MT6620 Wi-Fi][Driver/FW] WiFi Direct Integration + * Remove unnecessary assert and message. + * + * 03 08 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * support the power save related p2p setting. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify P2P's netdevice functions to support multiple H/W queues + * + * 03 03 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * for get request, the buffer length to be copied is header + payload. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add code to let the beacon and probe response for Auto GO WSC . + * + * 03 02 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * add a missed break. + * + * 03 01 2011 yuche.tsai + * [WCXRP00000501] [Volunteer Patch][MT6620][Driver] No common channel issue when doing GO formation + * Update channel issue when doing GO formation.. + * + * 02 25 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * add the Operation channel setting. + * + * 02 23 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * fixed the set int ioctl set index and value map to driver issue. + * + * 02 22 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int from supplicant, and can used to set the p2p parameters + * + * 02 21 2011 terry.wu + * [WCXRP00000476] [MT6620 Wi-Fi][Driver] Clean P2P scan list while removing P2P + * Clean P2P scan list while removing P2P. + * + * 02 18 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * fixed the ioctl setting that index not map to spec defined config method. + * + * 02 17 2011 wh.su + * [WCXRP00000471] [MT6620 Wi-Fi][Driver] Add P2P Provison discovery append Config Method attribute at WSC IE + * append the WSC IE config method attribute at provision discovery request. + * + * 02 17 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * modify the structure pointer for set WSC IE. + * + * 02 16 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * fixed the probe request send out without WSC IE issue (at P2P). + * + * 02 09 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * fix typo + * + * 02 09 2011 yuche.tsai + * [WCXRP00000431] [Volunteer Patch][MT6620][Driver] Add MLME support for deauthentication under AP(Hot-Spot) mode. + * Add Support for MLME deauthentication for Hot-Spot. + * + * 01 25 2011 terry.wu + * [WCXRP00000393] [MT6620 Wi-Fi][Driver] Add new module insert parameter + * Add a new module parameter to indicate current runnig mode, P2P or AP. + * + * 01 12 2011 yuche.tsai + * [WCXRP00000352] [Volunteer Patch][MT6620][Driver] P2P Statsion Record Client List Issue + * 1. Modify Channel Acquire Time of AP mode from 5s to 1s. + * 2. Call cnmP2pIsPermit() before active P2P network. + * 3. Add channel selection support for AP mode. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * ioctl implementations for P2P Service Discovery + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 12 15 2010 cp.wu + * NULL + * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() + * + * 12 08 2010 yuche.tsai + * [WCXRP00000245] [MT6620][Driver] Invitation & Provision Discovery Feature Check-in + * [WCXRP000000245][MT6620][Driver] Invitation Request Feature Add + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 17 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID[WCXRP00000179] [MT6620 Wi-Fi][FW] Set the Tx + * lowest rate at wlan table for normal operation + * fixed some ASSERT check. + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 10 2010 george.huang + * NULL + * update iwpriv LP related + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at win XP. + * + * 09 09 2010 cp.wu + * NULL + * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 08 25 2010 cp.wu + * NULL + * add netdev_ops(NDO) for linux kernel 2.6.31 or greater + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 20 2010 cp.wu + * NULL + * correct typo. + * + * 08 20 2010 yuche.tsai + * NULL + * Invert Connection request provision status parameter. + * + * 08 19 2010 cp.wu + * NULL + * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. + * + * 08 18 2010 cp.wu + * NULL + * modify pwp ioctls attribution by removing FIXED_SIZE. + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 17 2010 cp.wu + * NULL + * correct p2p net device registration with NULL pointer access issue. + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 16 2010 cp.wu + * NULL + * add subroutines for P2P to set multicast list. + * + * 08 16 2010 george.huang + * NULL + * add wext handlers to link P2P set PS profile/ network address function (TBD) + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 12 2010 cp.wu + * NULL + * follow-up with ioctl interface update for Wi-Fi Direct application + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * add basic support for ioctl of getting scan result. (only address and SSID are reporterd though) + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant + * + * 08 03 2010 cp.wu + * NULL + * surpress compilation warning. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 23 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * p2p interface revised to be sync. with HAL + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement private io controls for Wi-Fi Direct + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * 1) add timeout handler mechanism for pending command packets + * 2) add p2p add/removal key + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement wireless extension ioctls in iw_handler form. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "gl_p2p_os.h" +#include "gl_p2p_ioctl.h" +#include "gl_vendor.h" + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define ARGV_MAX_NUM (4) + +/*For CFG80211 - wiphy parameters*/ +#define MAX_SCAN_LIST_NUM (1) +#define MAX_SCAN_IE_LEN (512) + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +static struct cfg80211_ops mtk_p2p_ops = { + .change_virtual_intf = mtk_p2p_cfg80211_change_iface, /* 1st */ + .change_bss = mtk_p2p_cfg80211_change_bss, + .scan = mtk_p2p_cfg80211_scan, + .remain_on_channel = mtk_p2p_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mtk_p2p_cfg80211_cancel_remain_on_channel, + .mgmt_tx = mtk_p2p_cfg80211_mgmt_tx, + .connect = mtk_p2p_cfg80211_connect, + .disconnect = mtk_p2p_cfg80211_disconnect, + .deauth = mtk_p2p_cfg80211_deauth, + .disassoc = mtk_p2p_cfg80211_disassoc, + .start_ap = mtk_p2p_cfg80211_start_ap, + .change_beacon = mtk_p2p_cfg80211_change_beacon, + .stop_ap = mtk_p2p_cfg80211_stop_ap, + .set_wiphy_params = mtk_p2p_cfg80211_set_wiphy_params, + .del_station = mtk_p2p_cfg80211_del_station, + .set_monitor_channel = mtk_p2p_cfg80211_set_channel, + .set_bitrate_mask = mtk_p2p_cfg80211_set_bitrate_mask, + .mgmt_frame_register = mtk_p2p_cfg80211_mgmt_frame_register, + .get_station = mtk_p2p_cfg80211_get_station, + .add_key = mtk_p2p_cfg80211_add_key, + .get_key = mtk_p2p_cfg80211_get_key, + .del_key = mtk_p2p_cfg80211_del_key, + .set_default_key = mtk_p2p_cfg80211_set_default_key, + .join_ibss = mtk_p2p_cfg80211_join_ibss, + .leave_ibss = mtk_p2p_cfg80211_leave_ibss, + .set_tx_power = mtk_p2p_cfg80211_set_txpower, + .get_tx_power = mtk_p2p_cfg80211_get_txpower, + .set_power_mgmt = mtk_p2p_cfg80211_set_power_mgmt, +#ifdef CONFIG_NL80211_TESTMODE + .testmode_cmd = mtk_p2p_cfg80211_testmode_cmd, +#endif +}; + +static const struct wiphy_vendor_command mtk_p2p_vendor_ops[] = { + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_GET_CHANNEL_LIST + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_get_channel_list + }, + { + { + .vendor_id = GOOGLE_OUI, + .subcmd = WIFI_SUBCMD_SET_COUNTRY_CODE + }, + .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV, + .doit = mtk_cfg80211_vendor_set_country_code + }, +}; + +/* There isn't a lot of sense in it, but you can transmit anything you like */ +static const struct ieee80211_txrx_stypes + mtk_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_ADHOC] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_STATION] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_AP] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_AP_VLAN] = { + /* copy AP */ + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = 0xffff, + .rx = BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | BIT(IEEE80211_STYPE_ACTION >> 4) + } +}; + +#endif + +/* the legacy wireless extension stuff */ +static const iw_handler rP2PIwStandardHandler[] = { + [SIOCGIWPRIV - SIOCIWFIRST] = mtk_p2p_wext_get_priv, + [SIOCGIWSCAN - SIOCIWFIRST] = mtk_p2p_wext_discovery_results, + [SIOCSIWESSID - SIOCIWFIRST] = mtk_p2p_wext_reconnect, + [SIOCSIWAUTH - SIOCIWFIRST] = mtk_p2p_wext_set_auth, + [SIOCSIWENCODEEXT - SIOCIWFIRST] = mtk_p2p_wext_set_key, + [SIOCSIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_set_powermode, + [SIOCGIWPOWER - SIOCIWFIRST] = mtk_p2p_wext_get_powermode, + [SIOCSIWTXPOW - SIOCIWFIRST] = mtk_p2p_wext_set_txpow, +#if CFG_SUPPORT_P2P_RSSI_QUERY + [SIOCGIWSTATS - SIOCIWFIRST] = mtk_p2p_wext_get_rssi, +#endif + [SIOCSIWMLME - SIOCIWFIRST] = mtk_p2p_wext_mlme_handler, +}; + +static const iw_handler rP2PIwPrivHandler[] = { + [IOC_P2P_CFG_DEVICE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_local_dev_info, + [IOC_P2P_PROVISION_COMPLETE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_provision_complete, + [IOC_P2P_START_STOP_DISCOVERY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_start_stop_discovery, + [IOC_P2P_DISCOVERY_RESULTS - SIOCIWFIRSTPRIV] = mtk_p2p_wext_discovery_results, + [IOC_P2P_WSC_BEACON_PROBE_RSP_IE - SIOCIWFIRSTPRIV] = mtk_p2p_wext_wsc_ie, + [IOC_P2P_CONNECT_DISCONNECT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_connect_disconnect, + [IOC_P2P_PASSWORD_READY - SIOCIWFIRSTPRIV] = mtk_p2p_wext_password_ready, +/* [IOC_P2P_SET_PWR_MGMT_PARAM - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_pm_param, */ + [IOC_P2P_SET_INT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_int, + [IOC_P2P_GET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_get_struct, + [IOC_P2P_SET_STRUCT - SIOCIWFIRSTPRIV] = mtk_p2p_wext_set_struct, + [IOC_P2P_GET_REQ_DEVICE_INFO - SIOCIWFIRSTPRIV] = mtk_p2p_wext_request_dev_info, +}; + +static const struct iw_priv_args rP2PIwPrivTable[] = { + { + .cmd = IOC_P2P_CFG_DEVICE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CFG_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CFG_DEVICE"} + , + { + .cmd = IOC_P2P_START_STOP_DISCOVERY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_REQ_DEVICE_TYPE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_DISCOVERY"} + , + { + .cmd = IOC_P2P_DISCOVERY_RESULTS, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_RESULT"} + , + { + .cmd = IOC_P2P_WSC_BEACON_PROBE_RSP_IE, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_HOSTAPD_PARAM), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_WSC_IE"} + , + { + .cmd = IOC_P2P_CONNECT_DISCONNECT, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_CONNECT_DEVICE), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_CONNECT"} + , + { + .cmd = IOC_P2P_PASSWORD_READY, + .set_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_PASSWORD_READY), + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_PASSWD_RDY"} + , + { + .cmd = IOC_P2P_GET_STRUCT, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "P2P_GET_STRUCT"} + , + { + .cmd = IOC_P2P_SET_STRUCT, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "P2P_SET_STRUCT"} + , + { + .cmd = IOC_P2P_GET_REQ_DEVICE_INFO, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = IW_PRIV_TYPE_BYTE | (__u16) sizeof(IW_P2P_DEVICE_REQ), + .name = "P2P_GET_REQDEV"} + , + { + /* SET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = 256, + .get_args = IW_PRIV_TYPE_NONE, + .name = "set_oid"} + , + { + /* GET STRUCT sub-ioctls commands */ + .cmd = PRIV_CMD_OID, + .set_args = IW_PRIV_TYPE_NONE, + .get_args = 256, + .name = "get_oid"} +}; + +const struct iw_handler_def mtk_p2p_wext_handler_def = { + .num_standard = (__u16) sizeof(rP2PIwStandardHandler) / sizeof(iw_handler), + .num_private = (__u16) sizeof(rP2PIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rP2PIwPrivTable) / sizeof(struct iw_priv_args), + .standard = rP2PIwStandardHandler, + .private = rP2PIwPrivHandler, + .private_args = rP2PIwPrivTable, +#if CFG_SUPPORT_P2P_RSSI_QUERY + .get_wireless_stats = mtk_p2p_wext_get_wireless_stats, +#else + .get_wireless_stats = NULL, +#endif +}; + +#ifdef CONFIG_PM +static const struct wiphy_wowlan_support p2p_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | WIPHY_WOWLAN_ANY, +}; +#endif + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* for IE Searching */ +extern BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); +#endif + +/* Net Device Hooks */ +static int p2pOpen(IN struct net_device *prDev); + +static int p2pStop(IN struct net_device *prDev); + +static struct net_device_stats *p2pGetStats(IN struct net_device *prDev); + +static void p2pSetMulticastList(IN struct net_device *prDev); + +static int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev); + +static int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd); + +static int p2pSetMACAddress(IN struct net_device *prDev, void *addr); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Override the implementation of select queue +* +* \param[in] dev Pointer to struct net_device +* \param[in] skb Pointer to struct skb_buff +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ + +unsigned int _p2p_cfg80211_classify8021d(struct sk_buff *skb) +{ + unsigned int dscp = 0; + + /* skb->priority values from 256->263 are magic values + * directly indicate a specific 802.1d priority. This is + * to allow 802.1d priority to be passed directly in from + * tags + */ + + if (skb->priority >= 256 && skb->priority <= 263) + return skb->priority - 256; + switch (skb->protocol) { + case htons(ETH_P_IP): + dscp = ip_hdr(skb)->tos & 0xfc; + break; + } + return dscp >> 5; +} + +static const UINT_16 au16Wlan1dToQueueIdx[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; + +static UINT_16 p2pSelectQueue(struct net_device *dev, struct sk_buff *skb, + void *accel_priv, select_queue_fallback_t fallback) +{ + skb->priority = _p2p_cfg80211_classify8021d(skb); + + return au16Wlan1dToQueueIdx[skb->priority]; +} + +static struct net_device *g_P2pPrDev; +static struct wireless_dev *gprP2pWdev; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->init +* +* \param[in] prDev Pointer to struct net_device. +* +* \retval 0 The execution of wlanInit succeeds. +* \retval -ENXIO No such device. +*/ +/*----------------------------------------------------------------------------*/ +static int p2pInit(struct net_device *prDev) +{ +/* P_GLUE_INFO_T prGlueInfo; */ + if (!prDev) + return -ENXIO; + + DBGLOG(P2P, INFO, "dev name=%s\n", prDev->name); + return 0; /* success */ +} /* end of p2pInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A function for prDev->uninit +* +* \param[in] prDev Pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +static void p2pUninit(IN struct net_device *prDev) +{ + +} /* end of p2pUninit() */ + +static const struct net_device_ops p2p_netdev_ops = { + .ndo_open = p2pOpen, + .ndo_stop = p2pStop, + .ndo_set_mac_address = p2pSetMACAddress, + .ndo_set_rx_mode = p2pSetMulticastList, + .ndo_get_stats = p2pGetStats, + .ndo_do_ioctl = p2pDoIOCTL, + .ndo_start_xmit = p2pHardStartXmit, + .ndo_select_queue = p2pSelectQueue, + .ndo_init = p2pInit, + .ndo_uninit = p2pUninit, +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Allocate memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PAllocInfo(IN P_GLUE_INFO_T prGlueInfo) +{ + P_ADAPTER_T prAdapter = NULL; + P_WIFI_VAR_T prWifiVar = NULL; + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + prAdapter = prGlueInfo->prAdapter; + prWifiVar = &(prAdapter->rWifiVar); + + if (!prWifiVar) { + ASSERT(FALSE); + return FALSE; + } + + do { + if (prGlueInfo->prP2PInfo == NULL) { + /*alloc memory for p2p info */ + prGlueInfo->prP2PInfo = kalMemAlloc(sizeof(GL_P2P_INFO_T), VIR_MEM_TYPE); + prAdapter->prP2pInfo = kalMemAlloc(sizeof(P2P_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2PConnSettings = kalMemAlloc(sizeof(P2P_CONNECTION_SETTINGS_T), VIR_MEM_TYPE); + prWifiVar->prP2pFsmInfo = kalMemAlloc(sizeof(P2P_FSM_INFO_T), VIR_MEM_TYPE); + prWifiVar->prP2pSpecificBssInfo = kalMemAlloc(sizeof(P2P_SPECIFIC_BSS_INFO_T), VIR_MEM_TYPE); + } else { + ASSERT(prAdapter->prP2pInfo != NULL); + ASSERT(prWifiVar->prP2PConnSettings != NULL); + ASSERT(prWifiVar->prP2pFsmInfo != NULL); + ASSERT(prWifiVar->prP2pSpecificBssInfo != NULL); + } + /*MUST set memory to 0 */ + if (prGlueInfo->prP2PInfo) + kalMemZero(prGlueInfo->prP2PInfo, sizeof(GL_P2P_INFO_T)); + if (prAdapter->prP2pInfo) + kalMemZero(prAdapter->prP2pInfo, sizeof(P2P_INFO_T)); + if (prWifiVar->prP2PConnSettings) + kalMemZero(prWifiVar->prP2PConnSettings, sizeof(P2P_CONNECTION_SETTINGS_T)); + if (prWifiVar->prP2pFsmInfo) + kalMemZero(prWifiVar->prP2pFsmInfo, sizeof(P2P_FSM_INFO_T)); + if (prWifiVar->prP2pSpecificBssInfo) + kalMemZero(prWifiVar->prP2pSpecificBssInfo, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + } while (FALSE); + + /* chk if alloc successful or not */ + if (prGlueInfo->prP2PInfo && + prAdapter->prP2pInfo && + prWifiVar->prP2PConnSettings && prWifiVar->prP2pFsmInfo && prWifiVar->prP2pSpecificBssInfo) { + return TRUE; + } + + if (prWifiVar->prP2pSpecificBssInfo) { + kalMemFree(prWifiVar->prP2pSpecificBssInfo, VIR_MEM_TYPE, sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + prWifiVar->prP2pSpecificBssInfo = NULL; + } + if (prWifiVar->prP2pFsmInfo) { + kalMemFree(prWifiVar->prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + + prWifiVar->prP2pFsmInfo = NULL; + } + if (prWifiVar->prP2PConnSettings) { + kalMemFree(prWifiVar->prP2PConnSettings, VIR_MEM_TYPE, sizeof(P2P_CONNECTION_SETTINGS_T)); + + prWifiVar->prP2PConnSettings = NULL; + } + if (prGlueInfo->prP2PInfo) { + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + + prGlueInfo->prP2PInfo = NULL; + } + if (prAdapter->prP2pInfo) { + kalMemFree(prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + + prAdapter->prP2pInfo = NULL; + } + return FALSE; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free memory for P2P_INFO, GL_P2P_INFO, P2P_CONNECTION_SETTINGS +* P2P_SPECIFIC_BSS_INFO, P2P_FSM_INFO +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo) +{ + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + /* free memory after p2p module is ALREADY unregistered */ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + + kalMemFree(prGlueInfo->prAdapter->prP2pInfo, VIR_MEM_TYPE, sizeof(P2P_INFO_T)); + kalMemFree(prGlueInfo->prP2PInfo, VIR_MEM_TYPE, sizeof(GL_P2P_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings, VIR_MEM_TYPE, + sizeof(P2P_CONNECTION_SETTINGS_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo, VIR_MEM_TYPE, sizeof(P2P_FSM_INFO_T)); + kalMemFree(prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo, VIR_MEM_TYPE, + sizeof(P2P_SPECIFIC_BSS_INFO_T)); + + /*Reomve p2p bss scan list */ + scanRemoveAllP2pBssDesc(prGlueInfo->prAdapter); + + /*reset all pointer to NULL */ + prGlueInfo->prP2PInfo = NULL; + prGlueInfo->prAdapter->prP2pInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo = NULL; + prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo = NULL; + + return TRUE; + } else { + return FALSE; + } + +} + +#if !CFG_SUPPORT_PERSIST_NETDEV +BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) +{ + BOOLEAN fgDoRegister = FALSE; +/* BOOLEAN fgRollbackRtnlLock = FALSE; */ + BOOLEAN ret; + + GLUE_SPIN_LOCK_DECLARATION(); + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_UNREGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERING; + fgDoRegister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoRegister) + return TRUE; + + /* net device initialize */ + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + + /* register for net device */ + if (register_netdev(prGlueInfo->prP2PInfo->prDevHandler) < 0) { + DBGLOG(P2P, WARN, "unable to register netdevice for p2p\n"); + + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + + ret = FALSE; + } else { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_REGISTERED; + ret = TRUE; + } + return ret; +} + +BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired) +{ + BOOLEAN fgDoUnregister = FALSE; +/* BOOLEAN fgRollbackRtnlLock = FALSE; */ + GLUE_SPIN_LOCK_DECLARATION(); + + if ((!prGlueInfo) || (!prGlueInfo->prAdapter)) { + ASSERT(FALSE); + return FALSE; + } + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueInfo->prAdapter->rP2PNetRegState == ENUM_NET_REG_STATE_REGISTERED) { + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERING; + fgDoUnregister = TRUE; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (!fgDoUnregister) + return TRUE; + + /* prepare for removal */ + if (netif_carrier_ok(prGlueInfo->prP2PInfo->prDevHandler)) + netif_carrier_off(prGlueInfo->prP2PInfo->prDevHandler); + + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + DBGLOG(P2P, INFO, "P2P unregister_netdev 0x%p\n", prGlueInfo->prP2PInfo->prDevHandler); + unregister_netdev(prGlueInfo->prP2PInfo->prDevHandler); + + prGlueInfo->prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + return TRUE; +} +#endif + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo) +{ + struct wiphy *prWiphy = NULL; + struct wireless_dev *prWdev = NULL; +#if CFG_SUPPORT_PERSIST_NETDEV + struct net_device *prNetDev = NULL; +#endif +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prWdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!prWdev) { + DBGLOG(P2P, ERROR, "allocate p2p wireless device fail, no memory\n"); + return FALSE; + } + /* 1. allocate WIPHY */ + prWiphy = wiphy_new(&mtk_p2p_ops, sizeof(P_GLUE_INFO_T)); + if (!prWiphy) { + DBGLOG(P2P, ERROR, "unable to allocate wiphy for p2p\n"); + goto free_wdev; + } + + prWiphy->interface_modes = BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_STATION); + + prWiphy->bands[NL80211_BAND_2GHZ] = &mtk_band_2ghz; + prWiphy->bands[NL80211_BAND_5GHZ] = &mtk_band_5ghz; + + prWiphy->mgmt_stypes = mtk_cfg80211_default_mgmt_stypes; + prWiphy->max_remain_on_channel_duration = 5000; + prWiphy->cipher_suites = mtk_cipher_suites; + prWiphy->n_cipher_suites = ARRAY_SIZE(mtk_cipher_suites); + prWiphy->flags = WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_HAVE_AP_SME; + prWiphy->regulatory_flags = REGULATORY_CUSTOM_REG; + prWiphy->ap_sme_capa = 1; + + prWiphy->max_scan_ssids = MAX_SCAN_LIST_NUM; + prWiphy->max_scan_ie_len = MAX_SCAN_IE_LEN; + prWiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + prWiphy->vendor_commands = mtk_p2p_vendor_ops; + prWiphy->n_vendor_commands = sizeof(mtk_p2p_vendor_ops) / sizeof(struct wiphy_vendor_command); + +#ifdef CONFIG_PM + prWiphy->wowlan = &p2p_wowlan_support; +#endif + + /* 2.1 set priv as pointer to glue structure */ + *((P_GLUE_INFO_T *) wiphy_priv(prWiphy)) = prGlueInfo; + if (wiphy_register(prWiphy) < 0) { + DBGLOG(P2P, ERROR, "fail to register wiphy for p2p\n"); + goto free_wiphy; + } + prWdev->wiphy = prWiphy; +#if CFG_SUPPORT_PERSIST_NETDEV + /* 3. allocate netdev */ + prNetDev = alloc_netdev_mq(sizeof(P_GLUE_INFO_T), P2P_MODE_INF_NAME, NET_NAME_PREDICTABLE, + ether_setup, CFG_MAX_TXQ_NUM); + if (!prNetDev) { + DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); + goto unregister_wiphy; + } + + /* 4. setup netdev */ + /* 4.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prNetDev)) = prGlueInfo; + + /* 4.2 fill hardware address */ + /* COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] ^= 0x2; // change to local administrated address + memcpy(prGlueInfo->prP2PInfo->prDevHandler->dev_addr, rMacAddr, ETH_ALEN); + memcpy(prGlueInfo->prP2PInfo->prDevHandler->perm_addr, + prGlueInfo->prP2PInfo->prDevHandler->dev_addr, ETH_ALEN);*/ + + /* 4.3 register callback functions */ + prNetDev->netdev_ops = &p2p_netdev_ops; + /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def;*/ + + prNetDev->ieee80211_ptr = prWdev; + prWdev->netdev = prNetDev; + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prNetDev->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + /* net device initialize */ + netif_carrier_off(prNetDev); + netif_tx_stop_all_queues(prNetDev); + + /* register for net device */ + if (register_netdev(prNetDev) < 0) { + DBGLOG(P2P, ERROR, "unable to register netdevice for p2p\n"); + free_netdev(prNetDev); + goto unregister_wiphy; + } +#endif + gprP2pWdev = prWdev; + return TRUE; + +#if CFG_SUPPORT_PERSIST_NETDEV +unregister_wiphy: + wiphy_unregister(prWiphy); +#endif +free_wiphy: + wiphy_free(prWiphy); +free_wdev: + kfree(prWdev); +#endif + return FALSE; +} + +void glP2pDestroyWirelessDevice(VOID) +{ +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#if CFG_SUPPORT_PERSIST_NETDEV + unregister_netdev(gprP2pWdev->netdev); + free_netdev(gprP2pWdev->netdev); +#endif + wiphy_unregister(gprP2pWdev->wiphy); + wiphy_free(gprP2pWdev->wiphy); + kfree(gprP2pWdev); + gprP2pWdev = NULL; +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Register for cfg80211 for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode) +{ + P_ADAPTER_T prAdapter = NULL; + P_GL_HIF_INFO_T prHif = NULL; + PARAM_MAC_ADDRESS rMacAddr; + struct net_device *prDevHandler = NULL; +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + struct device *prDev; +#endif + + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prHif = &prGlueInfo->rHifInfo; + ASSERT(prHif); + + DBGLOG(P2P, TRACE, "glRegisterP2P\n"); +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + if (!gprP2pWdev) { + DBGLOG(P2P, ERROR, "gl_p2p, wireless device is not exist\n"); + return FALSE; + } +#endif + /*0. allocate p2pinfo */ + if (!p2PAllocInfo(prGlueInfo)) { + DBGLOG(P2P, ERROR, "Allocate memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prGlueInfo->prP2PInfo->prWdev = gprP2pWdev; + /* 1. fill wiphy parameters */ +#if MTK_WCN_HIF_SDIO + mtk_wcn_hif_sdio_get_dev(prHif->cltCtx, &prDev); + if (!prDev) + DBGLOG(P2P, WARN, "unable to get struct dev for p2p\n"); +#else + prDev = prHif->Dev; +#endif + /*set_wiphy_dev(gprP2pWdev->wiphy, prDev);*/ + if (!prGlueInfo->prAdapter->fgEnable5GBand) + gprP2pWdev->wiphy->bands[NL80211_BAND_5GHZ] = NULL; + + /* 2 set priv as pointer to glue structure */ + *(P_GLUE_INFO_T *) wiphy_priv(gprP2pWdev->wiphy) = prGlueInfo; + + if (fgIsApMode) { + gprP2pWdev->iftype = NL80211_IFTYPE_AP; +#if CFG_SUPPORT_PERSIST_NETDEV + if (kalStrnCmp(gprP2pWdev->netdev->name, AP_MODE_INF_NAME, 2)) { + rtnl_lock(); + dev_change_name(gprP2pWdev->netdev->name, AP_MODE_INF_NAME); + rtnl_unlock(); + } +#endif + } else { +#if CFG_SUPPORT_PERSIST_NETDEV + if (kalStrnCmp(gprP2pWdev->netdev->name, P2P_MODE_INF_NAME, 3)) { + rtnl_lock(); + dev_change_name(gprP2pWdev->netdev->name, P2P_MODE_INF_NAME); + rtnl_unlock(); + } +#endif + gprP2pWdev->iftype = NL80211_IFTYPE_P2P_CLIENT; + } +#endif /* CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ + +#if CFG_SUPPORT_PERSIST_NETDEV + prP2PInfo->prDevHandler = gprP2pWdev->netdev; +#else /* CFG_SUPPORT_PERSIST_NETDEV */ + /* 3. allocate netdev */ + prDevHandler = + alloc_netdev_mq(sizeof(P_GLUE_INFO_T), prDevName, NET_NAME_PREDICTABLE, ether_setup, CFG_MAX_TXQ_NUM); + if (!prDevHandler) { + DBGLOG(P2P, ERROR, "unable to allocate netdevice for p2p\n"); + return FALSE; + } + prGlueInfo->prP2PInfo->prDevHandler = prDevHandler; + /* 4. setup netdev */ + /* 4.1 Point to shared glue structure */ + *((P_GLUE_INFO_T *) netdev_priv(prDevHandler)) = prGlueInfo; + + /* 4.2 fill hardware address */ + COPY_MAC_ADDR(rMacAddr, prAdapter->rMyMacAddr); + rMacAddr[0] ^= 0x2; /* change to local administrated address */ + ether_addr_copy(prDevHandler->dev_addr, rMacAddr); + ether_addr_copy(prDevHandler->perm_addr, prDevHandler->dev_addr); + + /* 4.3 register callback functions */ + prDevHandler->netdev_ops = &p2p_netdev_ops; + /* prGlueInfo->prP2PInfo->prDevHandler->wireless_handlers = &mtk_p2p_wext_handler_def; */ + +#if (MTK_WCN_HIF_SDIO == 0) + SET_NETDEV_DEV(prDevHandler, prHif->Dev); +#endif + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + prDevHandler->ieee80211_ptr = gprP2pWdev; + gprP2pWdev->netdev = prDevHandler; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + prDevHandler->features = NETIF_F_IP_CSUM; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ +#endif /* CFG_SUPPORT_PERSIST_NETDEV */ + + /* 5. set p2p net device register state */ + prAdapter->rP2PNetRegState = ENUM_NET_REG_STATE_UNREGISTERED; + + /* 6. setup running mode */ + prAdapter->rWifiVar.prP2pFsmInfo->fgIsApMode = fgIsApMode; + + /* 7. finish */ + p2pFsmInit(prAdapter); + + p2pFuncInitConnectionSettings(prAdapter, prAdapter->rWifiVar.prP2PConnSettings); + + /* Active network too early would cause HW not able to sleep. + * Defer the network active time. + */ +/* nicActivateNetwork(prAdapter, NETWORK_TYPE_P2P_INDEX); */ + + return TRUE; +} /* end of glRegisterP2P() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Unregister Net Device for Wi-Fi Direct +* +* \param[in] prGlueInfo Pointer to glue info +* +* \return TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + /* normal flow: this func will called first before wlanRemove, and it can do fsmUninit/deactivateNetwork + gracefully. */ + /* when reset: because tx_thread with fw has stopped, so it can't do these job and the recovery will be + dependent on chip system reset. */ + /* if so, just skip it by flag GLUE_FLAG_HALT(warning: when tx_thread was stop, this flag was not cleared, + and NEED TO KEEP IT NOT CLEARED!). */ + if (!(prGlueInfo->ulFlag & GLUE_FLAG_HALT)) { + p2pFsmUninit(prGlueInfo->prAdapter); + nicDeactivateNetwork(prGlueInfo->prAdapter, NETWORK_TYPE_P2P_INDEX); + } +#if CFG_SUPPORT_PERSIST_NETDEV + dev_close(prGlueInfo->prP2PInfo->prDevHandler); +#else + free_netdev(prGlueInfo->prP2PInfo->prDevHandler); + prGlueInfo->prP2PInfo->prDevHandler = NULL; +#endif + /* Free p2p memory */ + if (!p2PFreeInfo(prGlueInfo)) { + DBGLOG(P2P, ERROR, "Free memory for p2p FAILED\n"); + ASSERT(0); + return FALSE; + } + return TRUE; +} /* end of glUnregisterP2P() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for stop p2p fsm immediate + * + * \param[in] prGlueInfo Pointer to struct P_GLUE_INFO_T. + * + * \retval TRUE The execution succeeds. + * \retval FALSE The execution failed. + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo) +{ +/* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + ASSERT(prGlueInfo); + +/* prAdapter = prGlueInfo->prAdapter; */ +/* ASSERT(prAdapter); */ + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prGlueInfo->prP2PInfo->prDevHandler); + +#if 0 + /* 2. switch P2P-FSM off */ + /* 2.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + DBGLOG(P2P, ERROR, "Allocate for p2p mesasage FAILED\n"); + /* return -ENOMEM; */ + } + + /* 2.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = FALSE; + + /* 2.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_UNBUF); + +#endif + + /* 3. stop queue and turn off carrier */ + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; + + return TRUE; +} /* end of p2pStop() */ + +/* Net Device Hooks */ +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device open (ifup) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int p2pOpen(IN struct net_device *prDev) +{ +/* P_GLUE_INFO_T prGlueInfo = NULL; */ +/* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + + ASSERT(prDev); + +#if 0 /* Move after device name set. (mtk_p2p_set_local_dev_info) */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* 1. switch P2P-FSM on */ + /* 1.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = TRUE; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + + /* 2. carrier on & start TX queue */ + netif_carrier_on(prDev); + netif_tx_start_all_queues(prDev); + + return 0; /* success */ +} /* end of p2pOpen() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A function for net_device stop (ifdown) + * + * \param[in] prDev Pointer to struct net_device. + * + * \retval 0 The execution succeeds. + * \retval < 0 The execution failed. + */ +/*----------------------------------------------------------------------------*/ +static int p2pStop(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + /* P_ADAPTER_T prAdapter = NULL; */ +/* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch; */ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + struct cfg80211_scan_info info = { + .aborted = true, + }; + + struct cfg80211_scan_request *prScanRequest = NULL; + + GLUE_SPIN_LOCK_DECLARATION(); + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + ASSERT(prGlueP2pInfo); + + /* CFG80211 down */ + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + if (prScanRequest) + cfg80211_scan_done(prScanRequest, &info); +#if 0 + + /* 1. stop TX queue */ + netif_tx_stop_all_queues(prDev); + + /* 2. switch P2P-FSM off */ + /* 2.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 2.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = FALSE; + + /* 2.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + /* 3. stop queue and turn off carrier */ + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_DISCONNECTED; + + netif_tx_stop_all_queues(prDev); + if (netif_carrier_ok(prDev)) + netif_carrier_off(prDev); + + return 0; +} /* end of p2pStop() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, to get the network interface statistical + * information. + * + * Whenever an application needs to get statistics for the interface, this method + * is called. This happens, for example, when ifconfig or netstat -i is run. + * + * \param[in] prDev Pointer to struct net_device. + * + * \return net_device_stats buffer pointer. + */ +/*----------------------------------------------------------------------------*/ +struct net_device_stats *p2pGetStats(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + +#if CFG_SUPPORT_PERSIST_NETDEV + /* @FIXME */ + /* prDev->stats.rx_packets = 0; */ + /* prDev->stats.tx_packets = 0; */ + prDev->stats.tx_errors = 0; + prDev->stats.rx_errors = 0; + /* prDev->stats.rx_bytes = 0; */ + /* prDev->stats.tx_bytes = 0; */ + prDev->stats.multicast = 0; + + return &prDev->stats; + +#else + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_packets = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.tx_packets = 0; */ + prGlueInfo->prP2PInfo->rNetDevStats.tx_errors = 0; + prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_bytes = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes = 0; */ + /* prGlueInfo->prP2PInfo->rNetDevStats.rx_errors = 0; */ + prGlueInfo->prP2PInfo->rNetDevStats.multicast = 0; + + return &prGlueInfo->prP2PInfo->rNetDevStats; +#endif +} /* end of p2pGetStats() */ + +static void p2pSetMulticastList(IN struct net_device *prDev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + g_P2pPrDev = prDev; + + /* 4 Mark HALT, notify main thread to finish current job */ +/* prGlueInfo->u4Flag |= GLUE_FLAG_SUB_MOD_MULTICAST; */ + set_bit(GLUE_FLAG_SUB_MOD_MULTICAST_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + +} /* p2pSetMulticastList */ + +/* FIXME: Since we cannot sleep in the wlanSetMulticastList, we arrange + * another workqueue for sleeping. We don't want to block + * tx_thread, so we can't let tx_thread to do this */ + +void p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo) +{ + if (!prGlueInfo) { + DBGLOG(INIT, ERROR, "prGlueInfo is NULL\n"); + return; + } +#if CFG_ENABLE_WIFI_DIRECT + if (prGlueInfo->prAdapter->fgIsP2PRegistered) + mtk_p2p_wext_set_Multicastlist(prGlueInfo); +#endif +} /* end of p2pSetMulticastListWorkQueueWrapper() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief This function is to set multicast list and set rx mode. + * + * \param[in] prDev Pointer to struct net_device + * + * \return (none) + */ +/*----------------------------------------------------------------------------*/ +void mtk_p2p_wext_set_Multicastlist(P_GLUE_INFO_T prGlueInfo) +{ + UINT_32 u4SetInfoLen = 0; + struct net_device *prDev = g_P2pPrDev; + + prGlueInfo = (NULL != prDev) ? *((P_GLUE_INFO_T *) netdev_priv(prDev)) : NULL; + + ASSERT(prDev); + ASSERT(prGlueInfo); + if (!prDev || !prGlueInfo) { + DBGLOG(P2P, WARN, "abnormal dev or skb: prDev(0x%p), prGlueInfo(0x%p)\n", prDev, prGlueInfo); + return; + } + + if (prDev->flags & IFF_PROMISC) + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_PROMISCUOUS; + + if (prDev->flags & IFF_BROADCAST) + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_BROADCAST; + + if (prDev->flags & IFF_MULTICAST) { + if ((prDev->flags & IFF_ALLMULTI) || + (netdev_mc_count(prDev) > MAX_NUM_GROUP_ADDR)) { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_ALL_MULTICAST; + } else { + prGlueInfo->prP2PInfo->u4PacketFilter |= PARAM_PACKET_FILTER_MULTICAST; + } + } + + if (prGlueInfo->prP2PInfo->u4PacketFilter & PARAM_PACKET_FILTER_MULTICAST) { + /* Prepare multicast address list */ + struct netdev_hw_addr *ha; + UINT_32 i = 0; + + netdev_for_each_mc_addr(ha, prDev) { + if (i < MAX_NUM_GROUP_ADDR) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucMCAddrList[i]), ha->addr); + i++; + } + } + + DBGLOG(P2P, TRACE, "SEt Multicast Address List\n"); + + if (i >= MAX_NUM_GROUP_ADDR) + return; + wlanoidSetP2PMulticastList(prGlueInfo->prAdapter, + &(prGlueInfo->prP2PInfo->aucMCAddrList[0]), (i * ETH_ALEN), &u4SetInfoLen); + + } + +} /* end of mtk_p2p_wext_set_Multicastlist */ + +/*----------------------------------------------------------------------------*/ +/*! + * * \brief This function is TX entry point of NET DEVICE. + * * + * * \param[in] prSkb Pointer of the sk_buff to be sent + * * \param[in] prDev Pointer to struct net_device + * * + * * \retval NETDEV_TX_OK - on success. + * * \retval NETDEV_TX_BUSY - on failure, packet will be discarded by upper layer. + * */ +/*----------------------------------------------------------------------------*/ +int p2pHardStartXmit(IN struct sk_buff *prSkb, IN struct net_device *prDev) +{ + P_QUE_ENTRY_T prQueueEntry = NULL; + P_QUE_T prTxQueue = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_16 u2QueueIdx = 0; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(prSkb); + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prGlueInfo->u8SkbToDriver++; + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + DBGLOG(P2P, ERROR, "GLUE_FLAG_HALT skip tx\n"); + prGlueInfo->u8SkbFreed++; + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } +#if (CFG_SUPPORT_MET_PROFILING == 1) + kalMetProfilingStart(prGlueInfo, prSkb); +#endif + + /* mark as P2P packets */ + GLUE_SET_PKT_FLAG_P2P(prSkb); +#if CFG_ENABLE_PKT_LIFETIME_PROFILE + GLUE_SET_PKT_ARRIVAL_TIME(prSkb, kalGetTimeTick()); +#endif + + STATS_TX_TIME_ARRIVE(prSkb); + prQueueEntry = (P_QUE_ENTRY_T) GLUE_GET_PKT_QUEUE_ENTRY(prSkb); + prTxQueue = &prGlueInfo->rTxQueue; + + if (wlanProcessSecurityFrame(prGlueInfo->prAdapter, (P_NATIVE_PACKET) prSkb) == FALSE) { + + u2QueueIdx = skb_get_queue_mapping(prSkb); + ASSERT(u2QueueIdx < CFG_MAX_TXQ_NUM); + + if (u2QueueIdx >= CFG_MAX_TXQ_NUM) { + DBGLOG(P2P, ERROR, "Incorrect queue index, skip this frame\n"); + prGlueInfo->u8SkbFreed++; + dev_kfree_skb(prSkb); + return NETDEV_TX_OK; + } + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + QUEUE_INSERT_TAIL(prTxQueue, prQueueEntry); + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_TX_QUE); + + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingFrameNum); + GLUE_INC_REF_CNT(prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); + + if (prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx] >= + CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD) { + DBGLOG(TX, INFO, "netif_stop_subqueue for p2p0, Queue len: %d\n", + prGlueInfo->ai4TxPendingFrameNumPerQueue[NETWORK_TYPE_P2P_INDEX][u2QueueIdx]); + netif_stop_subqueue(prDev, u2QueueIdx); + } + } else { + GLUE_INC_REF_CNT(prGlueInfo->i4TxPendingSecurityFrameNum); + } + + kalSetEvent(prGlueInfo); + + /* Statistic usage. */ + prGlueInfo->prP2PInfo->rNetDevStats.tx_bytes += prSkb->len; + prGlueInfo->prP2PInfo->rNetDevStats.tx_packets++; + /* prDev->stats.tx_packets++; */ + kalPerMonStart(prGlueInfo); + return NETDEV_TX_OK; +} /* end of p2pHardStartXmit() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief A method of struct net_device, a primary SOCKET interface to configure + * the interface lively. Handle an ioctl call on one of our devices. + * Everything Linux ioctl specific is done here. Then we pass the contents + * of the ifr->data to the request message handler. + * + * \param[in] prDev Linux kernel netdevice + * + * \param[in] prIfReq Our private ioctl request structure, typed for the generic + * struct ifreq so we can use ptr to function + * + * \param[in] cmd Command ID + * + * \retval 0 The IOCTL command is executed successfully. + * \retval <0 The execution of IOCTL command is failed. + */ +/*----------------------------------------------------------------------------*/ +int p2pDoIOCTL(struct net_device *prDev, struct ifreq *prIfReq, int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + struct iwreq *prIwReq = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + + ASSERT(prDev && prIfReq); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + if (!prGlueInfo) { + DBGLOG(P2P, ERROR, "prGlueInfo is NULL\n"); + return -EFAULT; + } + + if (prGlueInfo->u4ReadyFlag == 0) { + DBGLOG(P2P, ERROR, "Adapter is not ready\n"); + return -EINVAL; + } + + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case SIOCSIWENCODEEXT: + /* Set Encryption Material after 4-way handshaking is done */ + if (prIwReq->u.encoding.pointer) { + u4ExtraSize = prIwReq->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, prIwReq->u.encoding.pointer, prIwReq->u.encoding.length)) + ret = -EFAULT; + } else if (prIwReq->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = mtk_p2p_wext_set_key(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + break; + + case SIOCSIWMLME: + /* IW_MLME_DISASSOC used for disconnection */ + if (prIwReq->u.data.length != sizeof(struct iw_mlme)) { + DBGLOG(P2P, WARN, "MLME buffer strange:%d\n", prIwReq->u.data.length); + ret = -EINVAL; + break; + } + + if (!prIwReq->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, prIwReq->u.data.pointer, sizeof(struct iw_mlme))) + ret = -EFAULT; + else + ret = mtk_p2p_wext_mlme_handler(prDev, &rIwReqInfo, &(prIwReq->u), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + case SIOCGIWPRIV: + /* This ioctl is used to list all IW privilege ioctls */ + ret = mtk_p2p_wext_get_priv(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCGIWSCAN: + ret = mtk_p2p_wext_discovery_results(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case SIOCSIWAUTH: + ret = mtk_p2p_wext_set_auth(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; + + case IOC_P2P_CFG_DEVICE: + case IOC_P2P_PROVISION_COMPLETE: + case IOC_P2P_START_STOP_DISCOVERY: + case IOC_P2P_DISCOVERY_RESULTS: + case IOC_P2P_WSC_BEACON_PROBE_RSP_IE: + case IOC_P2P_CONNECT_DISCONNECT: + case IOC_P2P_PASSWORD_READY: + case IOC_P2P_GET_STRUCT: + case IOC_P2P_SET_STRUCT: + case IOC_P2P_GET_REQ_DEVICE_INFO: + ret = + rP2PIwPrivHandler[i4Cmd - SIOCIWFIRSTPRIV] (prDev, &rIwReqInfo, &(prIwReq->u), + (char *)&(prIwReq->u)); + break; +#if CFG_SUPPORT_P2P_RSSI_QUERY + case SIOCGIWSTATS: + ret = mtk_p2p_wext_get_rssi(prDev, &rIwReqInfo, &(prIwReq->u), NULL); + break; +#endif + case IOC_GET_PRIVATE_IOCTL_CMD: + ret = priv_support_driver_cmd(prDev, prIfReq, i4Cmd); + + break; + default: + ret = -ENOTTY; + } + + return ret; +} /* end of p2pDoIOCTL() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To report the iw private args table to user space. + * + * \param[in] prDev Net device requested. + * \param[in] info Pointer to iw_request_info. + * \param[inout] wrqu Pointer to iwreq_data. + * \param[inout] extra + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rP2PIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rP2PIwPrivTable, sizeof(rP2PIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* end of mtk_p2p_wext_get_priv() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To indicate P2P-FSM for re-associate to the connecting device + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 For success. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_reconnect: P2P Reconnect\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_reconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief MLME command handler +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_mlme *mlme = (struct iw_mlme *)extra; + P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + P_BSS_INFO_T prP2pBssInfo = (P_BSS_INFO_T) NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2pBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX]); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_mlme_handler:\n"); + + switch (mlme->cmd) { + case IW_MLME_DISASSOC: + prMsgP2PConnAbt = + (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + if (!prMsgP2PConnAbt) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, mlme->addr.sa_data); + + prMsgP2PConnAbt->u2ReasonCode = mlme->reason_code; + + if (EQUAL_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prP2pBssInfo->aucOwnMacAddr)) { + DBGLOG(P2P, TRACE, "P2P Connection Abort:\n"); + + /* 1.2 fill message */ + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + } else { + DBGLOG(P2P, TRACE, "P2P Connection Pause:\n"); + + /* 1.2 fill message */ + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); + + break; + + default: + return -EOPNOTSUPP; + } +#endif + return 0; +} /* end of mtk_p2p_wext_mlme_handler() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PROVISION_COMPLETE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_MSG_HDR_T prMsgHdr; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + switch (prData->flags) { + case P2P_PROVISIONING_SUCCESS: + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + + prGlueInfo->prP2PInfo->u4CipherPairwise = IW_AUTH_CIPHER_CCMP; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + + break; + + case P2P_PROVISIONING_FAIL: + + break; + + default: + return -EOPNOTSUPP; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_set_provision_complete() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_START_STOP_DISCOVERY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ +#if 0 + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_REQ_DEVICE_TYPE prReqDeviceType = (P_IW_P2P_REQ_DEVICE_TYPE) extra; + UINT_8 au4IeBuf[MAX_IE_LENGTH]; + P_MSG_HDR_T prMsgHdr; + P_MSG_P2P_DEVICE_DISCOVER_T prDiscoverMsg; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + if (prData->flags == P2P_STOP_DISCOVERY) { + prMsgHdr = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_HDR_T)); + + if (!prMsgHdr) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgHdr, MSG_SEND_METHOD_BUF); + } else if (prData->flags == P2P_START_DISCOVERY) { + + /* retrieve IE for Probe Response */ + if (prReqDeviceType->probe_rsp_len > 0) { + if (prReqDeviceType->probe_rsp_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prReqDeviceType->probe_rsp_ie, + prReqDeviceType->probe_rsp_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prReqDeviceType->probe_rsp_len; + } else { + return -E2BIG; + } + } + + /* retrieve IE for Probe Request */ + if (prReqDeviceType->probe_req_len > 0) { + if (prReqDeviceType->probe_req_len <= MAX_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[1], prReqDeviceType->probe_req_ie, + prReqDeviceType->probe_req_len)) { + return -EFAULT; + } + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prReqDeviceType->probe_req_len; + } else { + return -E2BIG; + } + } + /* update IE for Probe Request */ + + if (prReqDeviceType->scan_type == P2P_LISTEN) { + /* update listening parameter */ + + /* @TODO: update prConnSettings for Probe Response IE */ + } else { + /* indicate P2P-FSM with MID_MNY_P2P_DEVICE_DISCOVERY */ + prDiscoverMsg = (P_MSG_P2P_DEVICE_DISCOVER_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_DEVICE_DISCOVER_T)); + + if (!prDiscoverMsg) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + prDiscoverMsg->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + prDiscoverMsg->u4DevDiscoverTime = 0; /* unlimited */ + prDiscoverMsg->fgIsSpecificType = TRUE; + prDiscoverMsg->rTargetDeviceType.u2CategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[0])); + prDiscoverMsg->rTargetDeviceType.u2SubCategoryID = + *(PUINT_16) (&(prReqDeviceType->pri_device_type[6])); + COPY_MAC_ADDR(prDiscoverMsg->aucTargetDeviceID, aucNullAddr); + + /* @FIXME: parameter to be refined, where to pass IE buffer ? */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDiscoverMsg, MSG_SEND_METHOD_BUF); + } + } else { + return -EINVAL; + } +#endif + + return 0; +} /* end of mtk_p2p_wext_start_stop_discovery() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_INVITATION_STRUCT prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitation = (P_IW_P2P_IOCTL_INVITATION_STRUCT) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + if (prIoctlInvitation->ucReinvoke == 1) { + /* TODO: Set Group ID */ + p2pFuncSetGroupID(prAdapter, prIoctlInvitation->aucGroupID, prIoctlInvitation->aucSsid, + prIoctlInvitation->u4SsidLen); + } + + else { + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationReq = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; + + /* TODO: Do Invitation. */ + prMsgP2PInvitationReq = + (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_INVITATION_REQUEST_T)); + if (!prMsgP2PInvitationReq) { + ASSERT(0); /* Can't trigger P2P FSM */ + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationReq->aucDeviceID, prIoctlInvitation->aucDeviceID, MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationReq, MSG_SEND_METHOD_BUF); + + } + + } while (FALSE); +#endif + + return i4Status; + +} + +/* mtk_p2p_wext_invitation_request */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_abort(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; +#if 0 + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + P_IW_P2P_IOCTL_ABORT_INVITATION prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) NULL; + + UINT_8 bssid[MAC_ADDR_LEN]; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlInvitationAbort = (P_IW_P2P_IOCTL_ABORT_INVITATION) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + P_MSG_P2P_INVITATION_REQUEST_T prMsgP2PInvitationAbort = (P_MSG_P2P_INVITATION_REQUEST_T) NULL; + + prMsgP2PInvitationAbort = + (P_MSG_P2P_INVITATION_REQUEST_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_INVITATION_REQUEST_T)); + + if (!prMsgP2PInvitationAbort) { + ASSERT(0); /* Can't trigger P2P FSM */ + i4Status = -ENOMEM; + break; + } + + /* 1.2 fill message */ + kalMemCopy(prMsgP2PInvitationAbort->aucDeviceID, prIoctlInvitationAbort->dev_addr, + MAC_ADDR_LEN); + + DBGLOG(P2P, TRACE, "mtk_p2p_wext_invitation_request: P2P Invitation Req\n"); + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PInvitationAbort, MSG_SEND_METHOD_BUF); + + + } while (FALSE); +#endif + + return i4Status; + +} + +/* mtk_p2p_wext_invitation_abort */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief To override p2p interface address + * + * \param[in] prDev Net device requested. + * \param[in] addr Pointer to address + * + * \retval 0 For success. + * \retval -E2BIG For user's buffer size is too small. + * \retval -EFAULT For fail. + * + */ +/*----------------------------------------------------------------------------*/ +int p2pSetMACAddress(IN struct net_device *prDev, void *addr) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* @FIXME */ + return eth_mac_addr(prDev, addr); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher suite +* +* \param[in] prDev Net device requested. +* \param[out] +* +* \retval 0 Success. +* \retval -EINVAL Invalid parameter +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_auth(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_param *prAuth = (struct iw_param *)wrqu; + + ASSERT(prDev); + ASSERT(prAuth); + if (FALSE == GLUE_CHK_PR2(prDev, prAuth)) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + /* Save information to glue info and process later when ssid is set. */ + switch (prAuth->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: + break; + case IW_AUTH_CIPHER_PAIRWISE: + prGlueInfo->prP2PInfo->u4CipherPairwise = prAuth->value; + break; + case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_KEY_MGMT: + case IW_AUTH_TKIP_COUNTERMEASURES: + case IW_AUTH_DROP_UNENCRYPTED: + case IW_AUTH_80211_AUTH_ALG: + case IW_AUTH_WPA_ENABLED: + case IW_AUTH_RX_UNENCRYPTED_EAPOL: + case IW_AUTH_ROAMING_CONTROL: + case IW_AUTH_PRIVACY_INVOKED: + default: + /* @TODO */ + break; + } + + return 0; +} /* end of mtk_p2p_wext_set_auth() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[out] prIfReq Pointer to ifreq structure, content is copied back to +* user space buffer in gl_iwpriv_table. +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_key(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int ret = 0; + struct iw_encode_ext *prIWEncExt; + struct iw_point *prEnc; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + UINT_8 keyStructBuf[100]; + P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; + P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + do { + if (wrqu->encoding.pointer) { + u4ExtraSize = wrqu->encoding.length; + /*need confirm u4ExtraSize > 0 but is not very large*/ + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + /* here should set prExtraBuf default value */ + memset(prExtraBuf, 0, u4ExtraSize); + if (copy_from_user(prExtraBuf, wrqu->encoding.pointer, wrqu->encoding.length)) { + ret = -EFAULT; + break; + } + } else if (wrqu->encoding.length != 0) { + ret = -EINVAL; + break; + } + + prEnc = &wrqu->encoding; + /* here, need confirm (struct iw_encode_ext) < u4ExtraSize */ + prIWEncExt = (struct iw_encode_ext *)prExtraBuf; + + if (GLUE_CHK_PR3(prDev, prEnc, prExtraBuf) != TRUE) { + ret = -EINVAL; + break; + } + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { /* Key Removal */ + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + prRemoveKey, + prRemoveKey->u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + ret = -EFAULT; + } else { + if (prIWEncExt->alg == IW_ENCODE_ALG_CCMP) { + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + ((prEnc->flags & IW_ENCODE_INDEX) - 1) : 0; + if (prKey->u4KeyIndex <= 3) { + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) + prKey->u4KeyIndex |= 0x1UL << 31; + + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* group key */ + } else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, + IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = + ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddP2PKey, + prKey, + prKey->u4Length, + FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + ret = -EFAULT; + } else { + ret = -EINVAL; + } + } else { + ret = -EINVAL; + } + } + + } while (FALSE); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + + return ret; +} /* end of mtk_p2p_wext_set_key() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief set the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_powermode(IN struct net_device *prNetDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + /* printk("set_powermode = %d, value = %d\n", wrqu->power.disabled, wrqu->power.value); */ + struct iw_param *prPower = (struct iw_param *)&wrqu->power; +#if 1 + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ + /* prPower->value, prPower->disabled, prPower->flags); */ + + if (prPower->disabled) { + ePowerMode = Param_PowerModeCAM; + } else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } else { + DBGLOG(P2P, ERROR, "%s(): unsupported power management mode value = %d.\n", + __func__, prPower->value); + + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ + return -EFAULT; + } +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief get the p2p gc power mode +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_powermode(IN struct net_device *prNetDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + /* printk("mtk_p2p_wext_get_powermode\n"); */ + /* wrqu->power.disabled = 0; */ + /* wrqu->power.value = 1; */ + + struct iw_param *prPower = (struct iw_param *)&wrqu->power; + PARAM_POWER_MODE ePowerMode = Param_PowerModeMax; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + +#if 1 + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pPowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), TRUE, FALSE, FALSE, TRUE, &u4BufLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryP2pPowerSaveProfile, &ePowerMode, sizeof(ePowerMode), &u4BufLen); +#endif + + prPower->value = 0; + prPower->disabled = 1; + + if (Param_PowerModeCAM == ePowerMode) { + prPower->value = 0; + prPower->disabled = 1; + } else if (Param_PowerModeMAX_PSP == ePowerMode) { + prPower->value = 1; + prPower->disabled = 0; + } else if (Param_PowerModeFast_PSP == ePowerMode) { + prPower->value = 2; + prPower->disabled = 0; + } + + prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; +#if WIRELESS_EXT < 21 + prPower->value *= 1000000; +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_CFG_DEVICE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_CFG_DEVICE_TYPE prDeviceCfg = (P_IW_P2P_CFG_DEVICE_TYPE) extra; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + /* P_MSG_P2P_FUNCTION_SWITCH_T prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T)NULL; */ + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + prP2pSpecificBssInfo = prAdapter->rWifiVar.prP2pSpecificBssInfo; + + /* update connection settings for P2P-FSM */ + /* 1. update SSID */ + if (prDeviceCfg->ssid_len > ELEM_MAX_LEN_SSID) + prConnSettings->ucSSIDLen = ELEM_MAX_LEN_SSID; + else + prConnSettings->ucSSIDLen = prDeviceCfg->ssid_len; + + if (copy_from_user(prConnSettings->aucSSID, prDeviceCfg->ssid, prConnSettings->ucSSIDLen)) + return -EFAULT; + /* 2. update device type (WPS IE) */ + kalMemCopy(&(prConnSettings->rPrimaryDevTypeBE), &(prDeviceCfg->pri_device_type), sizeof(DEVICE_TYPE_T)); +#if P2P_MAX_SUPPORTED_SEC_DEV_TYPE_COUNT + kalMemCopy(&(prConnSettings->arSecondaryDevTypeBE[0]), &(prDeviceCfg->snd_device_type), sizeof(DEVICE_TYPE_T)); +#endif + + /* 3. update device name */ + if (prDeviceCfg->device_name_len > WPS_ATTRI_MAX_LEN_DEVICE_NAME) + prConnSettings->ucDevNameLen = WPS_ATTRI_MAX_LEN_DEVICE_NAME; + else + prConnSettings->ucDevNameLen = prDeviceCfg->device_name_len; + if (copy_from_user(prConnSettings->aucDevName, prDeviceCfg->device_name, prConnSettings->ucDevNameLen)) + return -EFAULT; + /* 4. update GO intent */ + prConnSettings->ucGoIntent = prDeviceCfg->intend; + + /* Preferred channel bandwidth */ + prAdapter->rWifiVar.rConnSettings.uc2G4BandwidthMode = prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; + prAdapter->rWifiVar.rConnSettings.uc5GBandwidthMode = prDeviceCfg->ch_width ? CONFIG_BW_20_40M : CONFIG_BW_20M; + +#if 0 + /* 1. switch P2P-FSM on */ + /* 1.1 allocate for message */ + prFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + + if (!prFuncSwitch) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + /* 1.2 fill message */ + prFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + prFuncSwitch->fgIsFuncOn = TRUE; + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + return 0; +} /* end of mtk_p2p_wext_set_local_dev_info() */ + +/*----------------------------------------------------------------------------*/ +/*! + * \brief I/O Control handler for both + * IOC_P2P_START_STOP_DISCOVERY & SIOCGIWSCAN + * + * \param[in] prDev Net device requested. + * \param[inout] wrqu Pointer to iwreq_data + * + * \retval 0 Success. + * \retval -EFAULT Setting parameters to driver fail. + * \retval -EOPNOTSUPP Key size not supported. + * + * \note + */ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_discovery_results(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + struct iw_event iwe; + char *current_ev = extra; + UINT_32 i; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + P_P2P_INFO_T prP2PInfo = (P_P2P_INFO_T) NULL; + P_EVENT_P2P_DEV_DISCOVER_RESULT_T prTargetResult = (P_EVENT_P2P_DEV_DISCOVER_RESULT_T) NULL; + P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prP2PInfo = prAdapter->prP2pInfo; + + for (i = 0; i < prP2PInfo->u4DeviceNum; i++) { + prTargetResult = &prP2PInfo->arP2pDiscoverResult[i]; + + /* SIOCGIWAP */ + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, prTargetResult->aucInterfaceAddr, 6); + + current_ev = iwe_stream_add_event(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, IW_EV_ADDR_LEN); + + /* SIOCGIWESSID */ + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + iwe.u.data.length = prTargetResult->u2NameLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, prTargetResult->aucName); + + /* IWEVGENIE for WPA IE */ + if (prTargetResult->u2IELength <= 600 && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0xDD, (PUINT_8 *) &prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); + } +#if CFG_SUPPORT_WPS + + /* IWEVGENIE for WPS IE */ + if ((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPSIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0xDD, (PUINT_8 *) &prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); + } +#endif + + /* IWEVGENIE for RSN IE */ + if ((prTargetResult->u2IELength <= 600) && wextSrchDesiredWPAIE(prTargetResult->pucIeBuf, + prTargetResult->u2IELength, + 0x30, (PUINT_8 *) &prDesiredIE)) { + + iwe.cmd = IWEVGENIE; + iwe.u.data.flags = 1; + iwe.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, (char *)prDesiredIE); + } + + /* IOC_P2P_GO_WSC_IE */ +#if 1 + /* device capability */ + if (1) { + UINT_8 data[40]; + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 9 + sizeof("p2p_cap="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_cap=%02x%02x%02x%02x%c", + prTargetResult->ucDeviceCapabilityBitmap, prTargetResult->ucGroupCapabilityBitmap, + (UINT_8) prTargetResult->u2ConfigMethod, + (UINT_8) (prTargetResult->u2ConfigMethod >> 8), '\0'); + current_ev = + iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + + /* printk("%s\n", data); */ + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 13 + sizeof("p2p_dev_type="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_dev_type=%02x%02x%02x%02x%02x%02x%c", + (UINT_8) prTargetResult->rPriDevType.u2CategoryID, + (UINT_8) prTargetResult->rPriDevType.u2SubCategoryID, + (UINT_8) prTargetResult->arSecDevType[0].u2CategoryID, + (UINT_8) prTargetResult->arSecDevType[0].u2SubCategoryID, + (UINT_8) prTargetResult->arSecDevType[1].u2CategoryID, + (UINT_8) prTargetResult->arSecDevType[1].u2SubCategoryID, '\0'); + current_ev = + iwe_stream_add_point(info, current_ev, extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + /* printk("%s\n", data); */ + + kalMemZero(data, 40); + + iwe.cmd = IWEVCUSTOM; + iwe.u.data.flags = 0; + iwe.u.data.length = 17 + sizeof("p2p_grp_bssid="); + if (iwe.u.data.length > 40) + iwe.u.data.length = 40; + + snprintf(data, iwe.u.data.length, "p2p_grp_bssid= %pM %c", + prTargetResult->aucBSSID, '\0'); + current_ev = iwe_stream_add_point(info, current_ev, + extra + IW_SCAN_MAX_DATA, &iwe, (char *)data); + /* printk("%s\n", data); */ + + } +#endif + } + + /* Length of data */ + wrqu->data.length = (current_ev - extra); + wrqu->data.flags = 0; + + return 0; +} /* end of mtk_p2p_wext_discovery_results() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_WSC_BEACON_PROBE_RSP_IE) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_HOSTAPD_PARAM prHostapdParam = (P_IW_P2P_HOSTAPD_PARAM) extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (prHostapdParam->len > 0) { + if (prHostapdParam->len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[0], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prHostapdParam->data, prHostapdParam->len)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[0] = prHostapdParam->len; + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prHostapdParam->len; + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + bssUpdateBeaconContent(prAdapter, NETWORK_TYPE_P2P_INDEX); + + /* @TODO: send message to P2P-FSM */ + + return 0; +} /* end of mtk_p2p_wext_wsc_ie() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_CONNECT_DISCONNECT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_point *prData = (struct iw_point *)&wrqu->data; +/* P_IW_P2P_CONNECT_DEVICE prConnectDevice = (P_IW_P2P_CONNECT_DEVICE)extra; */ +/* P_MSG_HDR_T prMsgHdr; */ +/* P_MSG_P2P_CONNECTION_REQUEST_T prMsgP2PConnReq; */ +/* P_MSG_P2P_CONNECTION_ABORT_T prMsgP2PConnAbt; */ +/* UINT_8 aucBCAddr[] = BC_MAC_ADDR; */ + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + if (prData->flags == P2P_CONNECT) { +#if 0 + /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_REQ */ + prMsgP2PConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (!prMsgP2PConnReq) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnReq, MSG_SEND_METHOD_BUF); +#endif + } else if (prData->flags == P2P_DISCONNECT) { +#if 0 + /* indicate P2P-FSM with MID_MNY_P2P_CONNECTION_ABORT */ + prMsgP2PConnAbt = (P_MSG_HDR_T) cnmMemAlloc(prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (!prMsgP2PConnAbt) { + ASSERT(0); /* Can't trigger P2P FSM */ + return -ENOMEM; + } + + COPY_MAC_ADDR(prMsgP2PConnAbt->aucTargetID, prConnectDevice->sta_addr); + + prMsgP2PConnAbt->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgP2PConnAbt, MSG_SEND_METHOD_BUF); +#endif + } else { + return -EINVAL; + } + + return 0; +} /* end of mtk_p2p_wext_connect_disconnect() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_PASSWORD_READY) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_PASSWORD_READY prPasswordReady = (P_IW_P2P_PASSWORD_READY) extra; + P_P2P_CONNECTION_SETTINGS_T prConnSettings; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + prConnSettings = prAdapter->rWifiVar.prP2PConnSettings; + + /* retrieve IE for Probe Request */ + if (prPasswordReady->probe_req_len > 0) { + if (prPasswordReady->probe_req_len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[1], prPasswordReady->probe_req_ie, + prPasswordReady->probe_req_len)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[1] = prPasswordReady->probe_req_len; + + /* retrieve IE for Probe Response */ + if (prPasswordReady->probe_rsp_len > 0) { + if (prPasswordReady->probe_rsp_len <= MAX_WSC_IE_LENGTH) { + if (copy_from_user + (prGlueInfo->prP2PInfo->aucWSCIE[2], prPasswordReady->probe_rsp_ie, + prPasswordReady->probe_rsp_len)) { + return -EFAULT; + } + } else { + return -E2BIG; + } + } + + prGlueInfo->prP2PInfo->u2WSCIELen[2] = prPasswordReady->probe_rsp_len; + + switch (prPasswordReady->active_config_method) { + case 1: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_PUSH_BUTTON; + break; + case 2: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_KEYPAD; + break; + case 3: + prConnSettings->u2LocalConfigMethod = WPS_ATTRI_CFG_METHOD_DISPLAY; + break; + default: + break; + } + + prConnSettings->fgIsPasswordIDRdy = TRUE; + return 0; +} /* end of mtk_p2p_wext_password_ready() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_REQ_DEVICE_INFO) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_DEVICE_REQ prDeviceReq = (P_IW_P2P_DEVICE_REQ) extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* specify data length */ + wrqu->data.length = sizeof(IW_P2P_DEVICE_REQ); + + /* copy to upper-layer supplied buffer */ + kalMemCopy(prDeviceReq->name, prGlueInfo->prP2PInfo->aucConnReqDevName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + prDeviceReq->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; + prDeviceReq->name[prDeviceReq->name_len] = '\0'; + COPY_MAC_ADDR(prDeviceReq->device_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); + prDeviceReq->device_type = prGlueInfo->prP2PInfo->ucConnReqDevType; + prDeviceReq->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; + prDeviceReq->active_config_method = prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod; + + return 0; +} /* end of mtk_p2p_wext_request_dev_info() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_IOCTL_INVITATION_INDICATE prInvIndicate = (P_IW_P2P_IOCTL_INVITATION_INDICATE) extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* specify data length */ + wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_INDICATE); + + /* copy to upper-layer supplied buffer */ + kalMemCopy(prInvIndicate->dev_name, prGlueInfo->prP2PInfo->aucConnReqDevName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + kalMemCopy(prInvIndicate->group_bssid, prGlueInfo->prP2PInfo->rConnReqGroupAddr, MAC_ADDR_LEN); + prInvIndicate->name_len = prGlueInfo->prP2PInfo->u4ConnReqNameLength; + prInvIndicate->dev_name[prInvIndicate->name_len] = '\0'; + COPY_MAC_ADDR(prInvIndicate->dev_addr, prGlueInfo->prP2PInfo->rConnReqPeerAddr); + prInvIndicate->config_method = prGlueInfo->prP2PInfo->i4ConnReqConfigMethod; + prInvIndicate->operating_channel = prGlueInfo->prP2PInfo->ucOperatingChnl; + prInvIndicate->invitation_type = prGlueInfo->prP2PInfo->ucInvitationType; + + return 0; +} /* end of mtk_p2p_wext_invitation_indicate() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_invitation_status(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_IOCTL_INVITATION_STATUS prInvStatus = (P_IW_P2P_IOCTL_INVITATION_STATUS) extra; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* specify data length */ + wrqu->data.length = sizeof(IW_P2P_IOCTL_INVITATION_STATUS); + + /* copy to upper-layer supplied buffer */ + prInvStatus->status_code = prGlueInfo->prP2PInfo->u4InvStatus; + + return 0; +} /* end of mtk_p2p_wext_invitation_status() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device found +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval TRUE Success. +* \retval FALSE Failure +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_FND"); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PDVCFND event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + + return FALSE; +} /* end of kalP2PIndicateFound() */ + +int +mtk_p2p_wext_set_network_address(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* @TODO: invoke wlan_p2p functions */ +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pNetworkAddress, + prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); +#endif + + return 0; + +} + +int +mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* @TODO: invoke wlan_p2p functions */ +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile, + prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); +#endif + + return 0; + +} + +int +mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prAdapter = prGlueInfo->prAdapter; + ASSERT(prAdapter); + + /* @TODO: invoke wlan_p2p functions */ +#if 0 + rStatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetP2pPowerSaveProfile, + prKey, prKey->u4Length, FALSE, FALSE, TRUE, &u4BufLen); +#endif + + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_start_formation(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int i4Status = 0; + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; +/* struct iw_point *prData = (struct iw_point*)&wrqu->data; */ + P_IW_P2P_IOCTL_START_FORMATION prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION) NULL; + + do { + if ((prDev == NULL) || (extra == NULL)) { + ASSERT(FALSE); + i4Status = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + prIoctlStartFormation = (P_IW_P2P_IOCTL_START_FORMATION) extra; + + if (prGlueInfo == NULL) { + i4Status = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; + + if (prAdapter == NULL) { + i4Status = -EINVAL; + break; + } + + } while (FALSE); + + return i4Status; + +} + +/* mtk_p2p_wext_start_formation */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_INT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Setting parameters not support. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_int(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 index; + INT_32 value; + PUINT_32 pu4IntBuf; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + P_P2P_FSM_INFO_T prP2pFsmInfo = (P_P2P_FSM_INFO_T) NULL; + UINT_32 u4Leng; + + ASSERT(prDev); + ASSERT(wrqu); + + /* printk("mtk_p2p_wext_set_int\n"); */ + pu4IntBuf = (PUINT_32) extra; + + if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + prP2pFsmInfo = prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo; + + u4SubCmd = (UINT_32) wrqu->mode; + index = pu4IntBuf[1]; + value = pu4IntBuf[2]; + + DBGLOG(P2P, INFO, "set parameter, u4SubCmd=%d idx=%d value=%d\n", (INT_16) u4SubCmd, (INT_16) index, value); + + switch (u4SubCmd) { + case PRIV_CMD_INT_P2P_SET: + switch (index) { + case 0: /* Listen CH */ + { + UINT_8 ucSuggestChnl = 0; + + prP2pConnSettings->ucListenChnl = value; + + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + if (rlmFuncFindAvailableChannel + (prGlueInfo->prAdapter, value, &ucSuggestChnl, TRUE, TRUE)) { + prP2pSpecificBssInfo->ucListenChannel = value; + } else { + prP2pSpecificBssInfo->ucListenChannel = ucSuggestChnl; + } + + break; + } + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, + (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, + (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + status = + mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); + break; + case 100: /* Oper CH */ + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + prP2pConnSettings->ucOperatingChnl = value; + break; + case 101: /* Local config Method, for P2P SDK */ + /* prP2pConnSettings->u2LocalConfigMethod; */ + break; + case 102: /* Sigma P2p reset */ + kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); + /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + status = + mtk_p2p_wext_set_oppps_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rOppPsParam); + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, + &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + + default: + break; + } + break; + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_SET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (FALSE == GLUE_CHK_PR2(prDev, wrqu)) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&prGlueInfo->prP2PInfo->aucOidBuf[0], sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEND_SD_RESPONSE: + status = mtk_p2p_wext_send_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_SEND_SD_REQUEST: + status = mtk_p2p_wext_send_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_TERMINATE_SD_PHASE: + status = mtk_p2p_wext_terminate_service_discovery_phase(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_INVITATION_STRUCT)) { + /* Do nothing */ + /* status = mtk_p2p_wext_invitation_request(prDev, info, wrqu, + (char *)(prP2PReq->aucBuffer)); */ + } + break; + + case P2P_CMD_ID_INVITATION_ABORT: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_ABORT_INVITATION)) { + /* Do nothing */ + /* status = mtk_p2p_wext_invitation_abort(prDev, info, wrqu, + (char *)(prP2PReq->aucBuffer)); */ + } + break; + + case P2P_CMD_ID_START_FORMATION: + if (prP2PReq->inBufferLength == sizeof(IW_P2P_IOCTL_START_FORMATION)) + status = mtk_p2p_wext_start_formation(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + break; + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (wrqu->data.length > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), wrqu->data.pointer, wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), extra, wrqu->data.length)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_set_sec_check_request(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), wrqu->data.pointer, wrqu->data.length)) { + status = -EFAULT; + break; + } + + if (!kalMemCmp(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), extra, wrqu->data.length)) + DBGLOG(P2P, INFO, "extra buffer is valid\n"); + else + DBGLOG(P2P, INFO, "extra 0x%p\n", extra); + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_set_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + break; + default: + status = -EOPNOTSUPP; + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler (IOC_P2P_GET_STRUCT) +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + int status = 0; + UINT_32 u4SubCmd = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = NULL; + + ASSERT(prDev); + ASSERT(wrqu); + + if (!prDev || !wrqu) { + DBGLOG(P2P, WARN, "%s(): invalid param(0x%p, 0x%p)\n", __func__, prDev, wrqu); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + u4SubCmd = (UINT_32) wrqu->data.flags; + + kalMemZero(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), sizeof(prGlueInfo->prP2PInfo->aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_GET_SD_REQUEST: + status = mtk_p2p_wext_get_service_discovery_request(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_GET_SD_RESPONSE: + status = mtk_p2p_wext_get_service_discovery_response(prDev, info, wrqu, (char *)prP2PReq); + break; + + case P2P_CMD_ID_INVITATION_INDICATE: + { + status = + mtk_p2p_wext_invitation_indicate(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + case P2P_CMD_ID_INVITATION_STATUS: + { + status = + mtk_p2p_wext_invitation_status(prDev, info, wrqu, (char *)(prP2PReq->aucBuffer)); + prP2PReq->outBufferLength = wrqu->data.length; + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.length + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + case P2P_CMD_ID_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + RF_CHANNEL_INFO_T aucChannelList[50]; + UINT_8 ucMaxChannelNum = 50; + PUINT_8 pucChnlList = (PUINT_8) prP2PReq->aucBuffer; + + kalGetChnlList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, aucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + prP2PReq->outBufferLength = NumOfChannel; + /*here must confirm NumOfChannel < 16, for prP2PReq->aucBuffer 16 byte*/ + if (NumOfChannel >= 15) { + /*DBGLOG(P2P, ERROR, "channel num > 15\n", __func__);*/ + ASSERT(FALSE); + } + + for (i = 0; i < NumOfChannel; i++) { +#if 0 + /* 20120208 frog: modify to avoid clockwork warning. */ + prP2PReq->aucBuffer[i] = aucChannelList[i].ucChannelNum; +#else + *pucChnlList = aucChannelList[i].ucChannelNum; + pucChnlList++; +#endif + } + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + NumOfChannel + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } + break; + } + + case P2P_CMD_ID_GET_OP_CH: + { + prP2PReq->inBufferLength = 4; + + status = wlanoidQueryP2pOpChannel(prGlueInfo->prAdapter, + prP2PReq->aucBuffer, + prP2PReq->inBufferLength, &prP2PReq->outBufferLength); + + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, + aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + break; + } + + default: + status = -EOPNOTSUPP; + } + + break; +#if CFG_SUPPORT_ANTI_PIRACY + case PRIV_SEC_CHECK_OID: + if (wrqu->data.length > 256) { + status = -EOPNOTSUPP; + break; + } + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucSecCheck[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucSecCheck[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_SEC_CHECK: + status = mtk_p2p_wext_get_sec_check_response(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + } + break; +#endif + case PRIV_CMD_P2P_VERSION: + if (copy_from_user(&(prGlueInfo->prP2PInfo->aucOidBuf[0]), + wrqu->data.pointer, sizeof(IW_P2P_TRANSPORT_STRUCT))) { + DBGLOG(P2P, ERROR, "%s() copy_from_user oidBuf fail\n", __func__); + return -EFAULT; + } + + prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) (&(prGlueInfo->prP2PInfo->aucOidBuf[0])); + + switch (prP2PReq->u4CmdId) { + case P2P_CMD_ID_P2P_VERSION: + status = mtk_p2p_wext_get_p2p_version(prDev, info, wrqu, (char *)prP2PReq); + break; + default: + status = -EOPNOTSUPP; + break; + } + + /* Copy queried data to user. */ + if (status == 0) { /* WLAN_STATUS_SUCCESS */ + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + prP2PReq->outBufferLength + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + else { + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + } + + break; + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery request frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDRequest, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } else { + return 0; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* getting service discovery response frame from driver +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidGetP2PSDResponse, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + &(prGlueInfo->prP2PInfo->aucOidBuf[0]), + u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + return 0; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery request frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDRequest, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* sending service discovery response frame +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSendP2PSDResponse, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetSecCheckRequest, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_get_sec_check_response\n"); + rStatus = kalIoctl(prGlueInfo, + wlanoidGetSecCheckResponse, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prP2PReq->outBufferLength = u4QueryInfoLen; + + if (copy_to_user(wrqu->data.pointer, + prP2PReq->aucBuffer, u4QueryInfoLen + OFFSET_OF(IW_P2P_TRANSPORT_STRUCT, aucBuffer))) { + DBGLOG(P2P, ERROR, "%s() copy_to_user() fail\n", __func__); + return -EIO; + } + return 0; + +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* terminating service discovery phase +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2PTerminateSDPhase, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; + /* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ + P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T prNoaParam = (P_PARAM_CUSTOM_NOA_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_set_noa_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetNoaParam, prNoaParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_NOA_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief P2P Private I/O Control handler for +* +* \param[in] prDev Net device requested. +* \param[inout] wrqu Pointer to iwreq_data +* +* \retval 0 Success. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4SetInfoLen; +/* P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT)extra; */ + P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T prOppPsParam = (P_PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + DBGLOG(P2P, INFO, "mtk_p2p_wext_set_oppps_param\n"); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetOppPsParam, prOppPsParam, /* prP2PReq->aucBuffer, */ + sizeof(PARAM_CUSTOM_OPPPS_PARAM_STRUCT_T), /* prP2PReq->inBufferLength, */ + FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return 0; +} + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + UINT_32 u4SetInfoLen; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSupplicantVersion, + prP2PReq->aucBuffer, prP2PReq->inBufferLength, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} + +/* mtk_p2p_wext_set_p2p_version */ + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + P_IW_P2P_TRANSPORT_STRUCT prP2PReq = (P_IW_P2P_TRANSPORT_STRUCT) extra; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pVersion, + prP2PReq->aucBuffer, prP2PReq->outBufferLength, TRUE, FALSE, TRUE, TRUE, &u4QueryInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_p2p_version */ + +#if CFG_SUPPORT_P2P_RSSI_QUERY + +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen; + struct iw_point *prData = (struct iw_point *)&wrqu->data; + UINT_16 u2BufferSize = 0; + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rssi; + struct iw_statistics *pStats = NULL; + + ASSERT(prDev); + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + + if (!prGlueInfo) { + rStatus = WLAN_STATUS_FAILURE; + goto stat_out; + } + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &u4QueryInfoLen); + + u2BufferSize = prData->length; + + if (u2BufferSize < sizeof(struct iw_statistics)) + return -E2BIG; + + if (copy_to_user(prData->pointer, pStats, sizeof(struct iw_statistics))) + rStatus = WLAN_STATUS_FAILURE; + +stat_out: + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + else + return rStatus; + +} /* mtk_p2p_wext_get_rssi */ + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev) +{ + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + pStats = (struct iw_statistics *)(&(prGlueInfo->rP2pIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryP2pRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, TRUE, &bufLen); + +stat_out: + return pStats; +} /* mtk_p2p_wext_get_wireless_stats */ + +#endif /* CFG_SUPPORT_P2P_RSSI_QUERY */ + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_ADAPTER_T prAdapter = (P_ADAPTER_T) NULL; +#if 0 + P_MSG_P2P_FUNCTION_SWITCH_T prMsgFuncSwitch = (P_MSG_P2P_FUNCTION_SWITCH_T) NULL; +#endif + int i4Ret = 0; + + ASSERT(prDev); + ASSERT(prTxPow); + + do { + if ((!prDev) || (!prTxPow)) { + i4Ret = -EINVAL; + break; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (!prGlueInfo) { + i4Ret = -EINVAL; + break; + } + + prAdapter = prGlueInfo->prAdapter; +#if 0 + prMsgFuncSwitch = + (P_MSG_P2P_FUNCTION_SWITCH_T) cnmMemAlloc(prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_FUNCTION_SWITCH_T)); + if (!prMsgFuncSwitch) { + ASSERT(0); + return -ENOMEM; + } + + prMsgFuncSwitch->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + if (prTxPow->disabled) { + /* Dissolve. */ + prMsgFuncSwitch->fgIsFuncOn = FALSE; + } else { + + /* Re-enable function. */ + prMsgFuncSwitch->fgIsFuncOn = TRUE; + } + + /* 1.3 send message */ + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgFuncSwitch, MSG_SEND_METHOD_BUF); +#endif + + } while (FALSE); + + return i4Ret; +} /* mtk_p2p_wext_set_txpow */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c new file mode 100644 index 0000000000000..4d71e0c59b05d --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_cfg80211.c @@ -0,0 +1,1935 @@ +/* +** Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_cfg80211.c + \brief Main routines of Linux driver interface for Wi-Fi Direct + using cfg80211 interface + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_p2p_cfg80211.c +** +** 01 30 2013 yuche.tsai +** [ALPS00455459] [GN_WIFI]??wifi direct??????????? +** Fix possible race condition under GO mode. +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 09 05 2012 wh.su +** [ALPS00351547] [6577JB][WiFi direct]The 3rd device fail to establish p2p connection with GO sometimes +** sync with the ICS code. +** +** 08 31 2012 yuche.tsai +** [ALPS00349585] [6577JB][WiFi direct][KE]Establish p2p connection while both device have connected to AP previously, +** one device reboots automatically with KE +** Fix possible KE when concurrent & disconnect. +** +** 08 21 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. +** +** 08 17 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 16 2012 yuche.tsai +** NULL +** Fix compile warning. +** +** 08 14 2012 yuche.tsai +** NULL +** Fix p2p bug find on ALPS.JB trunk. +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Fix compile error for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#include +#include +#include +#include +#include + +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_p2p_ioctl.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wformat" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +BOOLEAN +mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel, + IN enum nl80211_channel_type channel_type, + IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int mtk_p2p_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + P2P_PARAM_KEY_T rKey; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&rKey, sizeof(P2P_PARAM_KEY_T)); + + rKey.u4KeyIndex = key_index; + if (mac_addr) { + ether_addr_copy(rKey.arBSSID, mac_addr); + if ((rKey.arBSSID[0] == 0x00) && (rKey.arBSSID[1] == 0x00) && (rKey.arBSSID[2] == 0x00) && + (rKey.arBSSID[3] == 0x00) && (rKey.arBSSID[4] == 0x00) && (rKey.arBSSID[5] == 0x00)) { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + } + if (rKey.arBSSID[0] != 0xFF) { + rKey.u4KeyIndex |= BIT(31); + if ((rKey.arBSSID[0] != 0x00) || (rKey.arBSSID[1] != 0x00) || (rKey.arBSSID[2] != 0x00) || + (rKey.arBSSID[3] != 0x00) || (rKey.arBSSID[4] != 0x00) || (rKey.arBSSID[5] != 0x00)) + rKey.u4KeyIndex |= BIT(30); + } else { + rKey.u4KeyIndex |= BIT(31); + } + } else { + rKey.arBSSID[0] = 0xff; + rKey.arBSSID[1] = 0xff; + rKey.arBSSID[2] = 0xff; + rKey.arBSSID[3] = 0xff; + rKey.arBSSID[4] = 0xff; + rKey.arBSSID[5] = 0xff; + rKey.u4KeyIndex |= BIT(31); /* ???? */ + } + if (params->key) { + /* rKey.aucKeyMaterial[0] = kalMemAlloc(params->key_len, VIR_MEM_TYPE); */ + kalMemCopy(rKey.aucKeyMaterial, params->key, params->key_len); + } + rKey.u4KeyLength = params->key_len; + rKey.u4Length = ((ULONG)&(((P_P2P_PARAM_KEY_T) 0)->aucKeyMaterial)) + rKey.u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetAddP2PKey, &rKey, rKey.u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +int mtk_p2p_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) +) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_REMOVE_KEY_T prRemoveKey; + INT_32 i4Rslt = -EINVAL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (prGlueInfo->ulFlag & GLUE_FLAG_HALT) { + i4Rslt = 0; + return i4Rslt; + } + + kalMemZero(&prRemoveKey, sizeof(PARAM_REMOVE_KEY_T)); + if (mac_addr) + memcpy(prRemoveKey.arBSSID, mac_addr, PARAM_MAC_ADDR_LEN); + prRemoveKey.u4KeyIndex = key_index; + prRemoveKey.u4Length = sizeof(PARAM_REMOVE_KEY_T); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveP2PKey, + &prRemoveKey, prRemoveKey.u4Length, FALSE, FALSE, TRUE, TRUE, &u4BufLen); + + if (rStatus == WLAN_STATUS_SUCCESS) + i4Rslt = 0; + + return i4Rslt; +} + +int +mtk_p2p_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *netdev, u8 key_index, bool unicast, bool multicast) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return WLAN_STATUS_SUCCESS; +} + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo) +{ + INT_32 i4RetRslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P2P_STATION_INFO_T rP2pStaInfo; + + ASSERT(wiphy); + + do { + if ((wiphy == NULL) || (ndev == NULL) || (sinfo == NULL) || (mac == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_get_station\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + sinfo->filled = 0; + + /* Get station information. */ + /* 1. Inactive time? */ + p2pFuncGetStationInfo(prGlueInfo->prAdapter, (PUINT_8)mac, &rP2pStaInfo); + + /* Inactive time. */ + sinfo->filled |= NL80211_STA_INFO_INACTIVE_TIME; + sinfo->inactive_time = rP2pStaInfo.u4InactiveTime; + sinfo->generation = prP2pGlueInfo->i4Generation; + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_SCAN_REQUEST_T prMsgScanRequest = (P_MSG_P2P_SCAN_REQUEST_T) NULL; + UINT_32 u4MsgSize = 0, u4Idx = 0; + INT_32 i4RetRslt = -EINVAL; + P_RF_CHANNEL_INFO_T prRfChannelInfo = (P_RF_CHANNEL_INFO_T) NULL; + P_P2P_SSID_STRUCT_T prSsidStruct = (P_P2P_SSID_STRUCT_T) NULL; + struct ieee80211_channel *prChannel = NULL; + struct cfg80211_ssid *prSsid = NULL; + + /* [---------Channel---------] [---------SSID---------][---------IE---------] */ + DBGLOG(INIT, TRACE, "mtk_p2p_cfg80211_scan\n"); + + do { + if ((wiphy == NULL) || (request == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (prP2pGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_scan.\n"); + + if (prP2pGlueInfo->prScanRequest != NULL) { + /* There have been a scan request on-going processing. */ + DBGLOG(P2P, TRACE, "There have been a scan request on-going processing.\n"); + break; + } + + prP2pGlueInfo->prScanRequest = request; + + /* Should find out why the n_channels so many? */ + if (request->n_channels > MAXIMUM_OPERATION_CHANNEL_LIST) { + request->n_channels = MAXIMUM_OPERATION_CHANNEL_LIST; + DBGLOG(P2P, TRACE, "Channel list exceed the maximun support.\n"); + } + + u4MsgSize = sizeof(MSG_P2P_SCAN_REQUEST_T) + + (request->n_channels * sizeof(RF_CHANNEL_INFO_T)) + + (request->n_ssids * sizeof(PARAM_SSID_T)) + request->ie_len; + + prMsgScanRequest = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, u4MsgSize); + + if (prMsgScanRequest == NULL) { + ASSERT(FALSE); + i4RetRslt = -ENOMEM; + prP2pGlueInfo->prScanRequest = NULL; + DBGLOG(INIT, TRACE, "mtk_p2p_cfg80211_scan Allocate Mem failed\n"); + break; + } + + DBGLOG(P2P, TRACE, "Generating scan request message.\n"); + + prMsgScanRequest->rMsgHdr.eMsgId = MID_MNY_P2P_DEVICE_DISCOVERY; + + DBGLOG(P2P, INFO, "Requesting channel number:%d.\n", request->n_channels); + + for (u4Idx = 0; u4Idx < request->n_channels; u4Idx++) { + /* Translate Freq from MHz to channel number. */ + prRfChannelInfo = &(prMsgScanRequest->arChannelListInfo[u4Idx]); + prChannel = request->channels[u4Idx]; + + prRfChannelInfo->ucChannelNum = nicFreq2ChannelNum(prChannel->center_freq * 1000); + DBGLOG(P2P, TRACE, "Scanning Channel:%d, freq: %d\n", + prRfChannelInfo->ucChannelNum, prChannel->center_freq); + switch (prChannel->band) { + case NL80211_BAND_2GHZ: + prRfChannelInfo->eBand = BAND_2G4; + break; + case NL80211_BAND_5GHZ: + prRfChannelInfo->eBand = BAND_5G; + break; + default: + DBGLOG(P2P, TRACE, "UNKNOWN Band info from supplicant\n"); + prRfChannelInfo->eBand = BAND_NULL; + break; + } + + /* Iteration. */ + prRfChannelInfo++; + } + prMsgScanRequest->u4NumChannel = request->n_channels; + + DBGLOG(P2P, TRACE, "Finish channel list.\n"); + + /* SSID */ + prSsid = request->ssids; + prSsidStruct = (P_P2P_SSID_STRUCT_T) prRfChannelInfo; + if (prSsidStruct) { + if (request->n_ssids) { + ASSERT((ULONG) prSsidStruct == (ULONG)&(prMsgScanRequest->arChannelListInfo[u4Idx])); + prMsgScanRequest->prSSID = prSsidStruct; + } + + for (u4Idx = 0; u4Idx < request->n_ssids; u4Idx++) { + COPY_SSID(prSsidStruct->aucSsid, + prSsidStruct->ucSsidLen, request->ssids->ssid, request->ssids->ssid_len); + + prSsidStruct++; + prSsid++; + } + + prMsgScanRequest->i4SsidNum = request->n_ssids; + + DBGLOG(P2P, TRACE, "Finish SSID list:%d.\n", request->n_ssids); + + /* IE BUFFERS */ + prMsgScanRequest->pucIEBuf = (PUINT_8) prSsidStruct; + if (request->ie_len) { + kalMemCopy(prMsgScanRequest->pucIEBuf, request->ie, request->ie_len); + prMsgScanRequest->u4IELen = request->ie_len; + } + } + + DBGLOG(P2P, TRACE, "Finish IE Buffer.\n"); +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + prGlueInfo->prAdapter->rWifiVar.rChnLoadInfo.fgDataReadyBit = FALSE; +#endif + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgScanRequest, MSG_SEND_METHOD_BUF); + + i4RetRslt = 0; + } while (FALSE); + + return i4RetRslt; +} /* mtk_p2p_cfg80211_scan */ + +int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_wiphy_params\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (changed & WIPHY_PARAM_RETRY_SHORT) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY short param is changed.\n"); + } + + if (changed & WIPHY_PARAM_RETRY_LONG) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY long param is changed.\n"); + } + + if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY fragmentation threshold is changed.\n"); + } + + if (changed & WIPHY_PARAM_RTS_THRESHOLD) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The RETRY RTS threshold is changed.\n"); + } + + if (changed & WIPHY_PARAM_COVERAGE_CLASS) { + /* TODO: */ + DBGLOG(P2P, TRACE, "The coverage class is changed???\n"); + } + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_wiphy_params */ + +int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_tx_power_setting type, int mbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, + int *dbm) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + + return -EINVAL; +} + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 value; + UINT_32 u4Leng; + + ASSERT(wiphy); + + if (enabled) + value = 2; + else + value = 0; + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_power_mgmt ps=%d.\n", enabled); + + /* p2p_set_power_save */ + kalIoctl(prGlueInfo, wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + return 0; +} + +/* &&&&&&&&&&&&&&&&&&&&&&&&&& Add for ICS Wi-Fi Direct Support. &&&&&&&&&&&&&&&&&&&&&&& */ +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; + P_MSG_P2P_START_AP_T prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) NULL; + PUINT_8 pucBuffer = (PUINT_8) NULL; + /* P_IE_SSID_T prSsidIE = (P_IE_SSID_T)NULL; */ + + struct wireless_dev *wdev = dev->ieee80211_ptr; + struct cfg80211_chan_def *chandef = &wdev->preset_chandef; + + do { + if ((wiphy == NULL) || (settings == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_start_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if 1 + mtk_p2p_cfg80211_set_channel(wiphy, chandef); +#else + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings->ucOperatingChnl = + (chandef->chan->center_freq - 2407) / 5; + prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings->eBand = BAND_2G4; +#endif + + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + + settings->beacon.head_len + + settings->beacon.tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (settings->beacon.head_len != 0) { + kalMemCopy(pucBuffer, settings->beacon.head, settings->beacon.head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = settings->beacon.head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (UINT_32) settings->beacon.head_len); + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (settings->beacon.tail_len != 0) { + UINT_32 ucLen = settings->beacon.tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + + /*Add TIM IE */ + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; + /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ + TIM_IE(pucBuffer)->ucDTIMCount = 0 /*prBssInfo->ucDTIMCount */; /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucDTIMPeriod = 1; + TIM_IE(pucBuffer)->ucBitmapControl = 0 /*ucBitmapControl | (UINT_8)u4N1 */; + /* will be overwrite by FW */ + ucLen += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + kalMemCopy(pucBuffer, settings->beacon.tail, settings->beacon.tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + + prP2pStartAPMsg = (P_MSG_P2P_START_AP_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, sizeof(MSG_P2P_START_AP_T)); + + if (prP2pStartAPMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pStartAPMsg->rMsgHdr.eMsgId = MID_MNY_P2P_START_AP; + + prP2pStartAPMsg->fgIsPrivacy = settings->privacy; + + prP2pStartAPMsg->u4BcnInterval = settings->beacon_interval; + + prP2pStartAPMsg->u4DtimPeriod = settings->dtim_period; + + /* Copy NO SSID. */ + prP2pStartAPMsg->ucHiddenSsidType = settings->hidden_ssid; + + COPY_SSID(prP2pStartAPMsg->aucSsid, prP2pStartAPMsg->u2SsidLen, settings->ssid, settings->ssid_len); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pStartAPMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_LOCK(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); +#endif + + } while (FALSE); + + return i4Rslt; + +/* /////////////////////// */ + /** + * struct cfg80211_ap_settings - AP configuration + * + * Used to configure an AP interface. + * + * @beacon: beacon data + * @beacon_interval: beacon interval + * @dtim_period: DTIM period + * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from + * user space) + * @ssid_len: length of @ssid + * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames + * @crypto: crypto settings + * @privacy: the BSS uses privacy + * @auth_type: Authentication type (algorithm) + * @inactivity_timeout: time in seconds to determine station's inactivity. + */ +/* struct cfg80211_ap_settings { */ +/* struct cfg80211_beacon_data beacon; */ +/* */ +/* int beacon_interval, dtim_period; */ +/* const u8 *ssid; */ +/* size_t ssid_len; */ +/* enum nl80211_hidden_ssid hidden_ssid; */ +/* struct cfg80211_crypto_settings crypto; */ +/* bool privacy; */ +/* enum nl80211_auth_type auth_type; */ +/* int inactivity_timeout; */ +/* }; */ +/* ////////////////// */ + + return i4Rslt; +} /* mtk_p2p_cfg80211_start_ap */ + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_BEACON_UPDATE_T prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) NULL; + PUINT_8 pucBuffer = (PUINT_8) NULL; + + do { + if ((wiphy == NULL) || (info == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_beacon.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pBcnUpdateMsg = (P_MSG_P2P_BEACON_UPDATE_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + (sizeof(MSG_P2P_BEACON_UPDATE_T) + + info->head_len + info->tail_len)); + + if (prP2pBcnUpdateMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pBcnUpdateMsg->rMsgHdr.eMsgId = MID_MNY_P2P_BEACON_UPDATE; + pucBuffer = prP2pBcnUpdateMsg->aucBuffer; + + if (info->head_len != 0) { + kalMemCopy(pucBuffer, info->head, info->head_len); + + prP2pBcnUpdateMsg->u4BcnHdrLen = info->head_len; + + prP2pBcnUpdateMsg->pucBcnHdr = pucBuffer; + + pucBuffer = (PUINT_8) ((ULONG) pucBuffer + (UINT_32) info->head_len); + } else { + prP2pBcnUpdateMsg->u4BcnHdrLen = 0; + + prP2pBcnUpdateMsg->pucBcnHdr = NULL; + } + + if (info->tail_len != 0) { + UINT_32 ucLen = info->tail_len; + + prP2pBcnUpdateMsg->pucBcnBody = pucBuffer; + + /*Add TIM IE */ + /* IEEE 802.11 2007 - 7.3.2.6 */ + TIM_IE(pucBuffer)->ucId = ELEM_ID_TIM; + TIM_IE(pucBuffer)->ucLength = (3 + MAX_LEN_TIM_PARTIAL_BMP) /*((u4N2 - u4N1) + 4) */; + /* NOTE: fixed PVB length (AID is allocated from 8 ~ 15 only) */ + TIM_IE(pucBuffer)->ucDTIMCount = 0 /*prBssInfo->ucDTIMCount */; /* will be overwrite by FW */ + TIM_IE(pucBuffer)->ucDTIMPeriod = 1; + TIM_IE(pucBuffer)->ucBitmapControl = 0 /*ucBitmapControl | (UINT_8)u4N1 */; + /* will be overwrite by FW */ + ucLen += IE_SIZE(pucBuffer); + pucBuffer += IE_SIZE(pucBuffer); + + kalMemCopy(pucBuffer, info->tail, info->tail_len); + + prP2pBcnUpdateMsg->u4BcnBodyLen = ucLen; + } else { + prP2pBcnUpdateMsg->u4BcnBodyLen = 0; + + prP2pBcnUpdateMsg->pucBcnBody = NULL; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pBcnUpdateMsg, MSG_SEND_METHOD_BUF); + +/* ////////////////////////// */ +/** + * struct cfg80211_beacon_data - beacon data + * @head: head portion of beacon (before TIM IE) + * or %NULL if not changed + * @tail: tail portion of beacon (after TIM IE) + * or %NULL if not changed + * @head_len: length of @head + * @tail_len: length of @tail + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets + * @probe_resp_len: length of probe response template (@probe_resp) + * @probe_resp: probe response template (AP mode only) + */ +/* struct cfg80211_beacon_data { */ +/* const u8 *head, *tail; */ +/* const u8 *beacon_ies; */ +/* const u8 *proberesp_ies; */ +/* const u8 *assocresp_ies; */ +/* const u8 *probe_resp; */ + +/* size_t head_len, tail_len; */ +/* size_t beacon_ies_len; */ +/* size_t proberesp_ies_len; */ +/* size_t assocresp_ies_len; */ +/* size_t probe_resp_len; */ +/* }; */ + +/* ////////////////////////// */ + + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_beacon */ + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_SWITCH_OP_MODE_T prP2pSwitchMode = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_stop_ap.\n"); + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* Switch OP MOde. */ + prP2pSwitchMode = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_SWITCH_OP_MODE_T)); + + if (prP2pSwitchMode == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prP2pSwitchMode->rMsgHdr.eMsgId = MID_MNY_P2P_STOP_AP; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pSwitchMode, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT + if (glIsChipNeedWakelock(prGlueInfo)) + KAL_WAKE_UNLOCK(prGlueInfo->prAdapter, &prGlueInfo->prAdapter->rApWakeLock); +#endif + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_stop_ap */ + +/* TODO: */ +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* not implemented yet */ + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_deauth.\n"); + + return -EINVAL; +} /* mtk_p2p_cfg80211_deauth */ + +/* TODO: */ +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_disassoc.\n"); + + /* not implemented yet */ + + return -EINVAL; +} /* mtk_p2p_cfg80211_disassoc */ + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + P_MSG_P2P_CHNL_REQUEST_T prMsgChnlReq = (P_MSG_P2P_CHNL_REQUEST_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (chan == NULL) || (cookie == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + *cookie = prGlueP2pInfo->u8Cookie++; + + prMsgChnlReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_REQUEST_T)); + + if (prMsgChnlReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_remain_on_channel\n"); + + prMsgChnlReq->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_REQ; + prMsgChnlReq->u8Cookie = *cookie; + prMsgChnlReq->u4Duration = duration; + + mtk_p2p_cfg80211func_channel_format_switch(chan, NL80211_CHAN_HT20, /* 4 KH Need Check */ + &prMsgChnlReq->rChannelInfo, &prMsgChnlReq->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} + +/* mtk_p2p_cfg80211_remain_on_channel */ +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + u64 cookie) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_MSG_P2P_CHNL_ABORT_T prMsgChnlAbort = (P_MSG_P2P_CHNL_ABORT_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prMsgChnlAbort = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_CHNL_ABORT_T)); + + if (prMsgChnlAbort == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_cancel_remain_on_channel\n"); + + prMsgChnlAbort->rMsgHdr.eMsgId = MID_MNY_P2P_CHNL_ABORT; + prMsgChnlAbort->u8Cookie = cookie; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgChnlAbort, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_cancel_remain_on_channel */ + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T *prMsgExtListenReq = NULL; + P_MSG_P2P_MGMT_TX_REQUEST_T prMsgTxReq = (P_MSG_P2P_MGMT_TX_REQUEST_T) NULL; + P_MSDU_INFO_T prMgmtFrame = (P_MSDU_INFO_T) NULL; + PUINT_8 pucFrameBuf = (PUINT_8) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL) || (params == 0) || (cookie == NULL)) + break; + /* DBGLOG(P2P, TRACE, ("mtk_p2p_cfg80211_mgmt_tx\n")); */ + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + *cookie = prGlueP2pInfo->u8Cookie++; + + /* Channel & Channel Type & Wait time are ignored. */ + prMsgTxReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_P2P_MGMT_TX_REQUEST_T)); + + if (prMsgTxReq == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + /* Here need to extend the listen interval */ + prMsgExtListenReq = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(struct _MSG_P2P_EXTEND_LISTEN_INTERVAL_T)); + if (prMsgExtListenReq) { + prMsgExtListenReq->rMsgHdr.eMsgId = MID_MNY_P2P_EXTEND_LISTEN_INTERVAL; + prMsgExtListenReq->wait = params->wait; + DBGLOG(P2P, INFO, "ext listen, wait: %d\n", prMsgExtListenReq->wait); + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T)prMsgExtListenReq, + MSG_SEND_METHOD_BUF); + } + + prMsgTxReq->fgNoneCckRate = FALSE; + prMsgTxReq->fgIsWaitRsp = TRUE; + + prMgmtFrame = cnmMgtPktAlloc(prGlueInfo->prAdapter, (UINT_32) (params->len + MAC_TX_RESERVED_FIELD)); + + prMsgTxReq->prMgmtMsduInfo = prMgmtFrame; + if (prMsgTxReq->prMgmtMsduInfo == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prMsgTxReq->u8Cookie = *cookie; + prMsgTxReq->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_TX; + + pucFrameBuf = (PUINT_8) ((ULONG) prMgmtFrame->prPacket + MAC_TX_RESERVED_FIELD); + + kalMemCopy(pucFrameBuf, params->buf, params->len); + + prMgmtFrame->u2FrameLength = params->len; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgTxReq, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + if ((i4Rslt != 0) && (prMsgTxReq != NULL)) { + if (prMsgTxReq->prMgmtMsduInfo != NULL) + cnmMgtPktFree(prGlueInfo->prAdapter, prMsgTxReq->prMgmtMsduInfo); + + cnmMemFree(prGlueInfo->prAdapter, prMsgTxReq); + } + + return i4Rslt; +} /* mtk_p2p_cfg80211_mgmt_tx */ + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + switch (params->use_cts_prot) { + case -1: + DBGLOG(P2P, TRACE, "CTS protection no change\n"); + break; + case 0: + DBGLOG(P2P, TRACE, "CTS protection disable.\n"); + break; + case 1: + DBGLOG(P2P, TRACE, "CTS protection enable\n"); + break; + default: + DBGLOG(P2P, TRACE, "CTS protection unknown\n"); + break; + } + + switch (params->use_short_preamble) { + case -1: + DBGLOG(P2P, TRACE, "Short prreamble no change\n"); + break; + case 0: + DBGLOG(P2P, TRACE, "Short prreamble disable.\n"); + break; + case 1: + DBGLOG(P2P, TRACE, "Short prreamble enable\n"); + break; + default: + DBGLOG(P2P, TRACE, "Short prreamble unknown\n"); + break; + } + +#if 0 + /* not implemented yet */ + p2pFuncChangeBssParam(prGlueInfo->prAdapter, + prBssInfo->fgIsProtection, + prBssInfo->fgIsShortPreambleAllowed, prBssInfo->fgUseShortSlotTime, + /* Basic rates */ + /* basic rates len */ + /* ap isolate */ + /* ht opmode. */ + ); +#else + i4Rslt = 0; +#endif + + return i4Rslt; +} /* mtk_p2p_cfg80211_change_bss */ + +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) +//int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBcMac[] = BC_MAC_ADDR; + const UINT_8 *mac = NULL; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + if (params->mac == NULL) + mac = aucBcMac; + else + mac = params->mac; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_del_station.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* prDisconnectMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(MSG_P2P_CONNECTION_ABORT_T), + VIR_MEM_TYPE); */ + prDisconnectMsg = + (P_MSG_P2P_CONNECTION_ABORT_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (prDisconnectMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prDisconnectMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + COPY_MAC_ADDR(prDisconnectMsg->aucTargetID, mac); + prDisconnectMsg->u2ReasonCode = REASON_CODE_UNSPECIFIED; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnectMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_del_station */ + +int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_REQUEST_T prConnReqMsg = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (sme == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_connect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prConnReqMsg = + (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + (sizeof(MSG_P2P_CONNECTION_REQUEST_T) + sme->ie_len)); + + if (prConnReqMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prConnReqMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + COPY_SSID(prConnReqMsg->rSsid.aucSsid, prConnReqMsg->rSsid.ucSsidLen, sme->ssid, sme->ssid_len); + + COPY_MAC_ADDR(prConnReqMsg->aucBssid, sme->bssid); + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_connect to %pM, IE len: %d\n", + prConnReqMsg->aucBssid, sme->ie_len); + + DBGLOG(P2P, TRACE, "Assoc Req IE Buffer Length:%d\n", sme->ie_len); + kalMemCopy(prConnReqMsg->aucIEBuf, sme->ie, sme->ie_len); + prConnReqMsg->u4IELen = sme->ie_len; + + mtk_p2p_cfg80211func_channel_format_switch(sme->channel, + NL80211_CHAN_NO_HT, + &prConnReqMsg->rChannelInfo, &prConnReqMsg->eChnlSco); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prConnReqMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_connect */ + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = NULL; + P_MSG_P2P_CONNECTION_ABORT_T prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T) NULL; + UINT_8 aucBCAddr[] = BC_MAC_ADDR; + + do { + if ((wiphy == NULL) || (dev == NULL)) + break; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +/* prDisconnMsg = (P_MSG_P2P_CONNECTION_ABORT_T)kalMemAlloc(sizeof(P_MSG_P2P_CONNECTION_ABORT_T), VIR_MEM_TYPE); */ + prDisconnMsg = + (P_MSG_P2P_CONNECTION_ABORT_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_ABORT_T)); + + if (prDisconnMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_disconnect.Allocate Memory Failed.\n"); + break; + } + + prDisconnMsg->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_ABORT; + prDisconnMsg->u2ReasonCode = reason_code; + prDisconnMsg->fgSendDeauth = TRUE; + COPY_MAC_ADDR(prDisconnMsg->aucTargetID, aucBCAddr); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prDisconnMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_disconnect */ + +int +mtk_p2p_cfg80211_change_iface(IN struct wiphy *wiphy, + IN struct net_device *ndev, + IN enum nl80211_iftype type,/* IN u32 *flags,*/ IN struct vif_params *params) +{ + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + INT_32 i4Rslt = -EINVAL; + P_MSG_P2P_SWITCH_OP_MODE_T prSwitchModeMsg = (P_MSG_P2P_SWITCH_OP_MODE_T) NULL; + + do { + if ((wiphy == NULL) || (ndev == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_change_iface.\n"); + + if (ndev->ieee80211_ptr) + ndev->ieee80211_ptr->iftype = type; + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* Switch OP MOde. */ + prSwitchModeMsg = + (P_MSG_P2P_SWITCH_OP_MODE_T) cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, + sizeof(MSG_P2P_SWITCH_OP_MODE_T)); + + if (prSwitchModeMsg == NULL) { + ASSERT(FALSE); + i4Rslt = -ENOMEM; + break; + } + + prSwitchModeMsg->rMsgHdr.eMsgId = MID_MNY_P2P_FUN_SWITCH; + + switch (type) { + case NL80211_IFTYPE_P2P_CLIENT: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_CLIENT.\n"); + case NL80211_IFTYPE_STATION: + if (type == NL80211_IFTYPE_STATION) + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_STATION.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_INFRASTRUCTURE; + break; + case NL80211_IFTYPE_AP: + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_AP.\n"); + case NL80211_IFTYPE_P2P_GO: + if (type == NL80211_IFTYPE_P2P_GO) + DBGLOG(P2P, TRACE, "NL80211_IFTYPE_P2P_GO not AP.\n"); + prSwitchModeMsg->eOpMode = OP_MODE_ACCESS_POINT; + break; + default: + DBGLOG(P2P, TRACE, "Other type :%d .\n", type); + prSwitchModeMsg->eOpMode = OP_MODE_P2P_DEVICE; + break; + } + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prSwitchModeMsg, MSG_SEND_METHOD_BUF); + + i4Rslt = 0; + + } while (FALSE); + + return i4Rslt; + +} /* mtk_p2p_cfg80211_change_iface */ + +int mtk_p2p_cfg80211_set_channel(IN struct wiphy *wiphy, + struct cfg80211_chan_def *chandef) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + RF_CHANNEL_INFO_T rRfChnlInfo; + + do { + if (wiphy == NULL) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_channel.\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + mtk_p2p_cfg80211func_channel_format_switch(chandef->chan, chandef->width, &rRfChnlInfo, NULL); + p2pFuncSetChannel(prGlueInfo->prAdapter, &rRfChnlInfo); + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; + +} + +/* mtk_p2p_cfg80211_set_channel */ + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask) +{ + INT_32 i4Rslt = -EINVAL; + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + if ((wiphy == NULL) || (dev == NULL) || (mask == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_set_bitrate_mask\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + /* TODO: Set bitrate mask of the peer? */ + + i4Rslt = 0; + } while (FALSE); + + return i4Rslt; +} /* mtk_p2p_cfg80211_set_bitrate_mask */ + +void mtk_p2p_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg) +{ +#if 0 + P_MSG_P2P_MGMT_FRAME_REGISTER_T prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) NULL; +#endif + P_GLUE_INFO_T prGlueInfo = (P_GLUE_INFO_T) NULL; + + do { + if ((wiphy == NULL) || (wdev == NULL)) + break; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_mgmt_frame_register\n"); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + switch (frame_type) { + case MAC_FRAME_PROBE_REQ: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Open packet filer probe request\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_PROBE_REQ; + DBGLOG(P2P, TRACE, "Close packet filer probe request\n"); + } + break; + case MAC_FRAME_ACTION: + if (reg) { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter |= PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Open packet filer action frame.\n"); + } else { + prGlueInfo->prP2PInfo->u4OsMgmtFrameFilter &= ~PARAM_PACKET_FILTER_ACTION_FRAME; + DBGLOG(P2P, TRACE, "Close packet filer action frame.\n"); + } + break; + default: + DBGLOG(P2P, ERROR, "Ask frog to add code for mgmt:%x\n", frame_type); + break; + } + + if ((prGlueInfo->prAdapter != NULL) && (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE)) { + + /* prGlueInfo->u4Flag |= GLUE_FLAG_FRAME_FILTER; */ + set_bit(GLUE_FLAG_FRAME_FILTER_BIT, &prGlueInfo->ulFlag); + + /* wake up main thread */ + wake_up_interruptible(&prGlueInfo->waitq); + + if (in_interrupt()) + DBGLOG(P2P, TRACE, "It is in interrupt level\n"); + } +#if 0 + + prMgmtFrameRegister = (P_MSG_P2P_MGMT_FRAME_REGISTER_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof + (MSG_P2P_MGMT_FRAME_REGISTER_T)); + + if (prMgmtFrameRegister == NULL) { + ASSERT(FALSE); + break; + } + + prMgmtFrameRegister->rMsgHdr.eMsgId = MID_MNY_P2P_MGMT_FRAME_REGISTER; + + prMgmtFrameRegister->u2FrameType = frame_type; + prMgmtFrameRegister->fgIsRegister = reg; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMgmtFrameRegister, MSG_SEND_METHOD_BUF); + +#endif + + } while (FALSE); + +} /* mtk_p2p_cfg80211_mgmt_frame_register */ + +BOOLEAN +mtk_p2p_cfg80211func_channel_format_switch(IN struct ieee80211_channel *channel, + IN enum nl80211_channel_type channel_type, + IN P_RF_CHANNEL_INFO_T prRfChnlInfo, IN P_ENUM_CHNL_EXT_T prChnlSco) +{ + BOOLEAN fgIsValid = FALSE; + + do { + if (channel == NULL) + break; + + if (prRfChnlInfo) { + prRfChnlInfo->ucChannelNum = nicFreq2ChannelNum(channel->center_freq * 1000); + + switch (channel->band) { + case NL80211_BAND_2GHZ: + prRfChnlInfo->eBand = BAND_2G4; + break; + case NL80211_BAND_5GHZ: + prRfChnlInfo->eBand = BAND_5G; + break; + default: + prRfChnlInfo->eBand = BAND_2G4; + break; + } + + } + + if (prChnlSco) { + + switch (channel_type) { + case NL80211_CHAN_NO_HT: + *prChnlSco = CHNL_EXT_SCN; + break; + case NL80211_CHAN_HT20: + *prChnlSco = CHNL_EXT_SCN; + break; + case NL80211_CHAN_HT40MINUS: + *prChnlSco = CHNL_EXT_SCA; + break; + case NL80211_CHAN_HT40PLUS: + *prChnlSco = CHNL_EXT_SCB; + break; + default: + ASSERT(FALSE); + *prChnlSco = CHNL_EXT_SCN; + break; + } + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} + +/* mtk_p2p_cfg80211func_channel_format_switch */ + +#if CONFIG_NL80211_TESTMODE +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_TEST_PARAMS prParams = (P_NL80211_DRIVER_TEST_PARAMS) NULL; + INT_32 i4Status = -EINVAL; + P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = NULL; + + ASSERT(wiphy); + ASSERT(wdev); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_cmd\n"); + + if (data && len) { + prParams = (P_NL80211_DRIVER_TEST_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_cmd, data is NULL\n"); + return i4Status; + } + + if (prParams->index >> 24 == 0x01) { + /* New version */ + } else { + /* Old version */ + mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(wiphy, data, len); + i4Status = 0; + return i4Status; + } + + /* Clear the version byte */ + prParams->index = prParams->index & ~BITS(24, 31); + + if (prParams) { + switch (prParams->index) { + case 1: /* P2P Simga */ +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + { + P_NL80211_DRIVER_SW_CMD_PARAMS prParamsCmd; + + prParamsCmd = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if ((prParamsCmd->adr & 0xffff0000) == 0xffff0000) { + i4Status = mtk_p2p_cfg80211_testmode_sw_cmd(wiphy, data, len); + break; + } + } +#endif + i4Status = mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(wiphy, data, len); + break; +#if CFG_SUPPORT_WFD + case 2: /* WFD */ + i4Status = mtk_p2p_cfg80211_testmode_wfd_update_cmd(wiphy, data, len); + break; +#endif + case 3: /* Hotspot Client Management */ + i4Status = mtk_p2p_cfg80211_testmode_hotspot_block_cmd(wiphy, data, len); + break; + case 0x10: + i4Status = mtk_cfg80211_testmode_get_sta_statistics(wiphy, data, len, prGlueInfo); + break; +#if 1 + case 0x11: /*NFC Beam + Indication */ + prChnlReqInfo = &prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo; + if (data && len) { + P_NL80211_DRIVER_SET_NFC_PARAMS prParams = (P_NL80211_DRIVER_SET_NFC_PARAMS) data; + + prChnlReqInfo->NFC_BEAM = prParams->NFC_Enable; + DBGLOG(P2P, INFO, "NFC: BEAM[%d]\n", prChnlReqInfo->NFC_BEAM); + } + break; + case 0x12: /*NFC Beam + Indication */ + DBGLOG(P2P, INFO, "NFC: Polling\n"); + i4Status = mtk_cfg80211_testmode_get_scan_done(wiphy, data, len, prGlueInfo); + break; +#endif +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + case 0x30: + i4Status = mtk_cfg80211_testmode_get_lte_channel(wiphy, data, len, prGlueInfo); + break; +#endif + + default: + i4Status = -EINVAL; + break; + } + } + + return i4Status; +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + NL80211_DRIVER_TEST_PRE_PARAMS rParams; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_32 index_mode; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + kalMemZero(&rParams, sizeof(NL80211_DRIVER_TEST_PRE_PARAMS)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd\n"); + + if (data && len) + memcpy(&rParams, data, len); + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA,idx_mode=%d idx=%d value=%u\n", + (INT_16) rParams.idx_mode, (INT_16) rParams.idx, rParams.value); + + index_mode = rParams.idx_mode; + index = rParams.idx; + value = rParams.value; + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 100: /* Oper CH */ + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + /* prP2pConnSettings->ucOperatingChnl = value; */ + break; + case 101: /* Local config Method, for P2P SDK */ + prP2pConnSettings->u2LocalConfigMethod = value; + break; + case 102: /* Sigma P2p reset */ + /* kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); */ + /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ + p2pFsmUninit(prGlueInfo->prAdapter); + p2pFsmInit(prGlueInfo->prAdapter); + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + /* status = mtk_p2p_wext_set_oppps_param(prDev,info,wrqu,(char *)&prP2pSpecificBssInfo->rOppPsParam); */ + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + default: + break; + } + + return status; + +} + +int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_P2P_SIGMA_PARAMS prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + UINT_32 index; + INT_32 value; + int status = 0; + UINT_32 u4Leng; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd\n"); + + if (data && len) { + prParams = (P_NL80211_DRIVER_P2P_SIGMA_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_p2p_sigma_cmd, data is NULL or len is 0\n"); + return -EINVAL; + } + + index = (INT_32) prParams->idx; + value = (INT_32) prParams->value; + + DBGLOG(P2P, TRACE, "NL80211_ATTR_TESTDATA, idx=%d value=%d\n", + (INT_32) prParams->idx, (INT_32) prParams->value); + + switch (index) { + case 0: /* Listen CH */ + break; + case 1: /* P2p mode */ + break; + case 4: /* Noa duration */ + prP2pSpecificBssInfo->rNoaParam.u4NoaDurationMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 5: /* Noa interval */ + prP2pSpecificBssInfo->rNoaParam.u4NoaIntervalMs = value; + /* only to apply setting when setting NOA count */ + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 6: /* Noa count */ + prP2pSpecificBssInfo->rNoaParam.u4NoaCount = value; + /* status = mtk_p2p_wext_set_noa_param(prDev, info, wrqu, (char *)&prP2pSpecificBssInfo->rNoaParam); */ + break; + case 100: /* Oper CH */ + /* 20110920 - frog: User configurations are placed in ConnSettings. */ + /* prP2pConnSettings->ucOperatingChnl = value; */ + break; + case 101: /* Local config Method, for P2P SDK */ + prP2pConnSettings->u2LocalConfigMethod = value; + break; + case 102: /* Sigma P2p reset */ + /* kalMemZero(prP2pConnSettings->aucTargetDevAddr, MAC_ADDR_LEN); */ + /* prP2pConnSettings->eConnectionPolicy = ENUM_P2P_CONNECTION_POLICY_AUTO; */ + break; + case 103: /* WPS MODE */ + kalP2PSetWscMode(prGlueInfo, value); + break; + case 104: /* P2p send persence, duration */ + break; + case 105: /* P2p send persence, interval */ + break; + case 106: /* P2P set sleep */ + value = 1; + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + case 107: /* P2P set opps, CTWindowl */ + prP2pSpecificBssInfo->rOppPsParam.u4CTwindowMs = value; + /* status = mtk_p2p_wext_set_oppps_param(prDev,info,wrqu,(char *)&prP2pSpecificBssInfo->rOppPsParam); */ + break; + case 108: /* p2p_set_power_save */ + kalIoctl(prGlueInfo, + wlanoidSetP2pPowerSaveProfile, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + + break; + case 109: /* Max Clients */ + kalP2PSetMaxClients(prGlueInfo, value); + break; + case 110: /* Hotspot WPS mode */ + kalIoctl(prGlueInfo, wlanoidSetP2pWPSmode, &value, sizeof(value), FALSE, FALSE, TRUE, TRUE, &u4Leng); + break; + default: + break; + } + + return status; + +} + +#if CFG_SUPPORT_WFD +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_WFD_PARAMS prParams = (P_NL80211_DRIVER_WFD_PARAMS) NULL; + int status = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + static UINT_8 prevWfdEnable; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + prParams = (P_NL80211_DRIVER_WFD_PARAMS) data; + + DBGLOG(P2P, INFO, "mtk_p2p_cfg80211_testmode_wfd_update_cmd\n"); + + /* to reduce log, print when state changed */ + if (prevWfdEnable != prParams->WfdEnable) { + prevWfdEnable = prParams->WfdEnable; + DBGLOG(P2P, INFO, "WFD Enable:%x\n", prParams->WfdEnable); + DBGLOG(P2P, INFO, "WFD Session Available:%x\n", prParams->WfdSessionAvailable); + DBGLOG(P2P, INFO, "WFD Couple Sink Status:%x\n", prParams->WfdCoupleSinkStatus); + /* aucReserved0[2] */ + DBGLOG(P2P, INFO, "WFD Device Info:%x\n", prParams->WfdDevInfo); + DBGLOG(P2P, INFO, "WFD Control Port:%x\n", prParams->WfdControlPort); + DBGLOG(P2P, INFO, "WFD Maximum Throughput:%x\n", prParams->WfdMaximumTp); + DBGLOG(P2P, INFO, "WFD Extend Capability:%x\n", prParams->WfdExtendCap); + DBGLOG(P2P, INFO, "WFD Couple Sink Addr %pM\n", prParams->WfdCoupleSinkAddress); + DBGLOG(P2P, INFO, "WFD Associated BSSID %pM\n", prParams->WfdAssociatedBssid); + /* UINT_8 aucVideolp[4]; */ + /* UINT_8 aucAudiolp[4]; */ + DBGLOG(P2P, INFO, "WFD Video Port:%x\n", prParams->WfdVideoPort); + DBGLOG(P2P, INFO, "WFD Audio Port:%x\n", prParams->WfdAudioPort); + DBGLOG(P2P, INFO, "WFD Flag:%x\n", prParams->WfdFlag); + DBGLOG(P2P, INFO, "WFD Policy:%x\n", prParams->WfdPolicy); + DBGLOG(P2P, INFO, "WFD State:%x\n", prParams->WfdState); + /* UINT_8 aucWfdSessionInformationIE[24*8]; */ + DBGLOG(P2P, INFO, "WFD Session Info Length:%x\n", prParams->WfdSessionInformationIELen); + /* UINT_8 aucReserved1[2]; */ + DBGLOG(P2P, INFO, "WFD Primary Sink Addr %pM\n", prParams->aucWfdPrimarySinkMac); + DBGLOG(P2P, INFO, "WFD Secondary Sink Addr %pM\n", prParams->aucWfdSecondarySinkMac); + DBGLOG(P2P, INFO, "WFD Advanced Flag:%x\n", prParams->WfdAdvanceFlag); + DBGLOG(P2P, INFO, "WFD Sigma mode:%x\n", prParams->WfdSigmaMode); + /* UINT_8 aucReserved2[64]; */ + /* UINT_8 aucReserved3[64]; */ + /* UINT_8 aucReserved4[64]; */ + } + + prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + + kalMemCopy(&prWfdCfgSettings->u4WfdCmdType, &prParams->WfdCmdType, sizeof(WFD_CFG_SETTINGS_T)); + + prMsgWfdCfgUpdate = cnmMemAlloc(prGlueInfo->prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate == NULL) { + ASSERT(FALSE); + return status; + } + + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); +#if 0 /* Test Only */ +/* prWfdCfgSettings->ucWfdEnable = 1; */ +/* prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; */ + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_DEV_INFO_VALID; + prWfdCfgSettings->u2WfdDevInfo = 123; + prWfdCfgSettings->u2WfdControlPort = 456; + prWfdCfgSettings->u2WfdMaximumTp = 789; + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_SINK_INFO_VALID; + prWfdCfgSettings->ucWfdCoupleSinkStatus = 0xAB; + { + UINT_8 aucTestAddr[MAC_ADDR_LEN] = { 0x77, 0x66, 0x55, 0x44, 0x33, 0x22 }; + + COPY_MAC_ADDR(prWfdCfgSettings->aucWfdCoupleSinkAddress, aucTestAddr); + } + + prWfdCfgSettings->u4WfdFlag |= WFD_FLAGS_EXT_CAPABILITY_VALID; + prWfdCfgSettings->u2WfdExtendCap = 0xCDE; + +#endif + + return status; + +} +#endif /* CFG_SUPPORT_WFD */ + +int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) NULL; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + + if (data && len) { + prParams = (P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS) data; + } else { + DBGLOG(P2P, ERROR, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd, data is NULL or len is 0\n"); + return -EINVAL; + } + + DBGLOG(P2P, TRACE, "mtk_p2p_cfg80211_testmode_hotspot_block_cmd\n"); + + return kalP2PSetBlackList(prGlueInfo, prParams->aucBssid, prParams->ucblocked); +} + +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + P_NL80211_DRIVER_SW_CMD_PARAMS prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) NULL; + WLAN_STATUS rstatus = WLAN_STATUS_SUCCESS; + int fgIsValid = 0; + UINT_32 u4SetInfoLen = 0; + + ASSERT(wiphy); + + prGlueInfo = *((P_GLUE_INFO_T *) wiphy_priv(wiphy)); + +#if 1 + DBGLOG(P2P, TRACE, "--> %s()\n", __func__); +#endif + + if (data && len) + prParams = (P_NL80211_DRIVER_SW_CMD_PARAMS) data; + + if (prParams) { + if (prParams->set == 1) { + rstatus = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) wlanoidSetSwCtrlWrite, + &prParams->adr, (UINT_32) 8, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } + } + + if (WLAN_STATUS_SUCCESS != rstatus) + fgIsValid = -EFAULT; + + return fgIsValid; +} + +#endif + +#endif /* CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c new file mode 100644 index 0000000000000..d0f2d25a4529f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_init.c @@ -0,0 +1,433 @@ +/* +* Copyright (C) 2011-2014 MediaTek Inc. +* +* 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. +* +* You should have received a copy of the GNU General Public License along with this program. +* If not, see . +*/ + +/* +** Id: @(#) gl_p2p_init.c@@ +*/ + +/*! \file gl_p2p_init.c + \brief init and exit routines of Linux driver interface for Wi-Fi Direct + + This file contains the main routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define P2P_MODE_INF_NAME "p2p%d" +#if CFG_TC1_FEATURE +#define AP_MODE_INF_NAME "wlan%d" +#else +#define AP_MODE_INF_NAME "ap%d" +#endif +/* #define MAX_INF_NAME_LEN 15 */ +/* #define MIN_INF_NAME_LEN 1 */ + +#define RUNNING_P2P_MODE 0 +#define RUNNING_AP_MODE 1 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* Get interface name and running mode from module insertion parameter +* Usage: insmod p2p.ko mode=1 +* default: interface name is p2p%d +* running mode is P2P +*/ +static PUCHAR ifname = P2P_MODE_INF_NAME; +static UINT_16 mode = RUNNING_P2P_MODE; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief check interface name parameter is valid or not +* if invalid, set ifname to P2P_MODE_INF_NAME +* +* +* \retval +*/ +/*----------------------------------------------------------------------------*/ +VOID p2pCheckInterfaceName(VOID) +{ + + if (mode) { + mode = RUNNING_AP_MODE; + ifname = AP_MODE_INF_NAME; + } +#if 0 + UINT_32 ifLen = 0; + + if (ifname) { + ifLen = strlen(ifname); + + if (ifLen > MAX_INF_NAME_LEN) + ifname[MAX_INF_NAME_LEN] = '\0'; + else if (ifLen < MIN_INF_NAME_LEN) + ifname = P2P_MODE_INF_NAME; + } else { + ifname = P2P_MODE_INF_NAME; + } +#endif +} + +void p2pHandleSystemSuspend(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ + UINT_32 u4NumIPv6 = 0; +#endif + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + + + if (!wlanExportGlueInfo(&prGlueInfo)) { + DBGLOG(P2P, INFO, "No glue info\n"); + return; + } + + ASSERT(prGlueInfo); + /* <1> Sanity check and acquire the net_device */ + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ip is not available.\n"); + return; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ipv6 is not available.\n"); + return; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); + /* todo: traverse between list to find whole sets of IPv6 addresses */ + + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) + ; /* Do nothing */ +#endif + /* <7> set up the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#ifdef CONFIG_IPV6 + prParamNetAddrList->u4AddressCount += u4NumIPv6; +#endif + + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((UINT_32) prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + +/* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); +// TODO: frog. The pointer is not right. */ + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (prParamNetAddr->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS_IP); +#endif + } +#ifdef CONFIG_IPV6 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); +/* prParamNetAddr = (P_PARAM_NETWORK_ADDRESS)((UINT_32)prParamNetAddr + sizeof(ip6)); */ + + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((ULONG) prParamNetAddr + + (ULONG) (prParamNetAddr->u2AddressLength + + OFFSET_OF(PARAM_NETWORK_ADDRESS, + aucAddress))); + + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + } +} + +void p2pHandleSystemResume(void) +{ + struct net_device *prDev = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_8 ip[4] = { 0 }; +#ifdef CONFIG_IPV6 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ +#endif + + if (!wlanExportGlueInfo(&prGlueInfo)) { + DBGLOG(P2P, WARN, "no glue info\n"); + return; + } + + ASSERT(prGlueInfo); + /* <1> Sanity check and acquire the net_device */ + prDev = prGlueInfo->prP2PInfo->prDevHandler; + ASSERT(prDev); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ip is not available.\n"); + return; + } + /* <4> copy the IPv4 address */ + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + +#ifdef CONFIG_IPV6 + /* <5> get the IPv6 address */ + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(P2P, INFO, "ipv6 is not available.\n"); + return; + } + /* <6> copy the IPv6 address */ + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(P2P, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); +#endif + /* <7> clear the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; +/* UINT_8 aucBuf[32] = {0}; */ + UINT_32 u4Len = sizeof(PARAM_NETWORK_ADDRESS_LIST); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) g_aucBufIpAddr; + /* aucBuf; */ + + kalMemZero(g_aucBufIpAddr, sizeof(g_aucBufIpAddr)); + + prParamNetAddrList->u4AddressCount = 0; + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + + ASSERT(u4Len <= sizeof(g_aucBufIpAddr /*aucBuf */)); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetP2pSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, TRUE, &u4SetInfoLen); + + DBGLOG(INIT, INFO, "IP: %d.%d.%d.%d, rStatus: %u\n", ip[0], ip[1], ip[2], ip[3], rStatus); + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p init procedure, include register pointer to wlan +* glue register p2p +* set p2p registered flag +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo) +{ + + DBGLOG(P2P, TRACE, "p2pLaunch\n"); + + if (prGlueInfo->prAdapter->fgIsP2PRegistered == TRUE) { + DBGLOG(P2P, INFO, "p2p already registered\n"); + return FALSE; + } else if (glRegisterP2P(prGlueInfo, ifname, (BOOLEAN) mode)) { + prGlueInfo->prAdapter->fgIsP2PRegistered = TRUE; + + DBGLOG(P2P, TRACE, "Launch success, fgIsP2PRegistered TRUE.\n"); + return TRUE; + } + DBGLOG(P2P, ERROR, "Launch Fail\n"); + + return FALSE; +} + +VOID p2pSetMode(IN BOOLEAN fgIsAPMOde) +{ + if (fgIsAPMOde) { + mode = RUNNING_AP_MODE; + ifname = AP_MODE_INF_NAME; + } else { + mode = RUNNING_P2P_MODE; + ifname = P2P_MODE_INF_NAME; + } + +} /* p2pSetMode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* run p2p exit procedure, include unregister pointer to wlan +* glue unregister p2p +* set p2p registered flag + +* \retval 1 Success +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo) +{ + if (prGlueInfo->prAdapter->fgIsP2PRegistered == FALSE) { + DBGLOG(P2P, INFO, "p2p is not Registered.\n"); + return FALSE; + } + /*Check p2p fsm is stop or not. If not then stop now */ + if (IS_P2P_ACTIVE(prGlueInfo->prAdapter)) + p2pStopImmediate(prGlueInfo); + prGlueInfo->prAdapter->fgIsP2PRegistered = FALSE; + glUnregisterP2P(prGlueInfo); + /*p2p is removed successfully */ + return TRUE; + +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver entry point when the driver is configured as a Linux Module, and +* is called once at module load time, by the user-level modutils +* application: insmod or modprobe. +* +* \retval 0 Success +*/ +/*----------------------------------------------------------------------------*/ +static int initP2P(void) +{ + P_GLUE_INFO_T prGlueInfo; + + /*check interface name validation */ + p2pCheckInterfaceName(); + + DBGLOG(P2P, INFO, "InitP2P, Ifname: %s, Mode: %s\n", ifname, mode ? "AP" : "P2P"); + + /*register p2p init & exit function to wlan sub module handler */ + wlanSubModRegisterInitExit(p2pLaunch, p2pRemove, P2P_MODULE); + + /*if wlan is not start yet, do nothing + * p2pLaunch will be called by txthread while wlan start + */ + /*if wlan is not started yet, return FALSE */ + if (wlanExportGlueInfo(&prGlueInfo)) { + wlanSubModInit(prGlueInfo); + return prGlueInfo->prAdapter->fgIsP2PRegistered ? 0 : -EIO; + } + + return 0; +} /* end of initP2P() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Driver exit point when the driver as a Linux Module is removed. Called +* at module unload time, by the user level modutils application: rmmod. +* This is our last chance to clean up after ourselves. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +/* 1 Module Leave Point */ +static VOID __exit exitP2P(void) +{ + P_GLUE_INFO_T prGlueInfo; + + DBGLOG(P2P, INFO, KERN_INFO DRV_NAME "ExitP2P\n"); + + /*if wlan is not started yet, return FALSE */ + if (wlanExportGlueInfo(&prGlueInfo)) + wlanSubModExit(prGlueInfo); + /*UNregister p2p init & exit function to wlan sub module handler */ + wlanSubModRegisterInitExit(NULL, NULL, P2P_MODULE); +} /* end of exitP2P() */ +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c new file mode 100644 index 0000000000000..11a417e4c74c9 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_p2p_kal.c @@ -0,0 +1,1314 @@ +/* +** Id: @(#) gl_p2p_cfg80211.c@@ +*/ + +/*! \file gl_p2p_kal.c + \brief + +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "net/cfg80211.h" +#include "precomp.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct state from glue layer +* +* \param[in] +* prGlueInfo +* rPeerAddr +* \return +* ENUM_BOW_DEVICE_STATE +*/ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->eState; +} /* end of kalP2PGetState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to update the assoc req to p2p +* +* \param[in] +* prGlueInfo +* pucFrameBody +* u4FrameBodyLen +* fgReassocRequest +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PUpdateAssocInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; + unsigned char *pucDesiredIE = NULL; +/* unsigned char aucExtraInfoBuf[200]; */ + PUINT_8 cp; + + memset(&wrqu, 0, sizeof(wrqu)); + + if (fgReassocRequest) { + if (u4FrameBodyLen < 15) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } else { + if (u4FrameBodyLen < 9) { + /* + printk(KERN_WARNING "frameBodyLen too short:%ld\n", frameBodyLen); + */ + return; + } + } + + cp = pucFrameBody; + + if (fgReassocRequest) { + /* Capability information field 2 */ + /* Listen interval field 2 */ + /* Current AP address 6 */ + cp += 10; + u4FrameBodyLen -= 10; + } else { + /* Capability information field 2 */ + /* Listen interval field 2 */ + cp += 4; + u4FrameBodyLen -= 4; + } + + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPSIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPSIE!!\n"); */ + /* WPS IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0x30, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPAIE!!\n"); */ + /* RSN IE found */ + } else if (wextSrchDesiredWPAIE(cp, u4FrameBodyLen, 0xDD, &pucDesiredIE)) { + /* printk("wextSrchDesiredWPAIE!!\n"); */ + /* WPA IE found */ + } else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } + + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVASSOCREQIE, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct state in glue layer +* +* \param[in] +* prGlueInfo +* eBowState +* rPeerAddr +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetState(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eState, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucRole) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + if (eState == PARAM_MEDIA_STATE_CONNECTED) { + prGlueInfo->prP2PInfo->eState = PARAM_MEDIA_STATE_CONNECTED; + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_CONNECT=%pM ", rPeerAddr); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + + } else if (eState == PARAM_MEDIA_STATE_DISCONNECTED) { + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_STA_DISCONNECT=%pM ", rPeerAddr); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + } else { + ASSERT(0); + } + +} /* end of kalP2PSetState() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Wi-Fi Direct operating frequency +* +* \param[in] +* prGlueInfo +* +* \return +* in unit of KHz +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->u4FreqInKHz; +} /* end of kalP2PGetFreqInKHz() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to retrieve Bluetooth-over-Wi-Fi role +* +* \param[in] +* prGlueInfo +* +* \return +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo) +{ + ASSERT(prGlueInfo); + + return prGlueInfo->prP2PInfo->ucRole; +} /* end of kalP2PGetRole() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set Wi-Fi Direct role +* +* \param[in] +* prGlueInfo +* ucResult +* 0: successful +* 1: error +* ucRole +* 0: P2P Device +* 1: Group Client +* 2: Group Owner +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + ASSERT(ucRole <= 2); + + memset(&evt, 0, sizeof(evt)); + + if (ucResult == 0) + prGlueInfo->prP2PInfo->ucRole = ucRole; + + if (pucSSID) + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, + 1 /* persistence or not */ , pucSSID[7], pucSSID[8]); + else + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_FORMATION_RST=%d%d%d%c%c", ucResult, ucRole, + 1 /* persistence or not */ , '0', '0'); + + evt.data.length = strlen(aucBuffer); + + /* if (pucSSID) */ + /* printk("P2P GO SSID DIRECT-%c%c\n", pucSSID[7], pucSSID[8]); */ + + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PSetRole() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the cipher for p2p +* +* \param[in] +* prGlueInfo +* u4Cipher +* +* \return +* none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + prGlueInfo->prP2PInfo->u4CipherPairwise = u4Cipher; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the cipher, return for cipher is ccmp +* +* \param[in] +* prGlueInfo +* +* \return +* TRUE: cipher is ccmp +* FALSE: cipher is none +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return TRUE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return FALSE; + + return FALSE; +} + +BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_CCMP) + return FALSE; + + if (prGlueInfo->prP2PInfo->u4CipherPairwise == IW_AUTH_CIPHER_TKIP) + return TRUE; + + return FALSE; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetWscMode(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucWscMode) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + prGlueInfo->prP2PInfo->ucWSCRunning = ucWscMode; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the status of WSC +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 kalP2PGetWscMode(IN P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return 0; + } + + return prGlueInfo->prP2PInfo->ucWSCRunning; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to get the wsc ie length +* +* \param[in] +* prGlueInfo +* ucType : 0 for beacon, 1 for probe req, 2 for probe resp +* +* \return +* The WSC IE length +*/ +/*----------------------------------------------------------------------------*/ +UINT_16 kalP2PCalWSC_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType) +{ + ASSERT(prGlueInfo); + + ASSERT(ucType < 3); + + return prGlueInfo->prP2PInfo->u2WSCIELen[ucType]; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to copy the wsc ie setting from p2p supplicant +* +* \param[in] +* prGlueInfo +* +* \return +* The WPS IE length +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 3) || (pucBuffer == NULL)) + break; + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(pucBuffer, prGlP2pInfo->aucWSCIE[ucType], prGlP2pInfo->u2WSCIELen[ucType]); + + } while (FALSE); + +} + +VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength) +{ + P_GL_P2P_INFO_T prGlP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (ucType >= 3) || ((u2BufferLength > 0) && (pucBuffer == NULL))) + break; + + if (u2BufferLength > 400) { + DBGLOG(P2P, ERROR, + "Buffer length is not enough, GLUE only 400 bytes but %d received\n", u2BufferLength); + ASSERT(FALSE); + break; + } + + prGlP2pInfo = prGlueInfo->prP2PInfo; + + kalMemCopy(prGlP2pInfo->aucWSCIE[ucType], pucBuffer, u2BufferLength); + + prGlP2pInfo->u2WSCIELen[ucType] = u2BufferLength; + + } while (FALSE); + +} /* kalP2PUpdateWSC_IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief indicate an event to supplicant for device connection request +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength, + IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_REQ_DEVICE_INFO access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = u4NameLength > 32 ? 32 : u4NameLength; + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, pucDevName, prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, rPeerAddr); + prGlueInfo->prP2PInfo->ucConnReqDevType = ucDevType; + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = i4ConfigMethod; + prGlueInfo->prP2PInfo->i4ConnReqActiveConfigMethod = i4ActiveConfigMethod; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_DVC_REQ"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateConnReq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for device connection request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] pucGroupBssid Only valid when invitation Type equals to 0. +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid) +{ +#if 1 + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4ConnReqNameLength = + (UINT_32) ((prP2pDevDesc->u2NameLength > 32) ? 32 : prP2pDevDesc->u2NameLength); + kalMemCopy(prGlueInfo->prP2PInfo->aucConnReqDevName, prP2pDevDesc->aucName, + prGlueInfo->prP2PInfo->u4ConnReqNameLength); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqPeerAddr, prP2pDevDesc->aucDeviceAddr); + COPY_MAC_ADDR(prGlueInfo->prP2PInfo->rConnReqGroupAddr, pucGroupBssid); + prGlueInfo->prP2PInfo->i4ConnReqConfigMethod = (INT_32) (prP2pDevDesc->u2ConfigMethod); + prGlueInfo->prP2PInfo->ucOperatingChnl = ucOperatingChnl; + prGlueInfo->prP2PInfo->ucInvitationType = ucInvitationType; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_INDICATE"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + return; + +#else + P_MSG_P2P_CONNECTION_REQUEST_T prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) NULL; + P_P2P_SPECIFIC_BSS_INFO_T prP2pSpecificBssInfo = (P_P2P_SPECIFIC_BSS_INFO_T) NULL; + P_P2P_CONNECTION_SETTINGS_T prP2pConnSettings = (P_P2P_CONNECTION_SETTINGS_T) NULL; + + do { + ASSERT_BREAK((prGlueInfo != NULL) && (prP2pDevDesc != NULL)); + + /* Not a real solution */ + + prP2pSpecificBssInfo = prGlueInfo->prAdapter->rWifiVar.prP2pSpecificBssInfo; + prP2pConnSettings = prGlueInfo->prAdapter->rWifiVar.prP2PConnSettings; + + prP2pConnReq = (P_MSG_P2P_CONNECTION_REQUEST_T) cnmMemAlloc(prGlueInfo->prAdapter, + RAM_TYPE_MSG, + sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + if (prP2pConnReq == NULL) + break; + + kalMemZero(prP2pConnReq, sizeof(MSG_P2P_CONNECTION_REQUEST_T)); + + prP2pConnReq->rMsgHdr.eMsgId = MID_MNY_P2P_CONNECTION_REQ; + + prP2pConnReq->eFormationPolicy = ENUM_P2P_FORMATION_POLICY_AUTO; + + COPY_MAC_ADDR(prP2pConnReq->aucDeviceID, prP2pDevDesc->aucDeviceAddr); + + prP2pConnReq->u2ConfigMethod = prP2pDevDesc->u2ConfigMethod; + + if (ucInvitationType == P2P_INVITATION_TYPE_INVITATION) { + prP2pConnReq->fgIsPersistentGroup = FALSE; + prP2pConnReq->fgIsTobeGO = FALSE; + + } + + else if (ucInvitationType == P2P_INVITATION_TYPE_REINVOKE) { + DBGLOG(P2P, TRACE, "Re-invoke Persistent Group\n"); + prP2pConnReq->fgIsPersistentGroup = TRUE; + prP2pConnReq->fgIsTobeGO = (prGlueInfo->prP2PInfo->ucRole == 2) ? TRUE : FALSE; + + } + + p2pFsmRunEventDeviceDiscoveryAbort(prGlueInfo->prAdapter, NULL); + + if (ucOperatingChnl != 0) + prP2pSpecificBssInfo->ucPreferredChannel = ucOperatingChnl; + + if ((ucSsidLen < 32) && (pucSsid != NULL)) + COPY_SSID(prP2pConnSettings->aucSSID, prP2pConnSettings->ucSSIDLen, pucSsid, ucSsidLen); + + mboxSendMsg(prGlueInfo->prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prP2pConnReq, MSG_SEND_METHOD_BUF); + + } while (FALSE); + + /* frog add. */ + /* TODO: Invitation Indication */ + + return; +#endif + +} /* kalP2PInvitationIndication */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an status to supplicant for device invitation status. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4InvStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + /* buffer peer information for later IOC_P2P_GET_STRUCT access */ + prGlueInfo->prP2PInfo->u4InvStatus = u4InvStatus; + + /* prepare event structure */ + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_INV_STATUS"); + evt.data.length = strlen(aucBuffer); + + /* indicate in IWEVCUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* kalP2PInvitationStatus */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery request from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_REQ %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDRequest() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery response +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_RESP %d", ucSeqNum); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Indicate an event to supplicant for Service Discovery TX Done +* from other device. +* +* \param[in] prGlueInfo Pointer of GLUE_INFO_T +* \param[in] ucSeqNum Sequence number of the frame +* \param[in] ucStatus Status code for TX +* +* \retval none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SD_XMITTED: %d %d", ucSeqNum, ucStatus); + evt.data.length = strlen(aucBuffer); + + /* indicate IWEVP2PSDREQ event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); + +} /* end of kalP2PIndicateSDResponse() */ + +struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return NULL; + } + + return prGlueInfo->prP2PInfo->prDevHandler; +} + +#if CFG_SUPPORT_ANTI_PIRACY +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PIndicateSecCheckRsp(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucRsp, IN UINT_16 u2RspLen) +{ + union iwreq_data evt; + UINT_8 aucBuffer[IW_CUSTOM_MAX]; + + ASSERT(prGlueInfo); + + memset(&evt, 0, sizeof(evt)); + snprintf(aucBuffer, IW_CUSTOM_MAX - 1, "P2P_SEC_CHECK_RSP="); + + kalMemCopy(prGlueInfo->prP2PInfo->aucSecCheckRsp, pucRsp, u2RspLen); + evt.data.length = strlen(aucBuffer); + +#if DBG + DBGLOG_MEM8(SEC, LOUD, prGlueInfo->prP2PInfo->aucSecCheckRsp, u2RspLen); +#endif + /* indicate in IWECUSTOM event */ + wireless_send_event(prGlueInfo->prP2PInfo->prDevHandler, IWEVCUSTOM, &evt, aucBuffer); +} /* p2pFsmRunEventRxDisassociation */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief +* +* \param[in] prAdapter Pointer of ADAPTER_T +* +* \return none +*/ +/*----------------------------------------------------------------------------*/ +VOID +kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList) +{ + rlmDomainGetChnlList(prGlueInfo->prAdapter, eSpecificBand, FALSE, ucMaxChannelNum, + pucNumOfChannel, paucChannelList); +} /* kalGetChnlList */ + +/* ////////////////////////////////////ICS SUPPORT////////////////////////////////////// */ + +VOID +kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration) +{ + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + RF_CHANNEL_INFO_T rChannelInfo; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + + do { + if (prGlueInfo == NULL) + break; + + kalMemZero(&rChannelInfo, sizeof(RF_CHANNEL_INFO_T)); + + rChannelInfo.ucChannelNum = u4ChannelNum; + rChannelInfo.eBand = eBand; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueInfo->prP2PInfo, &rChannelInfo); + + kalP2pFuncGetChannelType(eSco, &eChnlType); + + cfg80211_ready_on_channel(prGlueInfo->prP2PInfo->prWdev, /* struct wireless_dev, */ + u8SeqNum, /* u64 cookie, */ + prIEEE80211ChnlStruct, /* struct ieee80211_channel * chan, */ + u4Duration, /* unsigned int duration, */ + GFP_KERNEL); /* gfp_t gfp */ /* allocation flags */ + } while (FALSE); + +} /* kalP2PIndicateChannelReady */ + +VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo) +{ + + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prIEEE80211ChnlStruct = (struct ieee80211_channel *)NULL; + enum nl80211_channel_type eChnlType = NL80211_CHAN_NO_HT; + RF_CHANNEL_INFO_T rRfChannelInfo; + + do { + if ((prGlueInfo == NULL) || (prChnlReqInfo == NULL)) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(P2P, TRACE, "kalP2PIndicateChannelExpired\n"); + + rRfChannelInfo.eBand = prChnlReqInfo->eBand; + rRfChannelInfo.ucChannelNum = prChnlReqInfo->ucReqChnlNum; + + prIEEE80211ChnlStruct = kalP2pFuncGetChannelEntry(prGlueP2pInfo, &rRfChannelInfo); + + kalP2pFuncGetChannelType(prChnlReqInfo->eChnlSco, &eChnlType); + + cfg80211_remain_on_channel_expired(prGlueP2pInfo->prWdev, /* struct wireless_dev, */ + prChnlReqInfo->u8Cookie, prIEEE80211ChnlStruct, GFP_KERNEL); + } while (FALSE); + +} /* kalP2PIndicateChannelExpired */ + +VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgIsAbort) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct cfg80211_scan_request *prScanRequest = NULL; + struct cfg80211_scan_info info = { + .aborted = true, + }; + + GLUE_SPIN_LOCK_DECLARATION(); + + do { + if (prGlueInfo == NULL) { + + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + DBGLOG(INIT, TRACE, "[p2p] scan complete %p\n", prGlueP2pInfo->prScanRequest); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + if (prGlueP2pInfo->prScanRequest != NULL) { + prScanRequest = prGlueP2pInfo->prScanRequest; + prGlueP2pInfo->prScanRequest = NULL; + } + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_NET_DEV); + + /* 2. then CFG80211 Indication */ + + if (prScanRequest != NULL) { + + /* report all queued beacon/probe response frames to upper layer */ + scanReportBss2Cfg80211(prGlueInfo->prAdapter, BSS_TYPE_P2P_DEVICE, NULL); + + info.aborted = fgIsAbort; + DBGLOG(INIT, TRACE, "DBG:p2p_cfg_scan_done\n"); + cfg80211_scan_done(prScanRequest, &info); + } + + } while (FALSE); + +} /* kalP2PIndicateScanDone */ + +VOID +kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + struct ieee80211_channel *prChannelEntry = (struct ieee80211_channel *)NULL; + struct ieee80211_mgmt *prBcnProbeRspFrame = (struct ieee80211_mgmt *)pucFrameBuf; + struct cfg80211_bss *prCfg80211Bss = (struct cfg80211_bss *)NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (prChannelInfo == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prGlueP2pInfo == NULL) { + ASSERT(FALSE); + break; + } + + prChannelEntry = kalP2pFuncGetChannelEntry(prGlueP2pInfo, prChannelInfo); + + if (prChannelEntry == NULL) { + DBGLOG(P2P, WARN, "Unknown channel info\n"); + break; + } + /* rChannelInfo.center_freq = nicChannelNum2Freq((UINT_32)prChannelInfo->ucChannelNum) / 1000; */ + + prCfg80211Bss = cfg80211_inform_bss_frame(prGlueP2pInfo->prWdev->wiphy, /* struct wiphy * wiphy, */ + prChannelEntry, + prBcnProbeRspFrame, u4BufLen, i4SignalStrength, GFP_KERNEL); + + /* Return this structure. */ + if (!prCfg80211Bss) { + DBGLOG(P2P, WARN, "inform bss to cfg80211 failed, bss channel %d, rcpi %d\n", + prChannelInfo->ucChannelNum, i4SignalStrength); + } else { + cfg80211_put_bss(prGlueP2pInfo->prWdev->wiphy, prCfg80211Bss); + DBGLOG(P2P, TRACE, "inform bss to cfg80211, bss channel %d, rcpi %d\n", + prChannelInfo->ucChannelNum, i4SignalStrength); + } + } while (FALSE); + +} /* kalP2PIndicateBssInfo */ + +VOID +kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if ((prGlueInfo == NULL) || (pucFrameBuf == NULL) || (u4FrameLen == 0)) { + DBGLOG(P2P, TRACE, "Unexpected pointer PARAM. %p, %p, %u.", + prGlueInfo, pucFrameBuf, u4FrameLen); + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + cfg80211_mgmt_tx_status(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + u8Cookie, pucFrameBuf, u4FrameLen, fgIsAck, GFP_KERNEL); + + } while (FALSE); + +} /* kalP2PIndicateMgmtTxStatus */ + +VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb) +{ +#define DBG_P2P_MGMT_FRAME_INDICATION 0 + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + INT_32 i4Freq = 0; + UINT_8 ucChnlNum = 0; +#if DBG_P2P_MGMT_FRAME_INDICATION + P_WLAN_MAC_HEADER_T prWlanHeader = (P_WLAN_MAC_HEADER_T) NULL; +#endif + + do { + if ((prGlueInfo == NULL) || (prSwRfb == NULL)) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + ucChnlNum = prSwRfb->prHifRxHdr->ucHwChannelNum; + +#if DBG_P2P_MGMT_FRAME_INDICATION + + prWlanHeader = (P_WLAN_MAC_HEADER_T) prSwRfb->pvHeader; + + switch (prWlanHeader->u2FrameCtrl) { + case MAC_FRAME_PROBE_REQ: + DBGLOG(P2P, TRACE, "RX Probe Req at channel %d ", ucChnlNum); + break; + case MAC_FRAME_PROBE_RSP: + DBGLOG(P2P, TRACE, "RX Probe Rsp at channel %d ", ucChnlNum); + break; + case MAC_FRAME_ACTION: + DBGLOG(P2P, TRACE, "RX Action frame at channel %d ", ucChnlNum); + break; + default: + DBGLOG(P2P, TRACE, "RX Packet:%d at channel %d ", prWlanHeader->u2FrameCtrl, ucChnlNum); + break; + } + + DBGLOG(P2P, TRACE, "from: %pM\n", prWlanHeader->aucAddr2); +#endif + i4Freq = nicChannelNum2Freq(ucChnlNum) / 1000; + + cfg80211_rx_mgmt(prGlueP2pInfo->prWdev, /* struct net_device * dev, */ + i4Freq, + RCPI_TO_dBm(prSwRfb->prHifRxHdr->ucRcpi), + prSwRfb->pvHeader, prSwRfb->u2PacketLen, GFP_ATOMIC); + } while (FALSE); + +} /* kalP2PIndicateRxMgmtFrame */ + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus) +{ + P_GL_P2P_INFO_T prGlueP2pInfo = (P_GL_P2P_INFO_T) NULL; + + do { + if (prGlueInfo == NULL) { + ASSERT(FALSE); + break; + } + + prGlueP2pInfo = prGlueInfo->prP2PInfo; + + if (prP2pConnInfo) { + cfg80211_connect_result(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ + prP2pConnInfo->aucBssid, prP2pConnInfo->aucIEBuf, + prP2pConnInfo->u4BufLength, + pucRxIEBuf, u2RxIELen, u2StatusReason, GFP_KERNEL); + /* gfp_t gfp */ /* allocation flags */ + prP2pConnInfo->fgIsConnRequest = FALSE; + } else { + /* Disconnect, what if u2StatusReason == 0? */ + cfg80211_disconnected(prGlueP2pInfo->prDevHandler, /* struct net_device * dev, */ + u2StatusReason, pucRxIEBuf, u2RxIELen, + eStatus == WLAN_STATUS_MEDIA_DISCONNECT_LOCALLY ? true : false, + GFP_KERNEL); + } + + } while (FALSE); + +} /* kalP2PGCIndicateConnectionStatus */ + +VOID kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew) +{ + P_GL_P2P_INFO_T prP2pGlueInfo = (P_GL_P2P_INFO_T) NULL; + struct station_info rStationInfo; + + memset(&rStationInfo, 0, sizeof(struct station_info)); + + do { + if ((prGlueInfo == NULL) || (prCliStaRec == NULL)) + break; + + prP2pGlueInfo = prGlueInfo->prP2PInfo; + + if (fgIsNew) { + //rStationInfo.filled = STATION_INFO_ASSOC_REQ_IES; + rStationInfo.generation = ++prP2pGlueInfo->i4Generation; + + rStationInfo.assoc_req_ies = prCliStaRec->pucAssocReqIe; + rStationInfo.assoc_req_ies_len = prCliStaRec->u2AssocReqIeLen; +/* rStationInfo.filled |= STATION_INFO_ASSOC_REQ_IES; */ + + cfg80211_new_sta(prGlueInfo->prP2PInfo->prDevHandler, /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, &rStationInfo, GFP_KERNEL); + } else { + ++prP2pGlueInfo->i4Generation; + + cfg80211_del_sta(prGlueInfo->prP2PInfo->prDevHandler, /* struct net_device * dev, */ + prCliStaRec->aucMacAddr, GFP_KERNEL); + } + + } while (FALSE); + + return; + +} /* kalP2PGOStationUpdate */ + +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type) +{ + BOOLEAN fgIsValid = FALSE; + + do { + if (channel_type) { + + switch (rChnlSco) { + case CHNL_EXT_SCN: + *channel_type = NL80211_CHAN_NO_HT; + break; + case CHNL_EXT_SCA: + *channel_type = NL80211_CHAN_HT40MINUS; + break; + case CHNL_EXT_SCB: + *channel_type = NL80211_CHAN_HT40PLUS; + break; + default: + ASSERT(FALSE); + *channel_type = NL80211_CHAN_NO_HT; + break; + } + + } + + fgIsValid = TRUE; + } while (FALSE); + + return fgIsValid; +} /* kalP2pFuncGetChannelType */ + +struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo) +{ + struct ieee80211_channel *prTargetChannelEntry = (struct ieee80211_channel *)NULL; + UINT_32 u4TblSize = 0, u4Idx = 0; + struct ieee80211_supported_band **bands; + + do { + if ((prP2pInfo == NULL) || (prChannelInfo == NULL)) + break; + bands = &prP2pInfo->prWdev->wiphy->bands[0]; + switch (prChannelInfo->eBand) { + case BAND_2G4: + prTargetChannelEntry = bands[NL80211_BAND_2GHZ]->channels; + u4TblSize = bands[NL80211_BAND_2GHZ]->n_channels; + break; + case BAND_5G: + prTargetChannelEntry = bands[NL80211_BAND_5GHZ]->channels; + u4TblSize = bands[NL80211_BAND_5GHZ]->n_channels; + break; + default: + break; + } + + if (prTargetChannelEntry == NULL) + break; + + for (u4Idx = 0; u4Idx < u4TblSize; u4Idx++, prTargetChannelEntry++) { + if (prTargetChannelEntry->hw_value == prChannelInfo->ucChannelNum) + break; + } + + if (u4Idx == u4TblSize) { + prTargetChannelEntry = NULL; + break; + } + + } while (FALSE); + + return prTargetChannelEntry; +} /* kalP2pFuncGetChannelEntry */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to set the block list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + if (EQUAL_MAC_ADDR(rbssid, aucNullAddr)) + return -EINVAL; + + if (fgIsblock) { + for (i = 0; i < 8; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + break; + } else if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid); + break; + } + } + if (i >= 8) { + DBGLOG(P2P, ERROR, "AP black list is full, cannot block more STA!!\n"); + return -ENOBUFS; + } + } else { + for (i = 0; i < 8; i++) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + COPY_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), aucNullAddr); + break; + } + } + if (i >= 8) + DBGLOG(P2P, ERROR, "The STA is not found in black list!!\n"); + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to compare the black list of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid) +{ + UINT_8 aucNullAddr[] = NULL_MAC_ADDR; + BOOLEAN fgIsExsit = FALSE; + UINT_32 i; + + ASSERT(prGlueInfo); + ASSERT(prGlueInfo->prP2PInfo); + + for (i = 0; i < 8; i++) { + if (UNEQUAL_MAC_ADDR(rbssid, aucNullAddr)) { + if (EQUAL_MAC_ADDR(&(prGlueInfo->prP2PInfo->aucblackMACList[i]), rbssid)) { + fgIsExsit = TRUE; + return fgIsExsit; + } + } + } + + return fgIsExsit; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to return the max clients of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return; + } + + if (u4MaxClient == 0 || prGlueInfo->prP2PInfo->ucMaxClients >= P2P_MAXIMUM_CLIENT_COUNT) + prGlueInfo->prP2PInfo->ucMaxClients = P2P_MAXIMUM_CLIENT_COUNT; + else + prGlueInfo->prP2PInfo->ucMaxClients = u4MaxClient; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief to return the max clients of Hotspot +* +* \param[in] +* prGlueInfo +* +* \return +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalP2PMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient) +{ + if ((!prGlueInfo) || (!prGlueInfo->prP2PInfo)) { + ASSERT(FALSE); + return FALSE; + } + + if (prGlueInfo->prP2PInfo->ucMaxClients) { + if ((UINT_8) u4NumClient > prGlueInfo->prP2PInfo->ucMaxClients) + return TRUE; + else + return FALSE; + } + + return FALSE; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c new file mode 100644 index 0000000000000..075045f547b7c --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_proc.c @@ -0,0 +1,1020 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_proc.c#1 +*/ + +/*! \file "gl_proc.c" + \brief This file defines the interface which can interact with users in /proc fs. + + Detail description. +*/ + +/* +** Log: gl_proc.c + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support +** \main\maintrunk.MT5921\19 2008-09-02 21:08:37 GMT mtk01461 +** Fix the compile error of SPRINTF() +** \main\maintrunk.MT5921\18 2008-08-10 18:48:28 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\17 2008-08-04 16:52:01 GMT mtk01461 +** Add proc dbg print message of DOMAIN_INDEX level +** \main\maintrunk.MT5921\16 2008-07-10 00:45:16 GMT mtk01461 +** Remove the check of MCR offset, we may use the MCR address which is not align to DW boundary or proprietary usage. +** \main\maintrunk.MT5921\15 2008-06-03 20:49:44 GMT mtk01461 +** \main\maintrunk.MT5921\14 2008-06-02 22:56:00 GMT mtk01461 +** Rename some functions for linux proc +** \main\maintrunk.MT5921\13 2008-06-02 20:23:18 GMT mtk01461 +** Revise PROC mcr read / write for supporting TELNET +** \main\maintrunk.MT5921\12 2008-03-28 10:40:25 GMT mtk01461 +** Remove temporary set desired rate in linux proc +** \main\maintrunk.MT5921\11 2008-01-07 15:07:29 GMT mtk01461 +** Add User Update Desired Rate Set for QA in Linux +** \main\maintrunk.MT5921\10 2007-12-11 00:11:14 GMT mtk01461 +** Fix SPIN_LOCK protection +** \main\maintrunk.MT5921\9 2007-12-04 18:07:57 GMT mtk01461 +** Add additional debug category to proc +** \main\maintrunk.MT5921\8 2007-11-02 01:03:23 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** \main\maintrunk.MT5921\7 2007-10-25 18:08:14 GMT mtk01461 +** Add VOIP SCAN Support & Refine Roaming +** Revision 1.3 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.2 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "precomp.h" + +/* #include "wlan_lib.h" */ +/* #include "debug.h" */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#define PROC_WLAN_THERMO "wlanThermo" +#define PROC_DRV_STATUS "status" +#define PROC_RX_STATISTICS "rx_statistics" +#define PROC_TX_STATISTICS "tx_statistics" +#define PROC_DBG_LEVEL_NAME "dbgLevel" +#define PROC_NEED_TX_DONE "TxDoneCfg" +#define PROC_AUTO_PER_CFG "autoPerCfg" +#define PROC_ROOT_NAME "wlan" +#define PROC_CMD_DEBUG_NAME "cmdDebug" + +#define PROC_MCR_ACCESS_MAX_USER_INPUT_LEN 20 +#define PROC_RX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_TX_STATISTICS_MAX_USER_INPUT_LEN 10 +#define PROC_DBG_LEVEL_MAX_USER_INPUT_LEN (20*10) +#define PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN 8 + +#define PROC_UID_SHELL 2000 +#define PROC_GID_WIFI 1010 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +/* static UINT_32 u4McrOffset; */ +#if CFG_SUPPORT_THERMO_THROTTLING +static P_GLUE_INFO_T g_prGlueInfo_proc; +#endif +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading MCR register to User Space, the offset of +* the MCR is specified in u4McrOffset. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +static int procMCRRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + char *p = page; + UINT_32 u4Count; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + rMcrInfo.u4McrOffset = u4McrOffset; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryMcrRead, + (PVOID)&rMcrInfo, sizeof(rMcrInfo), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + + /* SPRINTF(p, ("MCR (0x%08lxh): 0x%08lx\n", */ + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData)); */ + + u4Count = (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procMCRRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for writing MCR register to HW or update u4McrOffset +* for reading MCR later. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procMCRWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo; + char acBuf[PROC_MCR_ACCESS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + int i4CopySize; + PARAM_CUSTOM_MCR_RW_STRUCT_T rMcrInfo; + UINT_32 u4BufLen; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(data); + + i4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + if (copy_from_user(acBuf, buffer, i4CopySize)) + return 0; + acBuf[i4CopySize] = '\0'; + + if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 2) { + /* NOTE: Sometimes we want to test if bus will still be ok, after accessing + * the MCR which is not align to DW boundary. + */ + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv((struct net_device *)data)); + + u4McrOffset = rMcrInfo.u4McrOffset; + + /* printk("Write 0x%lx to MCR 0x%04lx\n", */ + /* rMcrInfo.u4McrOffset, rMcrInfo.u4McrData); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetMcrWrite, + (PVOID)&rMcrInfo, sizeof(rMcrInfo), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + + if (sscanf(acBuf, "0x%lx 0x%lx", &rMcrInfo.u4McrOffset, &rMcrInfo.u4McrData) == 1) { + /* if (IS_ALIGN_4(rMcrInfo.u4McrOffset)) */ + u4McrOffset = rMcrInfo.u4McrOffset; + } + + return count; + +} /* end of procMCRWrite() */ +#endif + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver Status to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procDrvStatusRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("GLUE LAYER STATUS:")); + SPRINTF(p, ("\n==================")); + + SPRINTF(p, ("\n* Number of Pending Frames: %ld\n", prGlueInfo->u4TxPendingFrameNum)); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryDrvStatusForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procDrvStatusRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver RX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procRxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("RX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryRxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procRxStatisticsRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver RX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procRxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetRxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procRxStatisticsWrite() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reading Driver TX Statistic Counters to User Space. +* +* \param[in] page Buffer provided by kernel. +* \param[in out] start Start Address to read(3 methods). +* \param[in] off Offset. +* \param[in] count Allowable number to read. +* \param[out] eof End of File indication. +* \param[in] data Pointer to the private data structure. +* +* \return number of characters print to the buffer from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procTxStatisticsRead(char *page, char **start, off_t off, int count, int *eof, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char *p = page; + UINT_32 u4Count; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + /* Kevin: Apply PROC read method 1. */ + if (off != 0) + return 0; /* To indicate end of file. */ + + SPRINTF(p, ("TX STATISTICS (Write 1 to clear):")); + SPRINTF(p, ("\n=================================\n")); + + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidQueryTxStatisticsForLinuxProc(prGlueInfo->prAdapter, p, &u4Count); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + u4Count += (UINT_32) (p - page); + + *eof = 1; + + return (int)u4Count; + +} /* end of procTxStatisticsRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The PROC function for reset Driver TX Statistic Counters. +* +* \param[in] file pointer to file. +* \param[in] buffer Buffer from user space. +* \param[in] count Number of characters to write +* \param[in] data Pointer to the private data structure. +* +* \return number of characters write from User Space. +*/ +/*----------------------------------------------------------------------------*/ +static int procTxStatisticsWrite(struct file *file, const char *buffer, unsigned long count, void *data) +{ + P_GLUE_INFO_T prGlueInfo = ((struct net_device *)data)->priv; + char acBuf[PROC_RX_STATISTICS_MAX_USER_INPUT_LEN + 1]; /* + 1 for "\0" */ + UINT_32 u4CopySize; + UINT_32 u4ClearCounter; + + GLUE_SPIN_LOCK_DECLARATION(); + + ASSERT(data); + + u4CopySize = (count < (sizeof(acBuf) - 1)) ? count : (sizeof(acBuf) - 1); + copy_from_user(acBuf, buffer, u4CopySize); + acBuf[u4CopySize] = '\0'; + + if (kstrtoint(acBuf, 10, &u4ClearCounter) == 1) { + if (u4ClearCounter == 1) { + GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + + wlanoidSetTxStatisticsForLinuxProc(prGlueInfo->prAdapter); + + GLUE_RELEASE_SPIN_LOCK(prGlueInfo, SPIN_LOCK_FSM); + } + } + + return count; + +} /* end of procTxStatisticsWrite() */ +#endif +static struct proc_dir_entry *gprProcRoot; +static UINT_8 aucDbModuleName[][PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN] = { + "INIT", "HAL", "INTR", "REQ", "TX", "RX", "RFTEST", "EMU", "SW1", "SW2", + "SW3", "SW4", "HEM", "AIS", "RLM", "MEM", "CNM", "RSN", "BSS", "SCN", + "SAA", "AAA", "P2P", "QM", "SEC", "BOW", "WAPI", "ROAMING", "TDLS", "OID", + "NIC" +}; +static UINT_8 aucProcBuf[1536]; +static ssize_t procDbgLevelRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 i; + UINT_16 u2ModuleNum = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + kalStrCpy(temp, "\nTEMP |LOUD |INFO |TRACE|EVENT|STATE|WARN |ERROR\n" + "bit7 |bit6 |bit5 |bit4 |bit3 |bit2 |bit1 |bit0\n\n" + "Debug Module\tIndex\tLevel\tDebug Module\tIndex\tLevel\n\n"); + temp += kalStrLen(temp); + + u2ModuleNum = (sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0xfe; + for (i = 0; i < u2ModuleNum; i += 2) + SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\tDBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[i][0], i, aucDebugModule[i], + &aucDbModuleName[i+1][0], i+1, aucDebugModule[i+1])); + + if ((sizeof(aucDbModuleName) / PROC_DBG_LEVEL_MAX_DISPLAY_STR_LEN) & 0x1) + SPRINTF(temp, ("DBG_%s_IDX\t(0x%02x):\t0x%02x\n", + &aucDbModuleName[u2ModuleNum][0], u2ModuleNum, aucDebugModule[u2ModuleNum])); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procDbgLevelWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + UINT_32 u4NewDbgModule, u4NewDbgLevel; + UINT_8 i = 0; + UINT_32 u4CopySize = kalStrLen(aucProcBuf);//sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + + if (u4CopySize >= count + 1) + u4CopySize = count; + + kalMemSet(aucProcBuf, 0, u4CopySize); + + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + kalPrint("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + + while (temp) { + if (sscanf(temp, "0x%x:0x%x", &u4NewDbgModule, &u4NewDbgLevel) != 2) { + kalPrint("debug module and debug level should be one byte in length\n"); + break; + } + if (u4NewDbgModule == 0xFF) { + for (i = 0; i < DBG_MODULE_NUM; i++) + aucDebugModule[i] = u4NewDbgLevel & DBG_CLASS_MASK; + + break; + } else if (u4NewDbgModule >= DBG_MODULE_NUM) { + kalPrint("debug module index should less than %d\n", DBG_MODULE_NUM); + break; + } + aucDebugModule[u4NewDbgModule] = u4NewDbgLevel & DBG_CLASS_MASK; + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + return count; +} + + +static const struct file_operations dbglevel_ops = { + .owner = THIS_MODULE, + .read = procDbgLevelRead, + .write = procDbgLevelWrite, +}; + +static ssize_t procTxDoneCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + UINT_16 u2TxDoneCfg = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + u2TxDoneCfg = StatsGetCfgTxDone(); + SPRINTF(temp, ("Tx Done Configure:\nARP %d\tDNS %d\nTCP %d\tUDP %d\nEAPOL %d\tDHCP %d\nICMP %d\n", + !!(u2TxDoneCfg & CFG_ARP), !!(u2TxDoneCfg & CFG_DNS), !!(u2TxDoneCfg & CFG_TCP), + !!(u2TxDoneCfg & CFG_UDP), !!(u2TxDoneCfg & CFG_EAPOL), !!(u2TxDoneCfg & CFG_DHCP), + !!(u2TxDoneCfg & CFG_ICMP))); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procTxDoneCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ +#define MODULE_NAME_LENGTH 6 + + UINT_8 i = 0; + UINT_32 u4CopySize = kalStrLen(aucProcBuf);//sizeof(aucProcBuf); + UINT_8 *temp = &aucProcBuf[0]; + UINT_16 u2SetTxDoneCfg = 0; + UINT_16 u2ClsTxDoneCfg = 0; + UINT_8 aucModule[MODULE_NAME_LENGTH]; + UINT_32 u4Enabled; + UINT_8 aucModuleArray[][MODULE_NAME_LENGTH] = {"ARP", "DNS", "TCP", "UDP", "EAPOL", "DHCP", "ICMP"}; + + if (u4CopySize >= count + 1) + u4CopySize = count; + + kalMemSet(aucProcBuf, 0, u4CopySize); + if (copy_from_user(aucProcBuf, buffer, u4CopySize)) { + kalPrint("error of copy from user\n"); + return -EFAULT; + } + aucProcBuf[u4CopySize] = '\0'; + temp = &aucProcBuf[0]; + while (temp) { + /* pick up a string and teminated after meet : */ + if (sscanf(temp, "%s %d", aucModule, &u4Enabled) != 2) { + kalPrint("read param fail, aucModule=%s\n", aucModule); + break; + } + for (i = 0; i < sizeof(aucModuleArray)/MODULE_NAME_LENGTH; i++) { + if (kalStrniCmp(aucModule, aucModuleArray[i], MODULE_NAME_LENGTH) == 0) { + if (u4Enabled) + u2SetTxDoneCfg |= 1 << i; + else + u2ClsTxDoneCfg |= 1 << i; + break; + } + } + temp = kalStrChr(temp, ','); + if (!temp) + break; + temp++; /* skip ',' */ + } + if (u2SetTxDoneCfg) + StatsSetCfgTxDone(u2SetTxDoneCfg, TRUE); + + if (u2ClsTxDoneCfg) + StatsSetCfgTxDone(u2ClsTxDoneCfg, FALSE); + return count; +} + +static const struct file_operations proc_txdone_ops = { + .owner = THIS_MODULE, + .read = procTxDoneCfgRead, + .write = procTxDoneCfgWrite, +}; + +static ssize_t procAutoPerCfgRead(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_8 *temp = &aucProcBuf[0]; + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + SPRINTF(temp, ("Auto Performance Configure:\nperiod\tL1\nL2\tL3\n")); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static ssize_t procAutoPerCfgWrite(struct file *file, const char *buffer, size_t count, loff_t *data) +{ + DBGLOG(INIT, WARN, "%s\n", __func__); + return 0; +} + +static const struct file_operations auto_per_ops = { + .owner = THIS_MODULE, + .read = procAutoPerCfgRead, + .write = procAutoPerCfgWrite, +}; + + +static ssize_t procCmdDebug(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + UINT_32 u4CopySize = 0; + + /* if *f_ops>0, we should return 0 to make cat command exit */ + if (*f_pos > 0) + return 0; + + wlanDumpTcResAndTxedCmd(aucProcBuf, sizeof(aucProcBuf)); + + u4CopySize = kalStrLen(aucProcBuf); + if (u4CopySize > count) + u4CopySize = count; + if (copy_to_user(buf, aucProcBuf, u4CopySize)) { + kalPrint("copy to user failed\n"); + return -EFAULT; + } + + *f_pos += u4CopySize; + return (ssize_t)u4CopySize; +} + +static const struct file_operations proc_CmdDebug_ops = { + .owner = THIS_MODULE, + .read = procCmdDebug, +}; + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function create a PROC fs in linux /proc/net subdirectory. +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ + +#if CFG_SUPPORT_THERMO_THROTTLING + +/** + * This function is called then the /proc file is read + * + */ +typedef struct _COEX_BUF1 { + UINT8 buffer[128]; + INT32 availSize; +} COEX_BUF1, *P_COEX_BUF1; + +COEX_BUF1 gCoexBuf1; + +static ssize_t procfile_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) +{ + + INT32 retval = 0; + INT32 i_ret = 0; + CHAR *warn_msg = "no data available, please run echo 15 xx > /proc/driver/wmt_psm first\n"; + + if (*f_pos > 0) { + retval = 0; + } else { + /*len = sprintf(page, "%d\n", g_psm_enable); */ +#if 1 + if (gCoexBuf1.availSize <= 0) { + DBGLOG(INIT, WARN, "no data available\n"); + retval = strlen(warn_msg) + 1; + if (count < retval) + retval = count; + i_ret = copy_to_user(buf, warn_msg, retval); + if (i_ret) { + DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } else +#endif + { + INT32 i = 0; + INT32 len = 0; + CHAR msg_info[128]; + INT32 max_num = 0; + /*we do not check page buffer, because there are only 100 bytes in g_coex_buf, no reason page + buffer is not enough, a bomb is placed here on unexpected condition */ + + DBGLOG(INIT, TRACE, "%d bytes available\n", gCoexBuf1.availSize); + max_num = ((sizeof(msg_info) > count ? sizeof(msg_info) : count) - 1) / 5; + + if (max_num > gCoexBuf1.availSize) + max_num = gCoexBuf1.availSize; + else + DBGLOG(INIT, TRACE, + "round to %d bytes due to local buffer size limitation\n", max_num); + + for (i = 0; i < max_num; i++) + len += sprintf(msg_info + len, "%d", gCoexBuf1.buffer[i]); + + len += sprintf(msg_info + len, "\n"); + retval = len; + + i_ret = copy_to_user(buf, msg_info, retval); + if (i_ret) { + DBGLOG(INIT, ERROR, "copy to buffer failed, ret:%d\n", retval); + retval = -EFAULT; + goto err_exit; + } + *f_pos += retval; + } + } + gCoexBuf1.availSize = 0; +err_exit: + + return retval; +} + +#if 1 +typedef INT32 (*WLAN_DEV_DBG_FUNC)(void); +static INT32 wlan_get_thermo_power(void); +static INT32 wlan_get_link_mode(void); + +static const WLAN_DEV_DBG_FUNC wlan_dev_dbg_func[] = { + [0] = wlan_get_thermo_power, + [1] = wlan_get_link_mode, + +}; + +INT32 wlan_get_thermo_power(void) +{ + P_ADAPTER_T prAdapter; + + prAdapter = g_prGlueInfo_proc->prAdapter; + + if (prAdapter->u4AirDelayTotal > 100) + gCoexBuf1.buffer[0] = 100; + else + gCoexBuf1.buffer[0] = prAdapter->u4AirDelayTotal; + gCoexBuf1.availSize = 1; + DBGLOG(RLM, TRACE, "PROC %s thrmo_power(%d)\n", __func__, gCoexBuf1.buffer[0]); + + return 0; +} + +INT32 wlan_get_link_mode(void) +{ + UINT_8 ucLinkMode = 0; + P_ADAPTER_T prAdapter; + BOOLEAN fgIsAPmode; + + prAdapter = g_prGlueInfo_proc->prAdapter; + fgIsAPmode = p2pFuncIsAPMode(prAdapter->rWifiVar.prP2pFsmInfo); + + DBGLOG(RLM, TRACE, "PROC %s AIS(%d)P2P(%d)AP(%d)\n", + __func__, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState, + prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState, fgIsAPmode); + +#if 1 + + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + ucLinkMode |= BIT(0); + if (prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].eConnectionState == PARAM_MEDIA_STATE_CONNECTED) + ucLinkMode |= BIT(1); + if (fgIsAPmode) + ucLinkMode |= BIT(2); + +#endif + gCoexBuf1.buffer[0] = ucLinkMode; + gCoexBuf1.availSize = 1; + + return 0; +} + +static ssize_t procfile_write(struct file *filp, const char __user *buffer, size_t count, loff_t *f_pos) +{ + char buf[256]; + char *pBuf; + ULONG len = count; + INT32 x = 0, y = 0, z = 0; + char *pToken = NULL; + char *pDelimiter = " \t"; + INT32 i4Ret = 0; + + if (copy_from_user(gCoexBuf1.buffer, buffer, count)) + return -EFAULT; + /* gCoexBuf1.availSize = count; */ + + /* return gCoexBuf1.availSize; */ +#if 1 + DBGLOG(INIT, TRACE, "write parameter len = %d\n\r", (INT32) len); + if (len >= sizeof(buf)) { + DBGLOG(INIT, ERROR, "input handling fail!\n"); + len = sizeof(buf) - 1; + return -1; + } + + if (copy_from_user(buf, buffer, len)) + return -EFAULT; + buf[len] = '\0'; + DBGLOG(INIT, TRACE, "write parameter data = %s\n\r", buf); + + pBuf = buf; + pToken = strsep(&pBuf, pDelimiter); + + if (pToken) /* x = NULL != pToken ? simple_strtol(pToken, NULL, 16) : 0; */ + i4Ret = kalkStrtos32(pToken, 16, &x); + if (!i4Ret) + DBGLOG(INIT, TRACE, "x = 0x%x\n", x); + +#if 1 + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + i4Ret = kalkStrtos32(pToken, 16, &y); /* y = simple_strtol(pToken, NULL, 16); */ + if (!i4Ret) + DBGLOG(INIT, TRACE, "y = 0x%08x\n\r", y); + } else { + y = 3000; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + y = 0x80000000; + } + + pToken = strsep(&pBuf, "\t\n "); + if (pToken != NULL) { + i4Ret = kalkStrtos32(pToken, 16, &z); /* z = simple_strtol(pToken, NULL, 16); */ + if (!i4Ret) + DBGLOG(INIT, TRACE, "z = 0x%08x\n\r", z); + } else { + z = 10; + /*efuse, register read write default value */ + if (0x11 == x || 0x12 == x || 0x13 == x) + z = 0xffffffff; + } + + DBGLOG(INIT, TRACE, " x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z); +#endif + + if (((sizeof(wlan_dev_dbg_func) / sizeof(wlan_dev_dbg_func[0])) > x) && NULL != wlan_dev_dbg_func[x]) + (*wlan_dev_dbg_func[x]) (); + else + DBGLOG(INIT, ERROR, "no handler defined for command id(0x%08x)\n\r", x); +#endif + + /* len = gCoexBuf1.availSize; */ + return len; +} +#endif + static const struct file_operations proc_fops = { + .owner = THIS_MODULE, + .read = procfile_read, + .write = procfile_write, + }; +#endif + +INT_32 procInitFs(VOID) +{ + struct proc_dir_entry *prEntry; + + if (init_net.proc_net == (struct proc_dir_entry *)NULL) { + kalPrint("init proc fs fail: proc_net == NULL\n"); + return -ENOENT; + } + + /* + * Directory: Root (/proc/net/wlan0) + */ + + gprProcRoot = proc_mkdir(PROC_ROOT_NAME, init_net.proc_net); + if (!gprProcRoot) { + kalPrint("gprProcRoot == NULL\n"); + return -ENOENT; + } + proc_set_user(gprProcRoot, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_DBG_LEVEL_NAME, 0664, gprProcRoot, &dbglevel_ops); + if (prEntry == NULL) { + kalPrint("Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_NEED_TX_DONE, 0664, gprProcRoot, &proc_txdone_ops); + if (prEntry == NULL) { + kalPrint("Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + prEntry = proc_create(PROC_AUTO_PER_CFG, 0664, gprProcRoot, &auto_per_ops); + if (prEntry == NULL) { + kalPrint("Unable to create /proc entry autoPerCfg\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + + return 0; +} /* end of procInitProcfs() */ + +INT_32 procUninitProcFs(VOID) +{ + remove_proc_entry(PROC_DBG_LEVEL_NAME, gprProcRoot); + remove_proc_subtree(PROC_ROOT_NAME, init_net.proc_net); + remove_proc_entry(PROC_AUTO_PER_CFG, gprProcRoot); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clean up a PROC fs created by procInitProcfs(). +* +* \param[in] prDev Pointer to the struct net_device. +* \param[in] pucDevName Pointer to the name of net_device. +* +* \return N/A +*/ +/*----------------------------------------------------------------------------*/ +INT_32 procRemoveProcfs(VOID) +{ + /* remove root directory (proc/net/wlan0) */ + /* remove_proc_entry(pucDevName, init_net.proc_net); */ + remove_proc_entry(PROC_WLAN_THERMO, gprProcRoot); + remove_proc_entry(PROC_CMD_DEBUG_NAME, gprProcRoot); +#if CFG_SUPPORT_THERMO_THROTTLING + g_prGlueInfo_proc = NULL; +#endif + return 0; +} /* end of procRemoveProcfs() */ + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo) +{ + struct proc_dir_entry *prEntry; + + DBGLOG(INIT, TRACE, "[%s]\n", __func__); + +#if CFG_SUPPORT_THERMO_THROTTLING + g_prGlueInfo_proc = prGlueInfo; +#endif + + prGlueInfo->pProcRoot = gprProcRoot; + + prEntry = proc_create(PROC_WLAN_THERMO, 0664, gprProcRoot, &proc_fops); + if (prEntry == NULL) { + DBGLOG(INIT, ERROR, "Unable to create /proc entry\n\r"); + return -1; + } + + prEntry = proc_create(PROC_CMD_DEBUG_NAME, 0444, gprProcRoot, &proc_CmdDebug_ops); + if (prEntry == NULL) { + kalPrint("Unable to create /proc entry dbgLevel\n\r"); + return -1; + } + proc_set_user(prEntry, KUIDT_INIT(PROC_UID_SHELL), KGIDT_INIT(PROC_GID_WIFI)); + return 0; +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c new file mode 100644 index 0000000000000..f97db8a69fd21 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_rst.c @@ -0,0 +1,228 @@ +/* +** Id: @(#) gl_rst.c@@ +*/ + +/*! \file gl_rst.c + \brief Main routines for supporintg MT6620 whole-chip reset mechanism + + This file contains the support routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_rst.c + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 04 22 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * skip power-off handshaking when RESET indication is received. + * + * 04 14 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * 1. add code to put whole-chip resetting trigger when abnormal firmware assertion is detected + * 2. add dummy function for both Win32 and Linux part. + * + * 03 30 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * use netlink unicast instead of broadcast + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include + +#include "precomp.h" +#include "gl_rst.h" + +#if CFG_CHIP_RESET_SUPPORT + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +BOOLEAN fgIsResetting = FALSE; +UINT_32 g_IsNeedDoChipReset = 0; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static RESET_STRUCT_T wifi_rst; + +static void mtk_wifi_reset(struct work_struct *work); + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. register wifi reset callback + * 2. initialize wifi reset work + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetInit(VOID) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + /* 1. Register reset callback */ + mtk_wcn_wmt_msgcb_reg(WMTDRV_TYPE_WIFI, (PF_WMT_CB) glResetCallback); +#endif /* MTK_WCN_SINGLE_MODULE */ + + /* 2. Initialize reset work */ + INIT_WORK(&(wifi_rst.rst_work), mtk_wifi_reset); + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is responsible for + * 1. deregister wifi reset callback + * + * @param none + * + * @retval none + */ +/*----------------------------------------------------------------------------*/ +VOID glResetUninit(VOID) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + /* 1. Deregister reset callback */ + mtk_wcn_wmt_msgcb_unreg(WMTDRV_TYPE_WIFI); +#endif /* MTK_WCN_SINGLE_MODULE */ + +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is invoked when there is reset messages indicated + * + * @param eSrcType + * eDstType + * eMsgType + * prMsgBody + * u4MsgLength + * + * @retval + */ +/*----------------------------------------------------------------------------*/ +static void *glResetCallback(ENUM_WMTDRV_TYPE_T eSrcType, + ENUM_WMTDRV_TYPE_T eDstType, + ENUM_WMTMSG_TYPE_T eMsgType, void *prMsgBody, unsigned int u4MsgLength) +{ + switch (eMsgType) { + case WMTMSG_TYPE_RESET: + if (u4MsgLength == sizeof(ENUM_WMTRSTMSG_TYPE_T)) { + P_ENUM_WMTRSTMSG_TYPE_T prRstMsg = (P_ENUM_WMTRSTMSG_TYPE_T) prMsgBody; + + switch (*prRstMsg) { + case WMTRSTMSG_RESET_START: + DBGLOG(INIT, WARN, "Whole chip reset start!\n"); + fgIsResetting = TRUE; + wifi_reset_start(); + break; + + case WMTRSTMSG_RESET_END: + DBGLOG(INIT, WARN, "Whole chip reset end!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_SUCCESS; + schedule_work(&(wifi_rst.rst_work)); + break; + + case WMTRSTMSG_RESET_END_FAIL: + DBGLOG(INIT, WARN, "Whole chip reset fail!\n"); + fgIsResetting = FALSE; + wifi_rst.rst_data = RESET_FAIL; + schedule_work(&(wifi_rst.rst_work)); + break; + + default: + break; + } + } + break; + + default: + break; + } + + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for wifi reset + * + * @param skb + * info + * + * @retval 0 + * nonzero + */ +/*----------------------------------------------------------------------------*/ +static void mtk_wifi_reset(struct work_struct *work) +{ + RESET_STRUCT_T *rst = container_of(work, RESET_STRUCT_T, rst_work); + + wifi_reset_end(rst->rst_data); +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for generating reset request to WMT + * + * @param None + * + * @retval None + */ +/*----------------------------------------------------------------------------*/ +VOID glSendResetRequest(VOID) +{ + /* WMT thread would trigger whole chip reset itself */ +} + +/*----------------------------------------------------------------------------*/ +/*! + * @brief This routine is called for checking if connectivity chip is resetting + * + * @param None + * + * @retval TRUE + * FALSE + */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsResetting(VOID) +{ + return fgIsResetting; +} + +#endif /* CFG_CHIP_RESET_SUPPORT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c new file mode 100644 index 0000000000000..862d011a43df3 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_vendor.c @@ -0,0 +1,1220 @@ +/* +** Id: @(#) gl_cfg80211.c@@ +*/ + +/*! \file gl_cfg80211.c + \brief Main routines for supporintg MT6620 cfg80211 control interface + + This file contains the support routines of Linux driver for MediaTek Inc. 802.11 + Wireless LAN Adapters. +*/ + +/* +** Log: gl_cfg80211.c +** +** 09 05 2013 cp.wu +** correct length to pass to wlanoidSetBssid() +** +** 09 04 2013 cp.wu +** fix typo +** +** 09 03 2013 cp.wu +** add path for reassociation +** +** 11 23 2012 yuche.tsai +** [ALPS00398671] [Acer-Tablet] Remove Wi-Fi Direct completely +** Fix bug of WiFi may reboot under user load, when WiFi Direct is removed.. +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 30 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . + * +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include + +#include "gl_os.h" +#include "wlan_lib.h" +#include "gl_wext.h" +#include "precomp.h" +#include "gl_cfg80211.h" +#include "gl_vendor.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +static struct nla_policy nla_parse_policy[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1] = { + [GSCAN_ATTRIBUTE_NUM_BUCKETS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BASE_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKETS_BAND] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_ID] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_PERIOD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BUCKET_CHANNELS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_THRESHOLD] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_REPORT_EVENTS] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_BSSID] = {.type = NLA_UNSPEC}, + [GSCAN_ATTRIBUTE_RSSI_LOW] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_HIGH] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE] = {.type = NLA_U32}, + [GSCAN_ATTRIBUTE_MIN_BREACHING] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_NUM_AP] = {.type = NLA_U16}, + [GSCAN_ATTRIBUTE_HOTLIST_FLUSH] = {.type = NLA_U8}, + [GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH] = {.type = NLA_U8}, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + struct nlattr *attr; + UINT_32 band = 0; + UINT_8 ucNumOfChannel, i, j; + RF_CHANNEL_INFO_T aucChannelList[64]; + UINT_32 num_channels; + wifi_channel channels[64]; + struct sk_buff *skb; + + ASSERT(wiphy && wdev); + if ((data == NULL) || !data_len) + return -EINVAL; + + DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_BAND) + band = nla_get_u32(attr); + + DBGLOG(REQ, INFO, "Get channel list for band: %d\n", band); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + if (band == 0) { /* 2.4G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_2G4, TRUE, + 64, &ucNumOfChannel, aucChannelList); + } else { /* 5G band */ + rlmDomainGetChnlList(prGlueInfo->prAdapter, BAND_5G, TRUE, + 64, &ucNumOfChannel, aucChannelList); + } + + kalMemZero(channels, sizeof(channels)); + for (i = 0, j = 0; i < ucNumOfChannel; i++) { + /* We need to report frequency list to HAL */ + channels[j] = nicChannelNum2Freq(aucChannelList[i].ucChannelNum) / 1000; + if (channels[j] == 0) + continue; + else if ((prGlueInfo->prAdapter->rWifiVar.rConnSettings.u2CountryCode == COUNTRY_CODE_TW) && + (channels[j] >= 5180 && channels[j] <= 5260)) { + /* Taiwan NCC has resolution to follow FCC spec to support 5G Band 1/2/3/4 + * (CH36~CH48, CH52~CH64, CH100~CH140, CH149~CH165) + * Filter CH36~CH52 for compatible with some old devices. + */ + continue; + } else { + DBGLOG(REQ, INFO, "channels[%d] = %d\n", j, channels[j]); + j++; + } + } + num_channels = j; + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(channels)); + if (!skb) { + DBGLOG(REQ, ERROR, "Allocate skb failed\n"); + return -ENOMEM; + } + + if (unlikely(nla_put_u32(skb, WIFI_ATTRIBUTE_NUM_CHANNELS, num_channels) < 0)) + goto nla_put_failure; + + if (unlikely(nla_put(skb, WIFI_ATTRIBUTE_CHANNEL_LIST, + (sizeof(wifi_channel) * num_channels), channels) < 0)) + goto nla_put_failure; + + return cfg80211_vendor_cmd_reply(skb); + +nla_put_failure: + kfree_skb(skb); + return -EFAULT; +} + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + struct nlattr *attr; + UINT_8 country[2] = {0, 0}; + + ASSERT(wiphy && wdev); + if ((data == NULL) || (data_len == 0)) + return -EINVAL; + + DBGLOG(REQ, INFO, "vendor command: data_len=%d\n", data_len); + + attr = (struct nlattr *)data; + if (attr->nla_type == WIFI_ATTRIBUTE_COUNTRY_CODE) { + country[0] = *((PUINT_8)nla_data(attr)); + country[1] = *((PUINT_8)nla_data(attr) + 1); + } + + DBGLOG(REQ, INFO, "Set country code: %c%c\n", country[0], country[1]); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + if (!prGlueInfo) + return -EFAULT; + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, country, 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T rGscanCapabilities; + struct sk_buff *skb; + /* UINT_32 u4BufLen; */ + + DBGLOG(REQ, TRACE, "%s for vendor command \r\n", __func__); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rGscanCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rGscanCapabilities, sizeof(rGscanCapabilities)); + + /*rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rGscanCapabilities, + sizeof(rGscanCapabilities), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); */ + rGscanCapabilities.max_scan_cache_size = PSCAN_MAX_SCAN_CACHE_SIZE; + rGscanCapabilities.max_scan_buckets = GSCAN_MAX_BUCKETS; + rGscanCapabilities.max_ap_cache_per_scan = PSCAN_MAX_AP_CACHE_PER_SCAN; + rGscanCapabilities.max_rssi_sample_size = 10; + rGscanCapabilities.max_scan_reporting_threshold = GSCAN_MAX_REPORT_THRESHOLD; + rGscanCapabilities.max_hotlist_aps = MAX_HOTLIST_APS; + rGscanCapabilities.max_significant_wifi_change_aps = MAX_SIGNIFICANT_CHANGE_APS; + rGscanCapabilities.max_bssid_history_entries = PSCAN_MAX_AP_CACHE_PER_SCAN * PSCAN_MAX_SCAN_CACHE_SIZE; + + /* NLA_PUT_U8(skb, NL80211_TESTMODE_STA_STATISTICS_INVALID, 0); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_ID, GOOGLE_OUI); */ + /* NLA_PUT_U32(skb, NL80211_ATTR_VENDOR_SUBCMD, GSCAN_SUBCMD_GET_CAPABILITIES); */ + /*NLA_PUT(skb, GSCAN_ATTRIBUTE_CAPABILITIES, sizeof(rGscanCapabilities), &rGscanCapabilities);*/ + if (unlikely(nla_put(skb, GSCAN_ATTRIBUTE_CAPABILITIES, + sizeof(rGscanCapabilities), &rGscanCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + /* CMD_GSCN_REQ_T rCmdGscnParam; */ + + /* INT_32 i4Status = -EINVAL; */ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_REPORT_EVENTS + 1]; + struct nlattr *pbucket, *pchannel; + UINT_32 len_basic, len_bucket, len_channel; + int i, j, k; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + + prWifiScanCmd = (P_PARAM_WIFI_GSCAN_CMD_PARAMS) kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (!prWifiScanCmd) { + DBGLOG(REQ, ERROR, "Can not alloc memory for PARAM_WIFI_GSCAN_CMD_PARAMS\n"); + return -ENOMEM; + } + + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_REPORT_EVENTS + 1)); + + nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL); + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BASE_PERIOD: + prWifiScanCmd->base_period = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_BUCKETS: + prWifiScanCmd->num_buckets = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_buckets=%d nla_len=%d, \r\n", + *(UINT_32 *) attr[k], prWifiScanCmd->num_buckets, attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d pbucket=%p\r\n", len_basic, pbucket); + + for (i = 0; i < prWifiScanCmd->num_buckets; i++) { + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_REPORT_EVENTS, (struct nlattr *)pbucket, + nla_parse_policy,NULL) < 0) + goto nla_put_failure; + len_bucket = 0; + for (k = GSCAN_ATTRIBUTE_NUM_BUCKETS; k <= GSCAN_ATTRIBUTE_REPORT_EVENTS; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BUCKETS_BAND: + prWifiScanCmd->buckets[i].band = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_ID: + prWifiScanCmd->buckets[i].bucket = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_PERIOD: + prWifiScanCmd->buckets[i].period = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_REPORT_EVENTS: + prWifiScanCmd->buckets[i].report_events = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS: + prWifiScanCmd->buckets[i].num_channels = nla_get_u32(attr[k]); + len_bucket += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "bucket%d: attr=0x%x, num_channels=%d nla_len = %d, \r\n", + i, *(UINT_32 *) attr[k], nla_get_u32(attr[k]), attr[k]->nla_len); + break; + } + } + } + pbucket = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + DBGLOG(REQ, TRACE, "+++pure bucket size=%d pbucket=%p \r\n", len_bucket, pbucket); + pbucket = (struct nlattr *)((UINT_8 *) pbucket + len_bucket); + /* pure bucket payload, not include channels */ + + /*don't need to use nla_parse_nested to parse channels */ + /* the header of channel in bucket i */ + pchannel = (struct nlattr *)((UINT_8 *) pbucket + NLA_HDRLEN); + for (j = 0; j < prWifiScanCmd->buckets[i].num_channels; j++) { + prWifiScanCmd->buckets[i].channels[j].channel = nla_get_u32(pchannel); + len_channel = NLA_ALIGN(pchannel->nla_len); + DBGLOG(REQ, TRACE, + "attr=0x%x, channel=%d, \r\n", *(UINT_32 *) pchannel, nla_get_u32(pchannel)); + + pchannel = (struct nlattr *)((UINT_8 *) pchannel + len_channel); + } + pbucket = pchannel; + } + + DBGLOG(REQ, TRACE, "base_period=%d, num_buckets=%d, bucket0: %d %d %d %d", + prWifiScanCmd->base_period, prWifiScanCmd->num_buckets, + prWifiScanCmd->buckets[0].bucket, prWifiScanCmd->buckets[0].period, + prWifiScanCmd->buckets[0].band, prWifiScanCmd->buckets[0].report_events); + + DBGLOG(REQ, TRACE, "num_channels=%d, channel0=%d, channel1=%d; num_channels=%d, channel0=%d, channel1=%d", + prWifiScanCmd->buckets[0].num_channels, + prWifiScanCmd->buckets[0].channels[0].channel, prWifiScanCmd->buckets[0].channels[1].channel, + prWifiScanCmd->buckets[1].num_channels, + prWifiScanCmd->buckets[1].channels[0].channel, prWifiScanCmd->buckets[1].channels[1].channel); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAParam, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return -1; +} + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + + INT_32 i4Status = -EINVAL; + /*PARAM_WIFI_GSCAN_CMD_PARAMS rWifiScanCmd;*/ + P_PARAM_WIFI_GSCAN_CMD_PARAMS prWifiScanCmd = NULL; + struct nlattr *attr[GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1]; + /* UINT_32 num_scans = 0; */ /* another attribute */ + int k; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + /*kalMemZero(&rWifiScanCmd, sizeof(rWifiScanCmd));*/ + prWifiScanCmd = kalMemAlloc(sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), VIR_MEM_TYPE); + if (prWifiScanCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE + 1)); + + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) + goto nla_put_failure; + for (k = GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN; k <= GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN: + prWifiScanCmd->max_ap_per_scan = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_REPORT_THRESHOLD: + prWifiScanCmd->report_threshold = nla_get_u32(attr[k]); + break; + case GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE: + prWifiScanCmd->num_scans = nla_get_u32(attr[k]); + break; + } + } + } + DBGLOG(REQ, TRACE, "attr=0x%x, attr2=0x%x ", *(UINT_32 *) attr[GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN], + *(UINT_32 *) attr[GSCAN_ATTRIBUTE_REPORT_THRESHOLD]); + + DBGLOG(REQ, TRACE, "max_ap_per_scan=%d, report_threshold=%d num_scans=%d \r\n", + prWifiScanCmd->max_ap_per_scan, prWifiScanCmd->report_threshold, prWifiScanCmd->num_scans); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAConfig, + prWifiScanCmd, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return 0; + +nla_put_failure: + if (prWifiScanCmd != NULL) + kalMemFree(prWifiScanCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_GSCAN_CMD_PARAMS)); + return i4Status; +} + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_SIGNIFICANT_CHANGE prWifiChangeCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + for (i = 0; i < 6; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiChangeCmd = kalMemAlloc(sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE), VIR_MEM_TYPE); + if (prWifiChangeCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiChangeCmd, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH, + (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE; k <= GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE: + prWifiChangeCmd->rssi_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiChangeCmd->lost_ap_sample_size = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_MIN_BREACHING: + prWifiChangeCmd->min_breaching = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiChangeCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n", + *(UINT_32 *) attr[k], prWifiChangeCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiChangeCmd->num_ap; i++) { + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy,NULL) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiChangeCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiChangeCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiChangeCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiChangeCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, rssi_sample_size=%d lost_ap_sample_size=%d min_breaching=%d", + flush, prWifiChangeCmd->rssi_sample_size, prWifiChangeCmd->lost_ap_sample_size, + prWifiChangeCmd->min_breaching); + DBGLOG(REQ, TRACE, + "ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + prWifiChangeCmd->ap[0].channel, prWifiChangeCmd->ap[0].low, prWifiChangeCmd->ap[0].high, + prWifiChangeCmd->ap[1].channel, prWifiChangeCmd->ap[1].low, prWifiChangeCmd->ap[1].high); + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiChangeCmd) + kalMemFree(prWifiChangeCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_SIGNIFICANT_CHANGE)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + /*WLAN_STATUS rStatus;*/ + P_GLUE_INFO_T prGlueInfo = NULL; + CMD_SET_PSCAN_ADD_HOTLIST_BSSID rCmdPscnAddHotlist; + + INT_32 i4Status = -EINVAL; + P_PARAM_WIFI_BSSID_HOTLIST prWifiHotlistCmd = NULL; + UINT_8 flush = 0; + /* struct nlattr *attr[GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1]; */ + struct nlattr **attr = NULL; + struct nlattr *paplist; + int i, k; + UINT_32 len_basic, len_aplist; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + for (i = 0; i < 5; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", + *((UINT_32 *) data + i * 4), *((UINT_32 *) data + i * 4 + 1), + *((UINT_32 *) data + i * 4 + 2), *((UINT_32 *) data + i * 4 + 3)); + prWifiHotlistCmd = kalMemAlloc(sizeof(PARAM_WIFI_BSSID_HOTLIST), VIR_MEM_TYPE); + if (prWifiHotlistCmd == NULL) + goto nla_put_failure; + kalMemZero(prWifiHotlistCmd, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + attr = kalMemAlloc(sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1), VIR_MEM_TYPE); + if (attr == NULL) + goto nla_put_failure; + kalMemZero(attr, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_NUM_AP, (struct nlattr *)(data - NLA_HDRLEN), nla_parse_policy,NULL) < 0) + goto nla_put_failure; + len_basic = 0; + for (k = GSCAN_ATTRIBUTE_HOTLIST_FLUSH; k <= GSCAN_ATTRIBUTE_NUM_AP; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE: + prWifiHotlistCmd->lost_ap_sample_size = nla_get_u32(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_NUM_AP: + prWifiHotlistCmd->num_ap = nla_get_u16(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + DBGLOG(REQ, TRACE, "attr=0x%x, num_ap=%d nla_len=%d, \r\n", + *(UINT_32 *) attr[k], prWifiHotlistCmd->num_ap, attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_HOTLIST_FLUSH: + flush = nla_get_u8(attr[k]); + len_basic += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + paplist = (struct nlattr *)((UINT_8 *) data + len_basic); + DBGLOG(REQ, TRACE, "+++basic attribute size=%d flush=%d\r\n", len_basic, flush); + + if (paplist->nla_type == GSCAN_ATTRIBUTE_HOTLIST_BSSIDS) + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + + for (i = 0; i < prWifiHotlistCmd->num_ap; i++) { + if (nla_parse_nested(attr, GSCAN_ATTRIBUTE_RSSI_HIGH, (struct nlattr *)paplist, nla_parse_policy,NULL) < 0) + goto nla_put_failure; + paplist = (struct nlattr *)((UINT_8 *) paplist + NLA_HDRLEN); + /* request.attr_start(i) as nested attribute */ + len_aplist = 0; + for (k = GSCAN_ATTRIBUTE_BSSID; k <= GSCAN_ATTRIBUTE_RSSI_HIGH; k++) { + if (attr[k]) { + switch (k) { + case GSCAN_ATTRIBUTE_BSSID: + kalMemCopy(prWifiHotlistCmd->ap[i].bssid, nla_data(attr[k]), sizeof(mac_addr)); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_LOW: + prWifiHotlistCmd->ap[i].low = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + case GSCAN_ATTRIBUTE_RSSI_HIGH: + prWifiHotlistCmd->ap[i].high = nla_get_u32(attr[k]); + len_aplist += NLA_ALIGN(attr[k]->nla_len); + break; + } + } + } + if (((i + 1) % 4 == 0) || (i == prWifiHotlistCmd->num_ap - 1)) + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d\n", i, len_aplist); + else + DBGLOG(REQ, TRACE, "ap[%d], len_aplist=%d \t", i, len_aplist); + paplist = (struct nlattr *)((UINT_8 *) paplist + len_aplist); + } + + DBGLOG(REQ, TRACE, + "flush=%d, lost_ap_sample_size=%d, Hotlist:ap[0].channel=%d low=%d high=%d, ap[1].channel=%d low=%d high=%d", + flush, prWifiHotlistCmd->lost_ap_sample_size, + prWifiHotlistCmd->ap[0].channel, prWifiHotlistCmd->ap[0].low, prWifiHotlistCmd->ap[0].high, + prWifiHotlistCmd->ap[1].channel, prWifiHotlistCmd->ap[1].low, prWifiHotlistCmd->ap[1].high); + + memcpy(&(rCmdPscnAddHotlist.aucMacAddr), &(prWifiHotlistCmd->ap[0].bssid), 6 * sizeof(UINT_8)); + rCmdPscnAddHotlist.ucFlags = (UINT_8) TRUE; + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + kalMemFree(attr, VIR_MEM_TYPE, sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return 0; + +nla_put_failure: + if (prWifiHotlistCmd) + kalMemFree(prWifiHotlistCmd, VIR_MEM_TYPE, sizeof(PARAM_WIFI_BSSID_HOTLIST)); + if (attr) + kalMemFree(attr, VIR_MEM_TYPE, + sizeof(struct nlattr *) * (GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + 1)); + return i4Status; +} + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS rWifiScanActionCmd; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gGScanEn = 0; + + static UINT_8 k; /* only for test */ + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", + __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_ENABLE_FEATURE) + gGScanEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gGScanEn=%d, \r\n", gGScanEn); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + if (gGScanEn == TRUE) + rWifiScanActionCmd.ucPscanAct = ENABLE; + else + rWifiScanActionCmd.ucPscanAct = DISABLE; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetGSCNAction, + &rWifiScanActionCmd, + sizeof(PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + /* mtk_cfg80211_vendor_get_scan_results(wiphy, wdev, data, data_len ); */ + + return 0; + + /* only for test */ + if (k % 3 == 1) { + mtk_cfg80211_vendor_event_significant_change_results(wiphy, wdev, NULL, 0); + mtk_cfg80211_vendor_event_hotlist_ap_found(wiphy, wdev, NULL, 0); + mtk_cfg80211_vendor_event_hotlist_ap_lost(wiphy, wdev, NULL, 0); + } + k++; + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_8 gFullScanResultsEn = 0; + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, INFO, "%s for vendor command: data_len=%d, data=0x%x 0x%x\r\n", + __func__, data_len, *((UINT_32 *) data), *((UINT_32 *) data + 1)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ENABLE_FULL_SCAN_RESULTS) + gFullScanResultsEn = nla_get_u32(attr); + DBGLOG(REQ, INFO, "gFullScanResultsEn=%d, \r\n", gFullScanResultsEn); + + return 0; + + /* only for test */ + mtk_cfg80211_vendor_event_complete_scan(wiphy, wdev, WIFI_SCAN_COMPLETE); + mtk_cfg80211_vendor_event_scan_results_available(wiphy, wdev, 4); + if (gFullScanResultsEn == TRUE) + mtk_cfg80211_vendor_event_full_scan_results(wiphy, wdev, NULL, 0); + + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + /*WLAN_STATUS rStatus;*/ + UINT_32 u4BufLen; + P_GLUE_INFO_T prGlueInfo = NULL; + PARAM_WIFI_GSCAN_GET_RESULT_PARAMS rGSscnResultParm; + + INT_32 i4Status = -EINVAL; + struct nlattr *attr; + UINT_32 get_num = 0, real_num = 0; + UINT_8 flush = 0; + /*PARAM_WIFI_GSCAN_RESULT result[4], *pResult; + struct sk_buff *skb;*/ + int i; /*int j;*/ + /*UINT_32 scan_id;*/ + + ASSERT(wiphy); + ASSERT(wdev); + if ((data == NULL) || !data_len) + goto nla_put_failure; + DBGLOG(REQ, TRACE, "%s for vendor command: data_len=%d \r\n", __func__, data_len); + for (i = 0; i < 2; i++) + DBGLOG(REQ, LOUD, "0x%x 0x%x 0x%x 0x%x \r\n", *((UINT_32 *) data + i * 4), + *((UINT_32 *) data + i * 4 + 1), *((UINT_32 *) data + i * 4 + 2), + *((UINT_32 *) data + i * 4 + 3)); + + attr = (struct nlattr *)data; + if (attr->nla_type == GSCAN_ATTRIBUTE_NUM_OF_RESULTS) { + get_num = nla_get_u32(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + if (attr->nla_type == GSCAN_ATTRIBUTE_FLUSH_RESULTS) { + flush = nla_get_u8(attr); + attr = (struct nlattr *)((UINT_8 *) attr + attr->nla_len); + } + DBGLOG(REQ, TRACE, "number=%d, flush=%d \r\n", get_num, flush); + + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + ASSERT(prGlueInfo); + + real_num = (get_num < PSCAN_MAX_SCAN_CACHE_SIZE) ? get_num : PSCAN_MAX_SCAN_CACHE_SIZE; + get_num = real_num; + +#if 0 /* driver buffer FW results and reports by buffer workaround for FW mismatch with hal results numbers */ + g_GetResultsCmdCnt++; + DBGLOG(REQ, INFO, + "(g_GetResultsCmdCnt [%d], g_GetResultsBufferedCnt [%d]\n", g_GetResultsCmdCnt, + g_GetResultsBufferedCnt); + + BOOLEAN fgIsGetResultFromBuffer = FALSE; + UINT_8 BufferedResultReportIndex = 0; + + if (g_GetResultsBufferedCnt > 0) { + + DBGLOG(REQ, INFO, + "(g_GetResultsBufferedCnt > 0), report buffered results instead of ask from FW\n"); + + /* reply the results to wifi_hal */ + for (i = 0; i < MAX_BUFFERED_GSCN_RESULTS; i++) { + + if (g_arGscanResultsIndicateNumber[i] > 0) { + real_num = g_arGscanResultsIndicateNumber[i]; + get_num = real_num; + g_arGscanResultsIndicateNumber[i] = 0; + fgIsGetResultFromBuffer = TRUE; + BufferedResultReportIndex = i; + break; + } + } + if (i == MAX_BUFFERED_GSCN_RESULTS) + DBGLOG(REQ, TRACE, "all buffered results are invalid, unexpected case \r\n"); + DBGLOG(REQ, TRACE, "BufferedResultReportIndex[%d] i = %d real_num[%d] get_num[%d] \r\n", + BufferedResultReportIndex, i, real_num, get_num); + } +#endif + + rGSscnResultParm.get_num = get_num; + rGSscnResultParm.flush = flush; +#if 0/* //driver buffer FW results and reports by buffer workaround for FW results mismatch with hal results number */ + if (fgIsGetResultFromBuffer) { + nicRxProcessGSCNEvent(prGlueInfo->prAdapter, g_arGscnResultsTempBuffer[BufferedResultReportIndex]); + g_GetResultsBufferedCnt--; + g_GetResultsCmdCnt--; + nicRxReturnRFB(prGlueInfo->prAdapter, g_arGscnResultsTempBuffer[BufferedResultReportIndex]); + } else +#endif + { + kalIoctl(prGlueInfo, + wlanoidGetGSCNResult, + &rGSscnResultParm, + sizeof(PARAM_WIFI_GSCAN_GET_RESULT_PARAMS), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + return 0; + +nla_put_failure: + return i4Status; +} + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, + struct wireless_dev *wdev, const void *data, int data_len) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4Status = -EINVAL; + PARAM_WIFI_RTT_CAPABILITIES rRttCapabilities; + struct sk_buff *skb; + + DBGLOG(REQ, TRACE, "%s for vendor command \r\n", __func__); + + ASSERT(wiphy); + ASSERT(wdev); + prGlueInfo = (P_GLUE_INFO_T) wiphy_priv(wiphy); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, sizeof(rRttCapabilities)); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + kalMemZero(&rRttCapabilities, sizeof(rRttCapabilities)); + + /*rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rRttCapabilities, + sizeof(rRttCapabilities), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); */ + rRttCapabilities.rtt_one_sided_supported = 0; + rRttCapabilities.rtt_ftm_supported = 0; + rRttCapabilities.lci_support = 0; + rRttCapabilities.lcr_support = 0; + rRttCapabilities.preamble_support = 0; + rRttCapabilities.bw_support = 0; + + if (unlikely(nla_put(skb, RTT_ATTRIBUTE_CAPABILITIES, + sizeof(rRttCapabilities), &rRttCapabilities) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + return i4Status; + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len) +{ + INT_32 i4Status = -EINVAL; + WIFI_RADIO_STAT *pRadioStat; + struct sk_buff *skb; + UINT_32 u4BufLen; + + ASSERT(wiphy); + ASSERT(wdev); + + u4BufLen = sizeof(WIFI_RADIO_STAT) + sizeof(WIFI_IFACE_STAT); + pRadioStat = kalMemAlloc(u4BufLen, VIR_MEM_TYPE); + if (!pRadioStat) { + DBGLOG(REQ, ERROR, "%s kalMemAlloc pRadioStat failed\n", __func__); + return -ENOMEM; + } + kalMemZero(pRadioStat, u4BufLen); + + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, u4BufLen); + if (!skb) { + DBGLOG(REQ, TRACE, "%s allocate skb failed:%x\n", __func__, i4Status); + return -ENOMEM; + } + + /*rStatus = kalIoctl(prGlueInfo, + wlanoidQueryStatistics, + &rRadioStat, + sizeof(rRadioStat), + TRUE, + TRUE, + TRUE, + FALSE, + &u4BufLen); */ + /* only for test */ + pRadioStat->radio = 10; + pRadioStat->on_time = 11; + pRadioStat->tx_time = 12; + pRadioStat->num_channels = 4; + + /*NLA_PUT(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat);*/ + if (unlikely(nla_put(skb, LSTATS_ATTRIBUTE_STATS, u4BufLen, pRadioStat) < 0)) + goto nla_put_failure; + + i4Status = cfg80211_vendor_cmd_reply(skb); + kalMemFree(pRadioStat, VIR_MEM_TYPE, u4BufLen); + return -1; /* not support LLS now*/ + /* return i4Status; */ + +nla_put_failure: + kfree_skb(skb); + return i4Status; +} + +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* WIFI_SCAN_EVENT complete_scan; */ + + DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(complete), GSCAN_EVENT_COMPLETE_SCAN, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* complete_scan = WIFI_SCAN_COMPLETE; */ + /*NLA_PUT_U32(skb, GSCAN_EVENT_COMPLETE_SCAN, complete);*/ + { + unsigned int __tmp = complete; + + if (unlikely(nla_put(skb, GSCAN_EVENT_COMPLETE_SCAN, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num) +{ + struct sk_buff *skb; + + ASSERT(wiphy); + ASSERT(wdev); + /* UINT_32 scan_result; */ + + DBGLOG(REQ, INFO, "%s for vendor command %d \r\n", __func__, num); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(num), GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + /* scan_result = 2; */ + /*NLA_PUT_U32(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, num);*/ + { + unsigned int __tmp = num; + + if (unlikely(nla_put(skb, GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + sizeof(unsigned int), &__tmp) < 0)) + goto nla_put_failure; + } + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(result), GSCAN_EVENT_FULL_SCAN_RESULTS, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + kalMemZero(&result, sizeof(result)); + kalMemCopy(result.ssid, "Gscan_full_test", sizeof("Gscan_full_test")); + result.channel = 2437; + + /* kalMemCopy(&result, pdata, sizeof(PARAM_WIFI_GSCAN_RESULT); */ + /*NLA_PUT(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, sizeof(result), &result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_FULL_SCAN_RESULTS, + sizeof(result), &result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_CHANGE_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_CHANGE_RESULT), + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "213123", sizeof(mac_addr)); + presult->channel = 2437; + presult->rssi[0] = -45; + presult->rssi[1] = -46; + presult++; + presult->channel = 2439; + presult->rssi[0] = -47; + presult->rssi[1] = -48; + /*NLA_PUT(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + (sizeof(PARAM_WIFI_CHANGE_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "123123", sizeof(mac_addr)); + presult->channel = 2441; + presult->rssi = -45; + presult++; + presult->channel = 2443; + presult->rssi = -47; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len) +{ + struct sk_buff *skb; + PARAM_WIFI_GSCAN_RESULT result[2], *presult; + + ASSERT(wiphy); + ASSERT(wdev); + DBGLOG(REQ, INFO, "%s for vendor command \r\n", __func__); + + skb = cfg80211_vendor_event_alloc(wiphy, wdev, sizeof(PARAM_WIFI_GSCAN_RESULT), + GSCAN_EVENT_HOTLIST_RESULTS_LOST, GFP_KERNEL); + if (!skb) { + DBGLOG(REQ, ERROR, "%s allocate skb failed\n", __func__); + return -ENOMEM; + } + + presult = result; + kalMemZero(presult, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2)); + /* only for test */ + kalMemCopy(presult->bssid, "321321", sizeof(mac_addr)); + presult->channel = 2445; + presult->rssi = -46; + presult++; + presult->channel = 2447; + presult->rssi = -48; + /*NLA_PUT(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result);*/ + if (unlikely(nla_put(skb, GSCAN_EVENT_HOTLIST_RESULTS_LOST, + (sizeof(PARAM_WIFI_GSCAN_RESULT) * 2), result) < 0)) + goto nla_put_failure; + + cfg80211_vendor_event(skb, GFP_KERNEL); + return 0; + +nla_put_failure: + kfree_skb(skb); + return -1; +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c new file mode 100644 index 0000000000000..1793742e98022 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext.c @@ -0,0 +1,4158 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext.c#3 +*/ + +/*! \file gl_wext.c + \brief ioctl() (mostly Linux Wireless Extensions) routines for STA driver. +*/ + +/* +** Log: gl_wext.c + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 23 2011 tsaiyuan.hsu + * [WCXRP00000979] [MT6620 Wi-Fi][DRV]] stop attempting to connect to config AP after D3 state + * avoid entering D3 state after deep sleep. + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 27 2011 wh.su + * [WCXRP00000877] [MT6620 Wi-Fi][Driver] Remove the netif_carry_ok check for avoid the wpa_supplicant fail to query + * the ap address + * Remove the netif check while query bssid and ssid + * + * 07 26 2011 chinglan.wang + * NULL + * [MT6620][WiFi Driver] Do not include the WSC IE in the association info packet when not do the wps connection.. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 05 17 2011 eddie.chen + * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning + * Initialize the vairlabes. + * + * 05 11 2011 jeffrey.chang + * [WCXRP00000718] [MT6620 Wi-Fi] modify the behavior of setting tx power + * modify set_tx_pow ioctl + * + * 03 29 2011 terry.wu + * [WCXRP00000610] [MT 6620 Wi-Fi][Driver] Fix klocwork waring + * [MT6620 Wi-Fi][Driver] Fix klocwork warning. Add Null pointer check on wext_get_essid. Limit the upper bound of + * essid storage array. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 02 21 2011 wh.su + * [WCXRP00000483] [MT6620 Wi-Fi][Driver] Check the kalIoctl return value before doing the memory copy at linux get + * essid + * fixed the potential error to do a larget memory copy while wlanoid get essid not actually running. + * + * 02 08 2011 george.huang + * [WCXRP00000422] [MT6620 Wi-Fi][Driver] support query power mode OID handler + * Support querying power mode OID. + * + * 01 29 2011 wh.su + * [WCXRP00000408] [MT6620 Wi-Fi][Driver] Not doing memory alloc while ioctl set ie with length 0 + * not doing mem alloc. while set ie length already 0 + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Remove debug text. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Adjust OID order. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish + * successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. . + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous types + * to ease slab system pressure + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Support set PS profile and set WMM-PS related iwpriv. + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Allow change PS profile function (through wext_set_power()). + * + * 12 14 2010 jeffrey.chang + * [WCXRP00000262] [MT6620 Wi-Fi][Driver] modify the scan request ioctl to handle hidden SSID + * handle hidden SSID + * + * 12 13 2010 chinglan.wang + * NULL + * Add WPS 1.0 feature flag to enable the WPS 1.0 function. + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * Fix compiling error + * + * 12 07 2010 cm.chang + * [WCXRP00000238] MT6620 Wi-Fi][Driver][FW] Support regulation domain setting from NVRAM and supplicant + * 1. Country code is from NVRAM or supplicant + * 2. Change band definition in CMD/EVENT. + * + * 11 30 2010 cp.wu + * [WCXRP00000213] [MT6620 Wi-Fi][Driver] Implement scanning with specified SSID for wpa_supplicant with ap_scan=1 + * . + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000121] [MT6620 Wi-Fi][Driver] Temporarily disable set power mode ioctl which may cause 6620 to enter power + * saving + * Temporarily disable set power mode ioctl which may cause MT6620 to enter power saving + * + * 10 18 2010 jeffrey.chang + * [WCXRP00000116] [MT6620 Wi-Fi][Driver] Refine the set_scan ioctl to resolve the Android UI hanging issue + * refine the scan ioctl to prevent hanging of Android UI + * + * 10 01 2010 wh.su + * [WCXRP00000067] [MT6620 Wi-Fi][Driver] Support the android+ WAPI function + * add the scan result with wapi ie. + * + * 09 30 2010 wh.su + * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue + * fixed the wapi ie assigned issue. + * + * 09 27 2010 wh.su + * NULL + * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 09 2010 cp.wu + * NULL + * add WPS/WPA/RSN IE for Wi-Fi Direct scanning result. + * + * 09 06 2010 cp.wu + * NULL + * Androi/Linux: return current operating channel information + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 02 2010 jeffrey.chang + * NULL + * enable remove key ioctl + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) enable encyption ioctls + * 2) temporarily disable remove keys ioctl to prevent TX1 busy + * + * 07 28 2010 jeffrey.chang + * NULL + * 1) remove unused spinlocks + * 2) enable encyption ioctls + * 3) fix scan ioctl which may cause supplicant to hang + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * for linux driver migration + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove unused macro and debug messages + * + * 05 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add dissassoication support for wpa supplicant + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Add ioctl of power management + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug message + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) prGlueInfo->pvInformationBuffer and prGlueInfo->u4InformationBufferLength are no longer used + * * 2) fix ioctl + * + * 04 12 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug messages for pre-release + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * are done in adapter layer. + * + * 04 02 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl type + * + * 04 01 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * enable pmksa cache operation + * + * 03 31 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix ioctl which may cause cmdinfo memory leak + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\38 2009-10-08 10:33:22 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). +** Add more checking for input parameters and pointers. +** \main\maintrunk.MT5921\37 2009-09-29 16:49:48 GMT mtk01090 +** Remove unused variables +** \main\maintrunk.MT5921\36 2009-09-28 20:19:11 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\35 2009-09-03 11:42:30 GMT mtk01088 +** adding the wapi ioctl support +** \main\maintrunk.MT5921\34 2009-08-18 22:56:50 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\33 2009-05-14 22:43:47 GMT mtk01089 +** fix compiling warning +** \main\maintrunk.MT5921\32 2009-05-07 22:26:18 GMT mtk01089 +** Add mandatory and private IO control for Linux BWCS +** \main\maintrunk.MT5921\31 2009-02-07 15:11:14 GMT mtk01088 +** fixed the compiling error +** \main\maintrunk.MT5921\30 2009-02-07 14:46:51 GMT mtk01088 +** add the privacy setting from linux supplicant ap selection +** \main\maintrunk.MT5921\29 2008-11-19 15:18:50 GMT mtk01088 +** fixed the compling error +** \main\maintrunk.MT5921\28 2008-11-19 11:56:18 GMT mtk01088 +** rename some variable with pre-fix to avoid the misunderstanding +** \main\maintrunk.MT5921\27 2008-08-29 16:59:43 GMT mtk01088 +** fixed compiling error +** \main\maintrunk.MT5921\26 2008-08-29 14:55:53 GMT mtk01088 +** adjust the code for meet the coding style, and add assert check +** \main\maintrunk.MT5921\25 2008-06-02 11:15:19 GMT mtk01461 +** Update after wlanoidSetPowerMode changed +** \main\maintrunk.MT5921\24 2008-05-30 15:13:12 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\23 2008-03-28 10:40:28 GMT mtk01461 +** Add set desired rate in Linux STD IOCTL +** \main\maintrunk.MT5921\22 2008-03-18 10:31:24 GMT mtk01088 +** add pmkid ioctl and indicate +** \main\maintrunk.MT5921\21 2008-03-11 15:21:24 GMT mtk01461 +** \main\maintrunk.MT5921\20 2008-03-11 14:50:55 GMT mtk01461 +** Refine WPS related priv ioctl for unified interface +** +** \main\maintrunk.MT5921\19 2008-03-06 16:30:41 GMT mtk01088 +** move the configuration code from set essid function, +** remove the non-used code +** \main\maintrunk.MT5921\18 2008-02-21 15:47:09 GMT mtk01461 +** Fix CR[489] +** \main\maintrunk.MT5921\17 2008-02-12 23:38:31 GMT mtk01461 +** Add Set Frequency & Channel oid support for Linux +** \main\maintrunk.MT5921\16 2008-01-24 12:07:34 GMT mtk01461 +** \main\maintrunk.MT5921\15 2008-01-24 12:00:10 GMT mtk01461 +** Modify the wext_essid for set up correct information for IBSS, and fix the wrong input ptr for prAdapter +** \main\maintrunk.MT5921\14 2007-12-06 09:30:12 GMT mtk01425 +** 1. Branch Test +** \main\maintrunk.MT5921\13 2007-12-04 18:07:59 GMT mtk01461 +** fix typo +** \main\maintrunk.MT5921\12 2007-11-30 17:10:21 GMT mtk01425 +** 1. Fix compiling erros +** +** \main\maintrunk.MT5921\11 2007-11-27 10:43:22 GMT mtk01425 +** 1. Add WMM-PS setting +** \main\maintrunk.MT5921\10 2007-11-06 20:33:32 GMT mtk01088 +** fixed the compiler error +** \main\maintrunk.MT5921\9 2007-11-06 19:33:15 GMT mtk01088 +** add WPS code +** \main\maintrunk.MT5921\8 2007-10-30 12:00:44 GMT MTK01425 +** 1. Update wlanQueryInformation +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#include "gl_os.h" + +#include "config.h" +#include "wlan_oid.h" + +#include "gl_wext.h" +#include "gl_wext_priv.h" + +#include "precomp.h" + +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif + +/* compatibility to wireless extensions */ +#ifdef WIRELESS_EXT + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +const long channel_freq[] = { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 +}; + + +#define NUM_CHANNELS (sizeof(channel_freq) / sizeof(channel_freq[0])) + +#define MAX_SSID_LEN 32 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +/* NOTE: name in iwpriv_args only have 16 bytes */ +static const struct iw_priv_args rIwPrivTable[] = { + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, ""}, + {IOCTL_SET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, ""}, + + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + {IOCTL_GET_INT, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, ""}, + + {IOCTL_SET_INTS, IW_PRIV_TYPE_INT | 4, 0, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_INT | 50, ""}, + {IOCTL_GET_INT, 0, IW_PRIV_TYPE_CHAR | 16, ""}, + + {IOCTL_SET_STRING, IW_PRIV_TYPE_CHAR | 256, 0, ""}, + + /* added for set_oid and get_oid */ + {IOCTL_SET_STRUCT, 256, 0, ""}, + {IOCTL_GET_STRUCT, 0, 256, ""}, + + /* sub-ioctl definitions */ +#if 0 + {PRIV_CMD_REG_DOMAIN, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_reg_domain"}, + {PRIV_CMD_REG_DOMAIN, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_reg_domain"}, +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + {PRIV_CMD_CSUM_OFFLOAD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_tcp_csum"}, +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + {PRIV_CMD_POWER_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power_mode"}, + {PRIV_CMD_POWER_MODE, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_power_mode"}, + + {PRIV_CMD_WMM_PS, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "set_wmm_ps"}, + + {PRIV_CMD_TEST_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_test_mode"}, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_test_cmd"}, + {PRIV_CMD_TEST_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_test_result"}, +#if CFG_SUPPORT_PRIV_MCR_RW + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_mcr"}, + {PRIV_CMD_ACCESS_MCR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_mcr"}, +#endif + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_sw_ctrl"}, + {PRIV_CMD_SW_CTRL, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_sw_ctrl"}, + +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_bwcs"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CUSTOM_BWCS_CMD, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_bwcs"}, +#endif + + /* SET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 256, 0, "set_oid"}, + /* GET STRUCT sub-ioctls commands */ + {PRIV_CMD_OID, 0, 256, "get_oid"}, + + {PRIV_CMD_BAND_CONFIG, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_band"}, + {PRIV_CMD_BAND_CONFIG, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "get_band"}, + + {PRIV_CMD_SET_TX_POWER, IW_PRIV_TYPE_INT | 4, 0, "set_txpower"}, + {PRIV_CMD_GET_CH_LIST, 0, IW_PRIV_TYPE_INT | 50, "get_ch_list"}, + {PRIV_CMD_DUMP_MEM, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, + "get_mem"}, + +#if CFG_ENABLE_WIFI_DIRECT + {PRIV_CMD_P2P_MODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_p2p_mode"}, +#endif + {PRIV_CMD_GET_BUILD_DATE_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_date_code"}, + {PRIV_CMD_GET_DEBUG_CODE, 0, IW_PRIV_TYPE_CHAR | 16, "get_dbg_code"}, + /* handle any command with many input parameters */ + {PRIV_CMD_OTHER, IW_PRIV_TYPE_CHAR | 256, 0, "set_str_cmd"}, + + {PRIV_CMD_WFD_DEBUG_CODE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_wfd_dbg_code"}, +}; + +static const iw_handler rIwPrivHandler[] = { + [IOCTL_SET_INT - SIOCIWFIRSTPRIV] = priv_set_int, + [IOCTL_GET_INT - SIOCIWFIRSTPRIV] = priv_get_int, + [IOCTL_SET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_ADDRESS - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_STR - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_GET_KEY - SIOCIWFIRSTPRIV] = NULL, + [IOCTL_SET_STRUCT - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_GET_STRUCT - SIOCIWFIRSTPRIV] = priv_get_struct, + [IOCTL_SET_STRUCT_FOR_EM - SIOCIWFIRSTPRIV] = priv_set_struct, + [IOCTL_SET_INTS - SIOCIWFIRSTPRIV] = priv_set_ints, + [IOCTL_GET_INTS - SIOCIWFIRSTPRIV] = priv_get_ints, + [IOCTL_SET_STRING - SIOCIWFIRSTPRIV] = priv_set_string, +}; + +const struct iw_handler_def wext_handler_def = { + .num_standard = 0, + .num_private = (__u16) sizeof(rIwPrivHandler) / sizeof(iw_handler), + .num_private_args = (__u16) sizeof(rIwPrivTable) / sizeof(struct iw_priv_args), + .standard = (iw_handler *) NULL, + .private = rIwPrivHandler, + .private_args = rIwPrivTable, + .get_wireless_stats = wext_get_wireless_stats, +}; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPA/RSN Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPA IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x01", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPA IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPAIE */ + +#if CFG_SUPPORT_WAPI +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WAPI Information Element . +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_WAPI && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredWAPIIE */ +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredHS20IE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucCurIE[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucCurIE[2], "\x50\x6f\x9a\x10", 4) == 0) + return TRUE; + } + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredInterworkingIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + switch (pucCurIE[1]) { + case IW_IE_LENGTH_ANO: + case IW_IE_LENGTH_ANO_HESSID: + case IW_IE_LENGTH_ANO_VENUE: + case IW_IE_LENGTH_ANO_VENUE_HESSID: + return TRUE; + + default: + break; + } + + } + /* check desired EID */ + return FALSE; +} /* wextIsDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredAdvProtocolIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Check if exist the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextIsDesiredRoamingConsortiumIE(IN PUINT_8 pucCurIE, IN INT_32 i4TotalIeLen) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucCurIE); + + i4InfoElemLen = (INT_32) pucCurIE[1] + 2; + + if (pucCurIE[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) + return TRUE; + /* check desired EID */ + return FALSE; +} /* wextIsDesiredRoamingConsortiumIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired HS2.0 Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_VENDOR && i4InfoElemLen <= i4TotalIeLen) { + if (pucIEStart[1] >= ELEM_MIN_LEN_HS20_INDICATION) { + if (memcmp(&pucIEStart[2], "\x50\x6f\x9a\x10", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredHS20IE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired interworking Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_INTERWORKING && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredInterworkingIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Adv Protocol Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ADVERTISEMENT_PROTOCOL && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredAdvProtocolIE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired Roaming Consortium Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ELEM_ID_ROAMING_CONSORTIUM && i4InfoElemLen <= i4TotalIeLen) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* wextSrchDesiredRoamingConsortiumIE */ +#endif + +#if CFG_SUPPORT_WPS +/*----------------------------------------------------------------------------*/ +/*! +* \brief Find the desired WPS Information Element according to desiredElemID. +* +* \param[in] pucIEStart IE starting address. +* \param[in] i4TotalIeLen Total length of all the IE. +* \param[in] ucDesiredElemId Desired element ID. +* \param[out] ppucDesiredIE Pointer to the desired IE. +* +* \retval TRUE Find the desired IE. +* \retval FALSE Desired IE not found. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE) +{ + INT_32 i4InfoElemLen; + + ASSERT(pucIEStart); + ASSERT(ppucDesiredIE); + + while (i4TotalIeLen >= 2) { + i4InfoElemLen = (INT_32) pucIEStart[1] + 2; + + if (pucIEStart[0] == ucDesiredElemId && i4InfoElemLen <= i4TotalIeLen) { + if (ucDesiredElemId != 0xDD) { + /* Non 0xDD, OK! */ + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + /* EID == 0xDD, check WPS IE */ + if (pucIEStart[1] >= 4) { + if (memcmp(&pucIEStart[2], "\x00\x50\xf2\x04", 4) == 0) { + *ppucDesiredIE = &pucIEStart[0]; + return TRUE; + } + } /* check WPS IE length */ + /* check EID == 0xDD */ + } + + /* check desired EID */ + /* Select next information element. */ + i4TotalIeLen -= i4InfoElemLen; + pucIEStart += i4InfoElemLen; + } + + return FALSE; +} /* parseSearchDesiredWPSIE */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Get the name of the protocol used on the air. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] pcName Buffer to store protocol name string +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note If netif_carrier_ok, protocol name is returned; +* otherwise, "disconnected" is returned. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_name(IN struct net_device *prNetDev, IN struct iw_request_info *prIwrInfo, OUT char *pcName, IN char *pcExtra) +{ + ENUM_PARAM_NETWORK_TYPE_T eNetWorkType = PARAM_NETWORK_TYPE_NUM; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcName); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcName)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (netif_carrier_ok(prNetDev)) { + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryNetworkTypeInUse, + &eNetWorkType, sizeof(eNetWorkType), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + switch (eNetWorkType) { + case PARAM_NETWORK_TYPE_DS: + strcpy(pcName, "IEEE 802.11b"); + break; + case PARAM_NETWORK_TYPE_OFDM24: + strcpy(pcName, "IEEE 802.11bgn"); + break; + case PARAM_NETWORK_TYPE_AUTOMODE: + case PARAM_NETWORK_TYPE_OFDM5: + strcpy(pcName, "IEEE 802.11abgn"); + break; + case PARAM_NETWORK_TYPE_FH: + default: + strcpy(pcName, "IEEE 802.11"); + break; + } + } else { + strcpy(pcName, "Disconnected"); + } + + return 0; +} /* wext_get_name */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set the operating channel in the wireless device. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL +* \param[in] prFreq Buffer to store frequency information +* \param[in] pcExtra NULL +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If infrastructure mode is not NET NET_TYPE_IBSS. +* \retval -EINVAL Invalid channel frequency. +* +* \note If infrastructure mode is IBSS, new channel frequency is set to device. +* The range of channel number depends on different regulatory domain. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_freq(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_freq *prIwFreq, IN char *pcExtra) +{ + +#if 0 + UINT_32 u4ChnlFreq; /* Store channel or frequency information */ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + printk("set m:%d, e:%d, i:%d, flags:%d\n", + prIwFreq->m, prIwFreq->e, prIwFreq->i, prIwFreq->flags); + */ + + /* If setting by frequency, convert to a channel */ + if ((prIwFreq->e == 1) && (prIwFreq->m >= (int)2.412e8) && (prIwFreq->m <= (int)2.484e8)) { + + /* Change to KHz format */ + u4ChnlFreq = (UINT_32) (prIwFreq->m / (KILO / 10)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetFrequency, + &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (WLAN_STATUS_SUCCESS != rStatus) + return -EINVAL; + } + /* Setting by channel number */ + else if ((prIwFreq->m > KILO) || (prIwFreq->e > 0)) + return -EOPNOTSUPP; + + /* Change to channel number format */ + u4ChnlFreq = (UINT_32) prIwFreq->m; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChannel, &u4ChnlFreq, sizeof(u4ChnlFreq), FALSE, FALSE, FALSE, &u4BufLen); + + if (WLAN_STATUS_SUCCESS != rStatus) + return -EINVAL; + +#endif + + return 0; + +} /* wext_set_freq */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the operating channel in the wireless device. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prFreq Buffer to store frequency information. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise +* +* \note If netif_carrier_ok, channel frequency information is stored in pFreq. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_freq(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_freq *prIwFreq, IN char *pcExtra) +{ + UINT_32 u4Channel = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prIwFreq); + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwFreq)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* GeorgeKuo: TODO skip checking in IBSS mode */ + if (!netif_carrier_ok(prNetDev)) + return -ENOTCONN; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryFrequency, &u4Channel, sizeof(u4Channel), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + prIwFreq->m = (int)u4Channel; /* freq in KHz */ + prIwFreq->e = 3; + + return 0; + +} /* wext_get_freq */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set operating mode. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] pu4Mode Pointer to new operation mode. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If new mode is not supported. +* +* \note Device will run in new operation mode if it is valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_mode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN unsigned int *pu4Mode, IN char *pcExtra) +{ + ENUM_PARAM_OP_MODE_T eOpMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + switch (*pu4Mode) { + case IW_MODE_AUTO: + eOpMode = NET_TYPE_AUTO_SWITCH; + break; + + case IW_MODE_ADHOC: + eOpMode = NET_TYPE_IBSS; + break; + + case IW_MODE_INFRA: + eOpMode = NET_TYPE_INFRA; + break; + + default: + DBGLOG(REQ, ERROR, "%s(): Set UNSUPPORTED Mode = %d.\n", __func__, *pu4Mode); + return -EOPNOTSUPP; + } + + /* printk("%s(): Set Mode = %d\n", __FUNCTION__, *pu4Mode); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetInfrastructureMode, + &eOpMode, sizeof(eOpMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + /* after set operation mode, key table are cleared */ + + /* reset wpa info */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + return 0; +} /* wext_set_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get operating mode. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo NULL. +* \param[out] pu4Mode Buffer to store operating mode information. +* \param[in] pcExtra NULL. +* +* \retval 0 If data is valid. +* \retval -EINVAL Otherwise. +* +* \note If netif_carrier_ok, operating mode information is stored in pu4Mode. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_mode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, OUT unsigned int *pu4Mode, IN char *pcExtra) +{ + ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_NUM; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pu4Mode); + if (FALSE == GLUE_CHK_PR2(prNetDev, pu4Mode)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryInfrastructureMode, + &eOpMode, sizeof(eOpMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + switch (eOpMode) { + case NET_TYPE_IBSS: + *pu4Mode = IW_MODE_ADHOC; + break; + + case NET_TYPE_INFRA: + *pu4Mode = IW_MODE_INFRA; + break; + + case NET_TYPE_AUTO_SWITCH: + *pu4Mode = IW_MODE_AUTO; + break; + + default: + DBGLOG(REQ, ERROR, "%s(): Get UNKNOWN Mode.\n", __func__); + return -EINVAL; + } + + return 0; +} /* wext_get_mode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get the valid range for each configurable STA setting value. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer to iw_point structure, not used. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 If data is valid. +* +* \note The extra buffer (pcExtra) is filled with information from driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_range(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, OUT char *pcExtra) +{ + struct iw_range *prRange = NULL; + PARAM_RATES_EX aucSuppRate = { 0 }; /* data buffers */ + int i = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prRange = (struct iw_range *)pcExtra; + + memset(prRange, 0, sizeof(*prRange)); + prRange->throughput = 20000000; /* 20Mbps */ + prRange->min_nwid = 0; /* not used */ + prRange->max_nwid = 0; /* not used */ + + /* scan_capa not implemented */ + + /* event_capa[6]: kernel + driver capabilities */ + prRange->event_capa[0] = (IW_EVENT_CAPA_K_0 | IW_EVENT_CAPA_MASK(SIOCGIWAP) + | IW_EVENT_CAPA_MASK(SIOCGIWSCAN) + /* can't display meaningful string in iwlist + | IW_EVENT_CAPA_MASK(SIOCGIWTXPOW) + | IW_EVENT_CAPA_MASK(IWEVMICHAELMICFAILURE) + | IW_EVENT_CAPA_MASK(IWEVASSOCREQIE) + | IW_EVENT_CAPA_MASK(IWEVPMKIDCAND) + */ + ); + prRange->event_capa[1] = IW_EVENT_CAPA_K_1; + + /* report 2.4G channel and frequency only */ + prRange->num_channels = (__u16) NUM_CHANNELS; + prRange->num_frequency = (__u8) NUM_CHANNELS; + for (i = 0; i < NUM_CHANNELS; i++) { + /* iwlib takes this number as channel number */ + prRange->freq[i].i = i + 1; + prRange->freq[i].m = channel_freq[i]; + prRange->freq[i].e = 6; /* Values in table in MHz */ + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySupportedRates, + &aucSuppRate, sizeof(aucSuppRate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + for (i = 0; i < IW_MAX_BITRATES && i < PARAM_MAX_LEN_RATES_EX; i++) { + if (aucSuppRate[i] == 0) + break; + prRange->bitrate[i] = (aucSuppRate[i] & 0x7F) * 500000; /* 0.5Mbps */ + } + prRange->num_bitrates = i; + + prRange->min_rts = 0; + prRange->max_rts = 2347; + prRange->min_frag = 256; + prRange->max_frag = 2346; + + prRange->min_pmp = 0; /* power management by driver */ + prRange->max_pmp = 0; /* power management by driver */ + prRange->min_pmt = 0; /* power management by driver */ + prRange->max_pmt = 0; /* power management by driver */ + prRange->pmp_flags = IW_POWER_RELATIVE; /* pm default flag */ + prRange->pmt_flags = IW_POWER_ON; /* pm timeout flag */ + prRange->pm_capa = IW_POWER_ON; /* power management by driver */ + + prRange->encoding_size[0] = 5; /* wep40 */ + prRange->encoding_size[1] = 16; /* tkip */ + prRange->encoding_size[2] = 16; /* ckip */ + prRange->encoding_size[3] = 16; /* ccmp */ + prRange->encoding_size[4] = 13; /* wep104 */ + prRange->encoding_size[5] = 16; /* wep128 */ + prRange->num_encoding_sizes = 6; + prRange->max_encoding_tokens = 6; /* token? */ + +#if WIRELESS_EXT < 17 + prRange->txpower_capa = 0x0002; /* IW_TXPOW_RELATIVE */ +#else + prRange->txpower_capa = IW_TXPOW_RELATIVE; +#endif + prRange->num_txpower = 5; + prRange->txpower[0] = 0; /* minimum */ + prRange->txpower[1] = 25; /* 25% */ + prRange->txpower[2] = 50; /* 50% */ + prRange->txpower[3] = 100; /* 100% */ + + prRange->we_version_compiled = WIRELESS_EXT; + prRange->we_version_source = WIRELESS_EXT; + + prRange->retry_capa = IW_RETRY_LIMIT; + prRange->retry_flags = IW_RETRY_LIMIT; + prRange->min_retry = 7; + prRange->max_retry = 7; + prRange->r_time_flags = IW_RETRY_ON; + prRange->min_r_time = 0; + prRange->max_r_time = 0; + + /* signal strength and link quality */ + /* Just define range here, reporting value moved to wext_get_stats() */ + prRange->sensitivity = -83; /* fixed value */ + prRange->max_qual.qual = 100; /* max 100% */ + prRange->max_qual.level = (__u8) (0x100 - 0); /* max 0 dbm */ + prRange->max_qual.noise = (__u8) (0x100 - 0); /* max 0 dbm */ + + /* enc_capa */ +#if WIRELESS_EXT > 17 + prRange->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; +#endif + + /* min_pms; Minimal PM saving */ + /* max_pms; Maximal PM saving */ + /* pms_flags; How to decode max/min PM saving */ + + /* modul_capa; IW_MODUL_* bit field */ + /* bitrate_capa; Types of bitrates supported */ + + return 0; +} /* wext_get_range */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set BSSID of AP to connect. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prAddr Pointer to struct sockaddr structure containing AP's BSSID. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* +* \note Desired AP's BSSID is set to driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_ap(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN struct sockaddr *prAddr, IN char *pcExtra) +{ + return 0; +} /* wext_set_ap */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get AP MAC address. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prAddr Pointer to struct sockaddr structure storing AP's BSSID. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, AP's mac address is stored in pAddr->sa_data. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_ap(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct sockaddr *prAddr, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prAddr); + if (FALSE == GLUE_CHK_PR2(prNetDev, prAddr)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_DISCONNECTED) { + /*memset(prAddr, 0, 6);*/ + memset(prAddr, 0, sizeof(struct sockaddr)); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssid, prAddr->sa_data, ETH_ALEN, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + return 0; +} /* wext_get_ap */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set mlme operation request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData Pointer of iw_point header. +* \param[in] pcExtra Pointer to iw_mlme structure mlme request information. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP unsupported IW_MLME_ command. +* \retval -EINVAL Set MLME Fail, different bssid. +* +* \note Driver will start mlme operation if valid. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_mlme(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prData, IN char *pcExtra) +{ + struct iw_mlme *prMlme = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + prMlme = (struct iw_mlme *)pcExtra; + if (prMlme->cmd == IW_MLME_DEAUTH || prMlme->cmd == IW_MLME_DISASSOC) { + if (!netif_carrier_ok(prNetDev)) { + DBGLOG(REQ, WARN, "[wifi] Set MLME Deauth/Disassoc, but netif_carrier_off\n"); + return 0; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + return 0; + } + DBGLOG(REQ, WARN, "[wifi] unsupported IW_MLME_ command :%d\n", prMlme->cmd); + return -EOPNOTSUPP; + +} /* wext_set_mlme */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To issue scan request. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prData NULL. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EFAULT Tx power is off. +* +* \note Device will start scanning. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_scan(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN union iwreq_data *prData, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + int essid_len = 0; + + ASSERT(prNetDev); + if (FALSE == GLUE_CHK_DEV(prNetDev)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if WIRELESS_EXT > 17 + /* retrieve SSID */ + if (prData) + essid_len = ((struct iw_scan_req *)(((struct iw_point *)prData)->pointer))->essid_len; +#endif + + init_completion(&prGlueInfo->rScanComp); + + /* TODO: parse flags and issue different scan requests? */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetBssidListScan, pcExtra, essid_len, FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 2 * KAL_HZ); */ + /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ + + return 0; +} /* wext_set_scan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To write the ie to buffer +* +*/ +/*----------------------------------------------------------------------------*/ +static inline int snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + + if (buf_size == 0) + return 0; + + for (i = 0; i < len; i++) { + ret = snprintf(pos, end - pos, "%02x", data[i]); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + end[-1] = '\0'; + return pos - buf; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get scan results, transform results from driver's format to WE's. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prData Pointer to iw_point structure, pData->length is the size of +* pcExtra buffer before used, and is updated after filling scan +* results. +* \param[out] pcExtra Pointer to buffer which is allocated by caller of this +* function, wext_support_ioctl() or ioctl_standard_call() in +* wireless.c. +* +* \retval 0 For success. +* \retval -ENOMEM If dynamic memory allocation fail. +* \retval -E2BIG Invalid length. +* +* \note Scan results is filled into pcExtra buffer, data size is updated in +* pData->length. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_scan(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN OUT struct iw_point *prData, IN char *pcExtra) +{ + UINT_32 i = 0; + UINT_32 j = 0; + P_PARAM_BSSID_LIST_EX_T prList = NULL; + P_PARAM_BSSID_EX_T prBss = NULL; + P_PARAM_VARIABLE_IE_T prDesiredIE = NULL; + struct iw_event iwEvent; /* local iw_event buffer */ + + /* write pointer of extra buffer */ + char *pcCur = NULL; + /* pointer to the end of last full entry in extra buffer */ + char *pcValidEntryEnd = NULL; + char *pcEnd = NULL; /* end of extra buffer */ + + UINT_32 u4AllocBufLen = 0; + + /* arrange rate information */ + UINT_32 u4HighestRate = 0; + char aucRatesBuf[64]; + UINT_32 u4BufIndex; + + /* return value */ + int ret = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prData, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Initialize local variables */ + pcCur = pcExtra; + pcValidEntryEnd = pcExtra; + pcEnd = pcExtra + prData->length; /* end of extra buffer */ + + /* Allocate another query buffer with the same size of extra buffer */ + u4AllocBufLen = prData->length; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(REQ, ERROR, "[wifi] no memory for scan list:%d\n", prData->length); + ret = -ENOMEM; + goto error; + } + prList->u4NumberOfItems = 0; + + /* wait scan done */ + /* printk ("wait for scan results\n"); */ + /* wait_for_completion_interruptible_timeout(&prGlueInfo->rScanComp, 4 * KAL_HZ); */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + /* Buffer length is not large enough. */ + /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ + +#if WIRELESS_EXT >= 17 + /* This feature is supported in WE-17 or above, limited by iwlist. + ** Return -E2BIG and iwlist will request again with a larger buffer. + */ + ret = -E2BIG; + /* Update length to give application a hint on result length */ + prData->length = (__u16) u4BufLen; + goto error; +#else + /* Realloc a larger query buffer here, but don't write too much to extra + ** buffer when filling it later. + */ + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + u4AllocBufLen = u4BufLen; + prList = kalMemAlloc(u4AllocBufLen, VIR_MEM_TYPE); + if (prList == NULL) { + DBGLOG(REQ, ERROR, "[wifi] no memory for larger scan list :%u\n", u4BufLen); + ret = -ENOMEM; + goto error; + } + prList->NumberOfItems = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryBssidList, prList, u4AllocBufLen, TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus == WLAN_STATUS_INVALID_LENGTH) { + DBGLOG(REQ, ERROR, "[wifi] larger buf:%u result:%u\n", u4AllocBufLen, u4BufLen); + ret = -E2BIG; + prData->length = (__u16) u4BufLen; + goto error; + } +#endif /* WIRELESS_EXT >= 17 */ + + } + + if (prList->u4NumberOfItems > CFG_MAX_NUM_BSS_LIST) { + DBGLOG(REQ, WARN, "[wifi] strange scan result count:%u\n", prList->u4NumberOfItems); + goto error; + } + + /* Copy required data from pList to pcExtra */ + prBss = &prList->arBssid[0]; /* set to the first entry */ + for (i = 0; i < prList->u4NumberOfItems; ++i) { + /* BSSID */ + iwEvent.cmd = SIOCGIWAP; + iwEvent.len = IW_EV_ADDR_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.ap_addr.sa_family = ARPHRD_ETHER; + ether_addr_copy(iwEvent.u.ap_addr.sa_data, prBss->arMacAddress); + memcpy(pcCur, &iwEvent, IW_EV_ADDR_LEN); + pcCur += IW_EV_ADDR_LEN; + + /* SSID */ + iwEvent.cmd = SIOCGIWESSID; + /* Modification to user space pointer(essid.pointer) is not needed. */ + iwEvent.u.essid.length = (__u16) prBss->rSsid.u4SsidLen; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.essid.length; + + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.essid.flags = 1; + iwEvent.u.essid.pointer = NULL; + +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, iwEvent.len); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prBss->rSsid.aucSsid, iwEvent.u.essid.length); + pcCur += iwEvent.len; + /* Frequency */ + iwEvent.cmd = SIOCGIWFREQ; + iwEvent.len = IW_EV_FREQ_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.freq.m = prBss->rConfiguration.u4DSConfig; + iwEvent.u.freq.e = 3; /* (in KHz) */ + iwEvent.u.freq.i = 0; + memcpy(pcCur, &iwEvent, IW_EV_FREQ_LEN); + pcCur += IW_EV_FREQ_LEN; + + /* Operation Mode */ + iwEvent.cmd = SIOCGIWMODE; + iwEvent.len = IW_EV_UINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + if (prBss->eOpMode == NET_TYPE_IBSS) + iwEvent.u.mode = IW_MODE_ADHOC; + else if (prBss->eOpMode == NET_TYPE_INFRA) + iwEvent.u.mode = IW_MODE_INFRA; + else + iwEvent.u.mode = IW_MODE_AUTO; + memcpy(pcCur, &iwEvent, IW_EV_UINT_LEN); + pcCur += IW_EV_UINT_LEN; + + /* Quality */ + iwEvent.cmd = IWEVQUAL; + iwEvent.len = IW_EV_QUAL_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.qual.qual = 0; /* Quality not available now */ + /* -100 < Rssi < -10, normalized by adding 0x100 */ + iwEvent.u.qual.level = 0x100 + prBss->rRssi; + iwEvent.u.qual.noise = 0; /* Noise not available now */ + iwEvent.u.qual.updated = IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID; + memcpy(pcCur, &iwEvent, IW_EV_QUAL_LEN); + pcCur += IW_EV_QUAL_LEN; + + /* Security Mode */ + iwEvent.cmd = SIOCGIWENCODE; + iwEvent.len = IW_EV_POINT_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.pointer = NULL; + iwEvent.u.data.flags = 0; + iwEvent.u.data.length = 0; + if (!prBss->u4Privacy) + iwEvent.u.data.flags |= IW_ENCODE_DISABLED; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + pcCur += IW_EV_POINT_LEN; + + /* rearrange rate information */ + u4BufIndex = sprintf(aucRatesBuf, "Rates (Mb/s):"); + u4HighestRate = 0; + for (j = 0; j < PARAM_MAX_LEN_RATES_EX; ++j) { + UINT_8 curRate = prBss->rSupportedRates[j] & 0x7F; + + if (curRate == 0) + break; + + if (curRate > u4HighestRate) + u4HighestRate = curRate; + + if (curRate == RATE_5_5M) + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " 5.5"); + else + u4BufIndex += sprintf(aucRatesBuf + u4BufIndex, " %d", curRate / 2); +#if DBG + if (u4BufIndex > sizeof(aucRatesBuf)) { + /* printk("rate info too long\n"); */ + break; + } +#endif + } + /* Report Highest Rates */ + iwEvent.cmd = SIOCGIWRATE; + iwEvent.len = IW_EV_PARAM_LEN; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.bitrate.value = u4HighestRate * 500000; + iwEvent.u.bitrate.fixed = 0; + iwEvent.u.bitrate.disabled = 0; + iwEvent.u.bitrate.flags = 0; + memcpy(pcCur, &iwEvent, iwEvent.len); + pcCur += iwEvent.len; + +#if WIRELESS_EXT >= 15 /* IWEVCUSTOM is available in WE-15 or above */ + /* Report Residual Rates */ + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = u4BufIndex; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 0; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, aucRatesBuf, u4BufIndex); + pcCur += iwEvent.len; +#endif /* WIRELESS_EXT >= 15 */ + + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, (PUINT_8 *) &prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#if CFG_SUPPORT_WPS /* search WPS IE (0xDD, 221, OUI: 0x0050f204 ) */ + if (wextSrchDesiredWPSIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0xDD, (PUINT_8 *) &prDesiredIE)) { + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#endif + + /* Search RSN IE (0x30, 48). pBss->IEs starts from timestamp. */ + /* pBss->IEs starts from timestamp */ + if (wextSrchDesiredWPAIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), + 0x30, (PUINT_8 *) &prDesiredIE)) { + + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; + } +#if CFG_SUPPORT_WAPI /* Android+ */ + if (wextSrchDesiredWAPIIE(&prBss->aucIEs[sizeof(PARAM_FIXED_IEs)], + prBss->u4IELength - sizeof(PARAM_FIXED_IEs), (PUINT_8 *) &prDesiredIE)) { + +#if 0 + iwEvent.cmd = IWEVGENIE; + iwEvent.u.data.flags = 1; + iwEvent.u.data.length = 2 + (__u16) prDesiredIE->ucLength; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; +#if WIRELESS_EXT <= 18 + memcpy(pcCur, &iwEvent, IW_EV_POINT_LEN); +#else + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); +#endif + memcpy(pcCur + IW_EV_POINT_LEN, prDesiredIE, 2 + prDesiredIE->ucLength); + pcCur += iwEvent.len; +#else + iwEvent.cmd = IWEVCUSTOM; + iwEvent.u.data.length = (2 + prDesiredIE->ucLength) * 2 + 8 /* wapi_ie= */; + iwEvent.len = IW_EV_POINT_LEN + iwEvent.u.data.length; + if ((pcCur + iwEvent.len) > pcEnd) + break; + iwEvent.u.data.flags = 1; + + memcpy(pcCur, &iwEvent, IW_EV_LCP_LEN); + memcpy(pcCur + IW_EV_LCP_LEN, + &iwEvent.u.data.length, sizeof(struct iw_point) - IW_EV_POINT_OFF); + + pcCur += (IW_EV_POINT_LEN); + + pcCur += sprintf(pcCur, "wapi_ie="); + + snprintf_hex(pcCur, pcEnd - pcCur, (UINT_8 *) prDesiredIE, prDesiredIE->ucLength + 2); + + pcCur += (2 + prDesiredIE->ucLength) * 2 /* iwEvent.len */; +#endif + } +#endif + /* Complete an entry. Update end of valid entry */ + pcValidEntryEnd = pcCur; + /* Extract next bss */ + prBss = (P_PARAM_BSSID_EX_T) ((char *)prBss + prBss->u4Length); + } + + /* Update valid data length for caller function and upper layer + * applications. + */ + prData->length = (pcValidEntryEnd - pcExtra); + /* printk(KERN_INFO "[wifi] buf:%d result:%ld\n", pData->length, u4BufLen); */ + + /* kalIndicateStatusAndComplete(prGlueInfo, WLAN_STATUS_SCAN_COMPLETE, NULL, 0); */ + +error: + /* free local query buffer */ + if (prList) + kalMemFree(prList, VIR_MEM_TYPE, u4AllocBufLen); + + return ret; +} /* wext_get_scan */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set desired network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer of iw_point header. +* \param[in] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -E2BIG Essid string length is too big. +* \retval -EINVAL pcExtra is null pointer. +* \retval -EFAULT Driver fail to set new essid. +* +* \note If string length is ok, device will try connecting to the new network. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, IN char *pcExtra) +{ + PARAM_SSID_T rNewSsid; + UINT_32 cipher; + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prEssid->length > IW_ESSID_MAX_SIZE) + return -E2BIG; + + /* set auth mode */ + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_DISABLED) { + eAuthMode = (prGlueInfo->rWpaInfo.u4AuthAlg == IW_AUTH_ALG_OPEN_SYSTEM) ? + AUTH_MODE_OPEN : AUTH_MODE_AUTO_SWITCH; + /* printk(KERN_INFO "IW_AUTH_WPA_VERSION_DISABLED->Param_AuthMode%s\n", */ + /* (eAuthMode == AUTH_MODE_OPEN) ? "Open" : "Shared"); */ + } else { + /* set auth mode */ + switch (prGlueInfo->rWpaInfo.u4KeyMgmt) { + case IW_AUTH_KEY_MGMT_802_1X: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA : AUTH_MODE_WPA2; + /* printk("IW_AUTH_KEY_MGMT_802_1X->AUTH_MODE_WPA%s\n", */ + /* (eAuthMode == AUTH_MODE_WPA) ? "" : "2"); */ + break; + case IW_AUTH_KEY_MGMT_PSK: + eAuthMode = + (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA) ? + AUTH_MODE_WPA_PSK : AUTH_MODE_WPA2_PSK; + /* printk("IW_AUTH_KEY_MGMT_PSK->AUTH_MODE_WPA%sPSK\n", */ + /* (eAuthMode == AUTH_MODE_WPA_PSK) ? "" : "2"); */ + break; +#if CFG_SUPPORT_WAPI /* Android+ */ + case IW_AUTH_KEY_MGMT_WAPI_PSK: + break; + case IW_AUTH_KEY_MGMT_WAPI_CERT: + break; +#endif + +/* #if defined (IW_AUTH_KEY_MGMT_WPA_NONE) */ +/* case IW_AUTH_KEY_MGMT_WPA_NONE: */ +/* eAuthMode = AUTH_MODE_WPA_NONE; */ +/* //printk("IW_AUTH_KEY_MGMT_WPA_NONE->AUTH_MODE_WPA_NONE\n"); */ +/* break; */ +/* #endif */ +#if CFG_SUPPORT_802_11W + case IW_AUTH_KEY_MGMT_802_1X_SHA256: + eAuthMode = AUTH_MODE_WPA2; + break; + case IW_AUTH_KEY_MGMT_PSK_SHA256: + eAuthMode = AUTH_MODE_WPA2_PSK; + break; +#endif + default: + /* printk(KERN_INFO DRV_NAME"strange IW_AUTH_KEY_MGMT : %ld set auto switch\n", */ + /* prGlueInfo->rWpaInfo.u4KeyMgmt); */ + eAuthMode = AUTH_MODE_AUTO_SWITCH; + break; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + /* set encryption status */ + cipher = prGlueInfo->rWpaInfo.u4CipherGroup | prGlueInfo->rWpaInfo.u4CipherPairwise; + if (cipher & IW_AUTH_CIPHER_CCMP) { + /* printk("IW_AUTH_CIPHER_CCMP->ENUM_ENCRYPTION3_ENABLED\n"); */ + eEncStatus = ENUM_ENCRYPTION3_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_TKIP) { + /* printk("IW_AUTH_CIPHER_TKIP->ENUM_ENCRYPTION2_ENABLED\n"); */ + eEncStatus = ENUM_ENCRYPTION2_ENABLED; + } else if (cipher & (IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40)) { + /* printk("IW_AUTH_CIPHER_WEPx->ENUM_ENCRYPTION1_ENABLED\n"); */ + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + } else if (cipher & IW_AUTH_CIPHER_NONE) { + /* printk("IW_AUTH_CIPHER_NONE->ENUM_ENCRYPTION_DISABLED\n"); */ + if (prGlueInfo->rWpaInfo.fgPrivacyInvoke) + eEncStatus = ENUM_ENCRYPTION1_ENABLED; + else + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } else { + /* printk("unknown IW_AUTH_CIPHER->Param_EncryptionDisabled\n"); */ + eEncStatus = ENUM_ENCRYPTION_DISABLED; + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + +#if WIRELESS_EXT < 21 + /* GeorgeKuo: a length error bug exists in (WE < 21) cases, kernel before + ** 2.6.19. Cut the trailing '\0'. + */ + rNewSsid.u4SsidLen = (prEssid->length) ? prEssid->length - 1 : 0; +#else + rNewSsid.u4SsidLen = prEssid->length; +#endif + kalMemCopy(rNewSsid.aucSsid, pcExtra, rNewSsid.u4SsidLen); + + /* + rNewSsid.aucSsid[rNewSsid.u4SsidLen] = '\0'; + printk("set ssid(%lu): %s\n", rNewSsid.u4SsidLen, rNewSsid.aucSsid); + */ + + if (kalIoctl(prGlueInfo, + wlanoidSetSsid, + (PVOID)&rNewSsid, + sizeof(PARAM_SSID_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen) != WLAN_STATUS_SUCCESS) { + /* printk(KERN_WARNING "Fail to set ssid\n"); */ + return -EFAULT; + } + + return 0; +} /* wext_set_essid */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current network name ESSID. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEssid Pointer to iw_point structure containing essid information. +* \param[out] pcExtra Pointer to buffer srtoring essid string. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, network essid is stored in pcExtra. +*/ +/*----------------------------------------------------------------------------*/ +/* static PARAM_SSID_T ssid; */ +static int +wext_get_essid(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEssid, OUT char *pcExtra) +{ + /* PARAM_SSID_T ssid; */ + + P_PARAM_SSID_T prSsid; + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEssid); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prEssid, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* if (!netif_carrier_ok(prNetDev)) { */ + /* return -ENOTCONN; */ + /* } */ + + prSsid = kalMemAlloc(sizeof(PARAM_SSID_T), VIR_MEM_TYPE); + + if (!prSsid) + return -ENOMEM; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQuerySsid, prSsid, sizeof(PARAM_SSID_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if ((rStatus == WLAN_STATUS_SUCCESS) && (prSsid->u4SsidLen <= MAX_SSID_LEN)) { + kalMemCopy(pcExtra, prSsid->aucSsid, prSsid->u4SsidLen); + prEssid->length = prSsid->u4SsidLen; + prEssid->flags = 1; + } + + kalMemFree(prSsid, VIR_MEM_TYPE, sizeof(PARAM_SSID_T)); + + return 0; +} /* wext_get_essid */ + +#if 0 + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set tx desired bit rate. Three cases here +* iwconfig wlan0 auto -> Set to origianl supported rate set. +* iwconfig wlan0 18M -> Imply "fixed" case, set to 18Mbps as desired rate. +* iwconfig wlan0 18M auto -> Set to auto rate lower and equal to 18Mbps +* +* \param[in] prNetDev Pointer to the net_device handler. +* \param[in] prIwReqInfo Pointer to the Request Info. +* \param[in] prRate Pointer to the Rate Parameter. +* \param[in] pcExtra Pointer to the extra buffer. +* +* \retval 0 Update desired rate. +* \retval -EINVAL Wrong parameter +*/ +/*----------------------------------------------------------------------------*/ +int +wext_set_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra) +{ + PARAM_RATES_EX aucSuppRate = { 0 }; + PARAM_RATES_EX aucNewRate = { 0 }; + UINT_32 u4NewRateLen = 0; + UINT_32 i; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* + printk("value = %d, fixed = %d, disable = %d, flags = %d\n", + prRate->value, prRate->fixed, prRate->disabled, prRate->flags); + */ + + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuerySupportedRates, &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + + /* Case: AUTO */ + if (prRate->value < 0) { + if (prRate->fixed == 0) { + /* iwconfig wlan0 rate auto */ + + /* set full supported rate to device */ + /* printk("wlanoidQuerySupportedRates():u4BufLen = %ld\n", u4BufLen); */ + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, + &aucSuppRate, sizeof(aucSuppRate), &u4BufLen); + return 0; + } + /* iwconfig wlan0 rate fixed */ + + /* fix rate to what? DO NOTHING */ + return -EINVAL; + } + + aucNewRate[0] = prRate->value / 500000; /* In unit of 500k */ + + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; i++) { + /* check the given value is supported */ + if (aucSuppRate[i] == 0) + break; + + if (aucNewRate[0] == aucSuppRate[i]) { + u4NewRateLen = 1; + break; + } + } + + if (u4NewRateLen == 0) { + /* the given value is not supported */ + /* return error or use given rate as upper bound? */ + return -EINVAL; + } + + if (prRate->fixed == 0) { + /* add all rates lower than desired rate */ + for (i = 0; i < PARAM_MAX_LEN_RATES_EX; ++i) { + if (aucSuppRate[i] == 0) + break; + + if (aucSuppRate[i] < aucNewRate[0]) + aucNewRate[u4NewRateLen++] = aucSuppRate[i]; + } + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetDesiredRates, &aucNewRate, sizeof(aucNewRate), &u4BufLen); + return 0; +} /* wext_set_rate */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get current tx bit rate. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRate Pointer to iw_param structure to store current tx rate. +* \param[in] pcExtra NULL. +* +* \retval 0 If netif_carrier_ok. +* \retval -ENOTCONN Otherwise. +* +* \note If netif_carrier_ok, current tx rate is stored in pRate. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRate, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + UINT_32 u4Rate = 0; + + ASSERT(prNetDev); + ASSERT(prRate); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRate)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!netif_carrier_ok(prNetDev)) + return -ENOTCONN; + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryLinkSpeed, &u4Rate, sizeof(u4Rate), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prRate->value = u4Rate * 100; /* u4Rate is in unit of 100bps */ + prRate->fixed = 0; + + return 0; +} /* wext_get_rate */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set RTS/CTS theshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prRts Pointer to iw_param structure containing rts threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 For success. +* \retval -EINVAL Given value is out of range. +* +* \note If given value is valid, device will follow the new setting. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_rts(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_param *prRts, IN char *pcExtra) +{ + PARAM_RTS_THRESHOLD u4RtsThresh; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prRts->disabled == 1) + u4RtsThresh = 2347; + else if (prRts->value < 0 || prRts->value > 2347) + return -EINVAL; + + u4RtsThresh = (PARAM_RTS_THRESHOLD) prRts->value; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRtsThreshold, + &u4RtsThresh, sizeof(u4RtsThresh), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + prRts->value = (typeof(prRts->value)) u4RtsThresh; + prRts->disabled = (prRts->value > 2347) ? 1 : 0; + prRts->fixed = 1; + + return 0; +} /* wext_set_rts */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get RTS/CTS theshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prRts Pointer to iw_param structure containing rts threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note RTS threshold is stored in pRts. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_rts(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prRts, IN char *pcExtra) +{ + PARAM_RTS_THRESHOLD u4RtsThresh = 0; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prRts); + if (FALSE == GLUE_CHK_PR2(prNetDev, prRts)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryRtsThreshold, + &u4RtsThresh, sizeof(u4RtsThresh), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + prRts->value = (typeof(prRts->value)) u4RtsThresh; + prRts->disabled = (prRts->value > 2347 || prRts->value < 0) ? 1 : 0; + prRts->fixed = 1; + + return 0; +} /* wext_get_rts */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get fragmentation threshold. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prFrag Pointer to iw_param structure containing frag threshold. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note RTS threshold is stored in pFrag. Fragmentation is disabled. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_frag(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prFrag, IN char *pcExtra) +{ + ASSERT(prFrag); + + prFrag->value = 2346; + prFrag->fixed = 1; + prFrag->disabled = 1; + return 0; +} /* wext_get_frag */ + +#if 1 +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set TX power, or enable/disable the radio. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prTxPow Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Tx power is stored in pTxPow. iwconfig wlan0 txpow on/off are used +* to enable/disable the radio. +*/ +/*----------------------------------------------------------------------------*/ + +static int +wext_set_txpow(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_param *prTxPow, IN char *pcExtra) +{ + int ret = 0; + /* PARAM_DEVICE_POWER_STATE ePowerState; */ + ENUM_ACPI_STATE_T ePowerState; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (prTxPow->disabled) { + /* <1> disconnect */ + rStatus = kalIoctl(prGlueInfo, wlanoidSetDisassociate, NULL, 0, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "######set disassoc failed\n"); + else + DBGLOG(REQ, TRACE, "######set assoc ok\n"); + /* <2> mark to power state flag */ + ePowerState = ACPI_STATE_D0; + DBGLOG(REQ, INFO, "set to acpi d3(0)\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + + } else { + ePowerState = ACPI_STATE_D0; + DBGLOG(REQ, INFO, "set to acpi d0\n"); + wlanSetAcpiState(prGlueInfo->prAdapter, ePowerState); + } + + prGlueInfo->ePowerState = ePowerState; + + return ret; +} /* wext_set_txpow */ + +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get TX power. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prTxPow Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Tx power is stored in pTxPow. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_txpow(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prTxPow, IN char *pcExtra) +{ + /* PARAM_DEVICE_POWER_STATE ePowerState; */ + + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prTxPow); + if (FALSE == GLUE_CHK_PR2(prNetDev, prTxPow)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* GeorgeKuo: wlanoidQueryAcpiDevicePowerState() reports capability, not + * current state. Use GLUE_INFO_T to store state. + */ + /* ePowerState = prGlueInfo->ePowerState; */ + + /* TxPow parameters: Fixed at relative 100% */ +#if WIRELESS_EXT < 17 + prTxPow->flags = 0x0002; /* IW_TXPOW_RELATIVE */ +#else + prTxPow->flags = IW_TXPOW_RELATIVE; +#endif + prTxPow->value = 100; + prTxPow->fixed = 1; + /* prTxPow->disabled = (ePowerState != ParamDeviceStateD3) ? FALSE : TRUE; */ + prTxPow->disabled = TRUE; + + return 0; +} /* wext_get_txpow */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Buffer to store key content. +* +* \retval 0 Success. +* +* \note Securiry information is stored in pEnc except key content. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_encode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_point *prEnc, IN char *pcExtra) +{ +#if 1 + /* ENUM_ENCRYPTION_STATUS_T eEncMode; */ + ENUM_PARAM_ENCRYPTION_STATUS_T eEncMode = ENUM_WEP_ENABLED; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (FALSE == GLUE_CHK_PR2(prNetDev, prEnc)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + rStatus = kalIoctl(prGlueInfo, + wlanoidQueryEncryptionStatus, + &eEncMode, sizeof(eEncMode), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + + switch (eEncMode) { + case ENUM_WEP_DISABLED: + prEnc->flags = IW_ENCODE_DISABLED; + break; + case ENUM_WEP_ENABLED: + prEnc->flags = IW_ENCODE_ENABLED; + break; + case ENUM_WEP_KEY_ABSENT: + prEnc->flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + break; + default: + prEnc->flags = IW_ENCODE_ENABLED; + break; + } + + /* Cipher, Key Content, Key ID can't be queried */ + prEnc->flags |= IW_ENCODE_NOKEY; +#endif + return 0; +} /* wext_get_encode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +static UINT_8 wepBuf[48]; + +static int +wext_set_encode(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra) +{ +#if 1 + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + /* UINT_8 wepBuf[48]; */ + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* reset to default mode */ + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4KeyMgmt = 0; + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_NONE; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; +#if CFG_SUPPORT_802_11W + prGlueInfo->rWpaInfo.u4Mfp = IW_AUTH_MFP_DISABLED; +#endif + + /* iwconfig wlan0 key off */ + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + eAuthMode = AUTH_MODE_OPEN; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + eEncStatus = ENUM_ENCRYPTION_DISABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, sizeof(eEncStatus), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + return 0; + } + + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prEnc->length == 5 || prEnc->length == 13 || prEnc->length == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prEnc->length; + prWepKey->u4KeyLength = prEnc->length; + kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prEnc->length); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSetAuthMode fail 0x%lx\n", rStatus); */ + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSetEncryptionStatus fail 0x%lx\n", rStatus); */ + return -EFAULT; + } + + return 0; + } +#endif + return -EOPNOTSUPP; +} /* wext_set_encode */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note New Power Management Mode is set to driver. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_power(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_param *prPower, IN char *pcExtra) +{ +#if 1 + + PARAM_POWER_MODE ePowerMode; + INT_32 i4PowerValue; + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* printk(KERN_INFO "wext_set_power value(%d) disabled(%d) flag(0x%x)\n", */ + /* prPower->value, prPower->disabled, prPower->flags); */ + + if (prPower->disabled) { + ePowerMode = Param_PowerModeCAM; + } else { + i4PowerValue = prPower->value; +#if WIRELESS_EXT < 21 + i4PowerValue /= 1000000; +#endif + if (i4PowerValue == 0) { + ePowerMode = Param_PowerModeCAM; + } else if (i4PowerValue == 1) { + ePowerMode = Param_PowerModeMAX_PSP; + } else if (i4PowerValue == 2) { + ePowerMode = Param_PowerModeFast_PSP; + } else { + DBGLOG(REQ, ERROR, "%s(): unsupported power management mode value = %d.\n", + __func__, prPower->value); + + return -EINVAL; + } + } + + rStatus = kalIoctl(prGlueInfo, + wlanoidSet802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO DRV_NAME"wlanoidSet802dot11PowerSaveProfile fail 0x%lx\n", rStatus); */ + return -EFAULT; + } +#endif + return 0; +} /* wext_set_power */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To get power management. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[out] prPower Pointer to iw_param structure containing tx power setting. +* \param[in] pcExtra NULL. +* +* \retval 0 Success. +* +* \note Power management mode is stored in pTxPow->value. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_get_power(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, OUT struct iw_param *prPower, IN char *pcExtra) +{ + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + PARAM_POWER_MODE ePowerMode = Param_PowerModeCAM; + + ASSERT(prNetDev); + ASSERT(prPower); + if (FALSE == GLUE_CHK_PR2(prNetDev, prPower)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + +#if 0 +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), TRUE, TRUE, &u4BufLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), &u4BufLen); +#endif +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + &ePowerMode, sizeof(ePowerMode), &u4BufLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) + return -EFAULT; + + prPower->value = 0; + prPower->disabled = 1; + + if (Param_PowerModeCAM == ePowerMode) { + prPower->value = 0; + prPower->disabled = 1; + } else if (Param_PowerModeMAX_PSP == ePowerMode) { + prPower->value = 1; + prPower->disabled = 0; + } else if (Param_PowerModeFast_PSP == ePowerMode) { + prPower->value = 2; + prPower->disabled = 0; + } + + prPower->flags = IW_POWER_PERIOD | IW_POWER_RELATIVE; +#if WIRELESS_EXT < 21 + prPower->value *= 1000000; +#endif + + /* printk(KERN_INFO "wext_get_power value(%d) disabled(%d) flag(0x%x)\n", */ + /* prPower->value, prPower->disabled, prPower->flags); */ + + return 0; +} /* wext_get_power */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set authentication parameters. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] rpAuth Pointer to iw_param structure containing authentication information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +static int +wext_set_auth(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_param *prAuth, IN char *pcExtra) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prAuth); + if (FALSE == GLUE_CHK_PR2(prNetDev, prAuth)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + /* Save information to glue info and process later when ssid is set. */ + switch (prAuth->flags & IW_AUTH_INDEX) { + case IW_AUTH_WPA_VERSION: +#if CFG_SUPPORT_WAPI + if (wlanQueryWapiMode(prGlueInfo->prAdapter)) { + prGlueInfo->rWpaInfo.u4WpaVersion = IW_AUTH_WPA_VERSION_DISABLED; + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_OPEN_SYSTEM; + } else { + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; + } +#else + prGlueInfo->rWpaInfo.u4WpaVersion = prAuth->value; +#endif + break; + + case IW_AUTH_CIPHER_PAIRWISE: + prGlueInfo->rWpaInfo.u4CipherPairwise = prAuth->value; + break; + + case IW_AUTH_CIPHER_GROUP: + prGlueInfo->rWpaInfo.u4CipherGroup = prAuth->value; + break; + + case IW_AUTH_KEY_MGMT: + prGlueInfo->rWpaInfo.u4KeyMgmt = prAuth->value; +#if CFG_SUPPORT_WAPI + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_PSK || + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WAPI_CERT) { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); + } +#endif + if (prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_WPS) + prGlueInfo->fgWpsActive = TRUE; + else + prGlueInfo->fgWpsActive = FALSE; + break; + + case IW_AUTH_80211_AUTH_ALG: + prGlueInfo->rWpaInfo.u4AuthAlg = prAuth->value; + break; + + case IW_AUTH_PRIVACY_INVOKED: + prGlueInfo->rWpaInfo.fgPrivacyInvoke = prAuth->value; + break; +#if CFG_SUPPORT_802_11W + case IW_AUTH_MFP: + /* printk("wext_set_auth IW_AUTH_MFP=%d\n", prAuth->value); */ + prGlueInfo->rWpaInfo.u4Mfp = prAuth->value; + break; +#endif +#if CFG_SUPPORT_WAPI + case IW_AUTH_WAPI_ENABLED: + { + UINT_32 u4BufLen; + WLAN_STATUS rStatus; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiMode, + &prAuth->value, sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + DBGLOG(REQ, INFO, "IW_AUTH_WAPI_ENABLED :%d\n", prAuth->value); + break; +#endif + default: + /* + printk(KERN_INFO "[wifi] unsupported IW_AUTH_INDEX :%d\n", prAuth->flags); + */ + break; + } + return 0; +} /* wext_set_auth */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To set encryption cipher and key. +* +* \param[in] prDev Net device requested. +* \param[in] prIwrInfo NULL. +* \param[in] prEnc Pointer to iw_point structure containing securiry information. +* \param[in] pcExtra Pointer to key string buffer. +* +* \retval 0 Success. +* \retval -EINVAL Key ID error for WEP. +* \retval -EFAULT Setting parameters to driver fail. +* \retval -EOPNOTSUPP Key size not supported. +* +* \note Securiry information is stored in pEnc. +*/ +/*----------------------------------------------------------------------------*/ +#if CFG_SUPPORT_WAPI +UINT_8 keyStructBuf[320]; /* add/remove key shared buffer */ +#else +UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +static int +wext_set_encode_ext(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwrInfo, IN struct iw_point *prEnc, IN char *pcExtra) +{ + P_PARAM_REMOVE_KEY_T prRemoveKey = (P_PARAM_REMOVE_KEY_T) keyStructBuf; + P_PARAM_KEY_T prKey = (P_PARAM_KEY_T) keyStructBuf; + + P_PARAM_WEP_T prWepKey = (P_PARAM_WEP_T) wepBuf; + + struct iw_encode_ext *prIWEncExt = (struct iw_encode_ext *)pcExtra; + + ENUM_PARAM_ENCRYPTION_STATUS_T eEncStatus; + ENUM_PARAM_AUTH_MODE_T eAuthMode; + /* ENUM_PARAM_OP_MODE_T eOpMode = NET_TYPE_AUTO_SWITCH; */ + +#if CFG_SUPPORT_WAPI + P_PARAM_WPI_KEY_T prWpiKey = (P_PARAM_WPI_KEY_T) keyStructBuf; +#endif + + P_GLUE_INFO_T prGlueInfo = NULL; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + ASSERT(prEnc); + if (FALSE == GLUE_CHK_PR3(prNetDev, prEnc, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + memset(keyStructBuf, 0, sizeof(keyStructBuf)); + +#if CFG_SUPPORT_WAPI + if (prIWEncExt->alg == IW_ENCODE_ALG_SMS4) { + if (prEnc->flags & IW_ENCODE_DISABLED) { + /* printk(KERN_INFO "[wapi] IW_ENCODE_DISABLED\n"); */ + return 0; + } + /* KeyID */ + prWpiKey->ucKeyID = (prEnc->flags & IW_ENCODE_INDEX); + prWpiKey->ucKeyID--; + if (prWpiKey->ucKeyID > 1) { + /* key id is out of range */ + /* printk(KERN_INFO "[wapi] add key error: key_id invalid %d\n", prWpiKey->ucKeyID); */ + return -EINVAL; + } + + if (prIWEncExt->key_len != 32) { + /* key length not valid */ + /* printk(KERN_INFO "[wapi] add key error: key_len invalid %d\n", prIWEncExt->key_len); */ + return -EINVAL; + } + /* printk(KERN_INFO "[wapi] %d ext_flags %d\n", prEnc->flags, prIWEncExt->ext_flags); */ + + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + prWpiKey->eKeyType = ENUM_WPI_GROUP_KEY; + prWpiKey->eDirection = ENUM_WPI_RX; + } else if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prWpiKey->eKeyType = ENUM_WPI_PAIRWISE_KEY; + prWpiKey->eDirection = ENUM_WPI_RX_TX; + } + + /* PN */ + { + UINT_32 i; + + for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) + prWpiKey->aucPN[i] = prIWEncExt->tx_seq[i]; + for (i = 0; i < IW_ENCODE_SEQ_MAX_SIZE; i++) + prWpiKey->aucPN[IW_ENCODE_SEQ_MAX_SIZE + i] = prIWEncExt->rx_seq[i]; + } + + /* BSSID */ + memcpy(prWpiKey->aucAddrIndex, prIWEncExt->addr.sa_data, 6); + + memcpy(prWpiKey->aucWPIEK, prIWEncExt->key, 16); + prWpiKey->u4LenWPIEK = 16; + + memcpy(prWpiKey->aucWPICK, &prIWEncExt->key[16], 16); + prWpiKey->u4LenWPICK = 16; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiKey, + prWpiKey, sizeof(PARAM_WPI_KEY_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* Do nothing */ + /* printk(KERN_INFO "[wapi] add key error:%lx\n", rStatus); */ + } + } else +#endif + { + + if ((prEnc->flags & IW_ENCODE_MODE) == IW_ENCODE_DISABLED) { + prRemoveKey->u4Length = sizeof(*prRemoveKey); + memcpy(prRemoveKey->arBSSID, prIWEncExt->addr.sa_data, 6); + /* + printk("IW_ENCODE_DISABLED: ID:%d, Addr:[ %pM ]\n", + prRemoveKey->KeyIndex, prRemoveKey->BSSID); + */ + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetRemoveKey, + prRemoveKey, prRemoveKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, INFO, "remove key error:%x\n", rStatus); + return 0; + } + /* return 0; */ + /* printk ("alg %x\n", prIWEncExt->alg); */ + + switch (prIWEncExt->alg) { + case IW_ENCODE_ALG_NONE: + break; + case IW_ENCODE_ALG_WEP: + /* iwconfig wlan0 key 0123456789 */ + /* iwconfig wlan0 key s:abcde */ + /* iwconfig wlan0 key 0123456789 [1] */ + /* iwconfig wlan0 key 01234567890123456789012345 [1] */ + /* check key size for WEP */ + if (prIWEncExt->key_len == 5 || prIWEncExt->key_len == 13 || prIWEncExt->key_len == 16) { + /* prepare PARAM_WEP key structure */ + prWepKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; + if (prWepKey->u4KeyIndex > 3) { + /* key id is out of range */ + return -EINVAL; + } + prWepKey->u4KeyIndex |= 0x80000000; + prWepKey->u4Length = 12 + prIWEncExt->key_len; + prWepKey->u4KeyLength = prIWEncExt->key_len; + /* kalMemCopy(prWepKey->aucKeyMaterial, pcExtra, prIWEncExt->key_len); */ + kalMemCopy(prWepKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddWep, + prWepKey, prWepKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAddWep fail 0x%x\n", rStatus); + return -EFAULT; + } + + /* change to auto switch */ + prGlueInfo->rWpaInfo.u4AuthAlg = IW_AUTH_ALG_SHARED_KEY | IW_AUTH_ALG_OPEN_SYSTEM; + eAuthMode = AUTH_MODE_AUTO_SWITCH; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAuthMode, + &eAuthMode, + sizeof(eAuthMode), FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetAuthMode fail 0x%x\n", rStatus); + return -EFAULT; + } + + prGlueInfo->rWpaInfo.u4CipherPairwise = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + prGlueInfo->rWpaInfo.u4CipherGroup = IW_AUTH_CIPHER_WEP104 | IW_AUTH_CIPHER_WEP40; + + eEncStatus = ENUM_WEP_ENABLED; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetEncryptionStatus, + &eEncStatus, + sizeof(ENUM_PARAM_ENCRYPTION_STATUS_T), + FALSE, FALSE, FALSE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "wlanoidSetEncryptionStatus fail 0x%x\n", rStatus); + return -EFAULT; + } + + } else { + DBGLOG(REQ, INFO, "key length %x\n", prIWEncExt->key_len); + DBGLOG(REQ, INFO, "key error\n"); + } + + break; + case IW_ENCODE_ALG_TKIP: + case IW_ENCODE_ALG_CCMP: +#if CFG_SUPPORT_802_11W + case IW_ENCODE_ALG_AES_CMAC: +#endif + { + + /* KeyID */ + prKey->u4KeyIndex = (prEnc->flags & IW_ENCODE_INDEX) ? + (prEnc->flags & IW_ENCODE_INDEX) - 1 : 0; +#if CFG_SUPPORT_802_11W + if (prKey->u4KeyIndex > 5) { +#else + if (prKey->u4KeyIndex > 3) { +#endif + DBGLOG(REQ, ERROR, "key index error:0x%x\n", prKey->u4KeyIndex); + /* key id is out of range */ + return -EINVAL; + } + + /* bit(31) and bit(30) are shared by pKey and pRemoveKey */ + /* Tx Key Bit(31) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { + prKey->u4KeyIndex |= 0x1UL << 31; + /* Code style */ + } + /* Pairwise Key Bit(30) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { + /* Do nothing */ + /* group key */ + } else { + /* pairwise key */ + prKey->u4KeyIndex |= 0x1UL << 30; + } + } + /* Rx SC Bit(29) */ + if (prIWEncExt->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { + prKey->u4KeyIndex |= 0x1UL << 29; + memcpy(&prKey->rKeyRSC, prIWEncExt->rx_seq, IW_ENCODE_SEQ_MAX_SIZE); + } + + /* BSSID */ + memcpy(prKey->arBSSID, prIWEncExt->addr.sa_data, 6); + + /* switch tx/rx MIC key for sta */ + if (prIWEncExt->alg == IW_ENCODE_ALG_TKIP && prIWEncExt->key_len == 32) { + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, 16); + memcpy(((PUINT_8) prKey->aucKeyMaterial) + 16, prIWEncExt->key + 24, 8); + memcpy((prKey->aucKeyMaterial) + 24, prIWEncExt->key + 16, 8); + } else { + memcpy(prKey->aucKeyMaterial, prIWEncExt->key, prIWEncExt->key_len); + } + + prKey->u4KeyLength = prIWEncExt->key_len; + prKey->u4Length = ((ULONG)&(((P_PARAM_KEY_T) 0)->aucKeyMaterial)) + prKey->u4KeyLength; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetAddKey, + prKey, prKey->u4Length, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "add key error:%x\n", rStatus); + return -EFAULT; + } + break; + } + } + + return 0; +} /* wext_set_encode_ext */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Set country code +* +* \param[in] prNetDev Net device requested. +* \param[in] prData iwreq.u.data carries country code value. +* +* \retval 0 For success. +* \retval -EEFAULT For fail. +* +* \note Country code is stored and channel list is updated based on current country domain. +*/ +/*----------------------------------------------------------------------------*/ +static int wext_set_country(IN struct net_device *prNetDev, IN struct iw_point *prData) +{ + P_GLUE_INFO_T prGlueInfo; + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + UINT_8 aucCountry[2]; + + ASSERT(prNetDev); + + /* prData->pointer should be like "COUNTRY US", "COUNTRY EU" + * and "COUNTRY JP" + */ + if (FALSE == GLUE_CHK_PR2(prNetDev, prData) || !prData->pointer || prData->length < 10) + return -EINVAL; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + aucCountry[0] = *((PUINT_8)prData->pointer + 8); + aucCountry[1] = *((PUINT_8)prData->pointer + 9); + + rStatus = kalIoctl(prGlueInfo, wlanoidSetCountryCode, &aucCountry[0], 2, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, ERROR, "Set country code error: %x\n", rStatus); + return -EFAULT; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To report the iw private args table to user space. +* +* \param[in] prNetDev Net device requested. +* \param[out] prData iwreq.u.data to carry the private args table. +* +* \retval 0 For success. +* \retval -E2BIG For user's buffer size is too small. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +static int wext_get_priv(IN struct net_device *prNetDev, OUT struct iw_point *prData) +{ + UINT_16 u2BufferSize = prData->length; + + /* Update our private args table size */ + prData->length = (__u16)sizeof(rIwPrivTable); + if (u2BufferSize < prData->length) + return -E2BIG; + + if (prData->length) { + if (copy_to_user(prData->pointer, rIwPrivTable, sizeof(rIwPrivTable))) + return -EFAULT; + } + + return 0; +} /* wext_get_priv */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief ioctl() (Linux Wireless Extensions) routines +* +* \param[in] prDev Net device requested. +* \param[in] ifr The ifreq structure for seeting the wireless extension. +* \param[in] i4Cmd The wireless extension ioctl command. +* +* \retval zero On success. +* \retval -EOPNOTSUPP If the cmd is not supported. +* \retval -EFAULT If copy_to_user goes wrong. +* \retval -EINVAL If any value's out of range. +* +* \note +*/ +/*----------------------------------------------------------------------------*/ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd) +{ + struct iwreq *iwr = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + int ret = 0; + char *prExtraBuf = NULL; + UINT_32 u4ExtraSize = 0; + P_GLUE_INFO_T prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + WLAN_STATUS rStatus; + UINT_32 u4BufLen; + P_PARAM_PMKID_T prPmkid; + + /* printk("%d CMD:0x%x\n", jiffies_to_msecs(jiffies), i4Cmd); */ + + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case SIOCGIWNAME: /* 0x8B01, get wireless protocol name */ + ret = wext_get_name(prDev, &rIwReqInfo, (char *)&iwr->u.name, NULL); + break; + + /* case SIOCSIWNWID: 0x8B02, deprecated */ + /* case SIOCGIWNWID: 0x8B03, deprecated */ + + case SIOCSIWFREQ: /* 0x8B04, set channel */ + ret = wext_set_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCGIWFREQ: /* 0x8B05, get channel */ + ret = wext_get_freq(prDev, NULL, &iwr->u.freq, NULL); + break; + + case SIOCSIWMODE: /* 0x8B06, set operation mode */ + ret = wext_set_mode(prDev, NULL, &iwr->u.mode, NULL); + /* ret = 0; */ + break; + + case SIOCGIWMODE: /* 0x8B07, get operation mode */ + ret = wext_get_mode(prDev, NULL, &iwr->u.mode, NULL); + break; + + /* case SIOCSIWSENS: 0x8B08, unsupported */ + /* case SIOCGIWSENS: 0x8B09, unsupported */ + + /* case SIOCSIWRANGE: 0x8B0A, unused */ + case SIOCGIWRANGE: /* 0x8B0B, get range of parameters */ + if (iwr->u.data.pointer != NULL) { + /* Buffer size should be large enough */ + if (iwr->u.data.length < sizeof(struct iw_range)) { + ret = -E2BIG; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_range), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* reset all fields */ + memset(prExtraBuf, 0, sizeof(struct iw_range)); + iwr->u.data.length = sizeof(struct iw_range); + + ret = wext_get_range(prDev, NULL, &iwr->u.data, prExtraBuf); + /* Push up to the caller */ + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_range)); + prExtraBuf = NULL; + } else { + ret = -EINVAL; + } + break; + + case SIOCSIWPRIV: /* 0x8B0C, set country code */ + ret = wext_set_country(prDev, &iwr->u.data); + break; + + case SIOCGIWPRIV: /* 0x8B0D, get private args table */ + ret = wext_get_priv(prDev, &iwr->u.data); + break; + + /* case SIOCSIWSTATS: 0x8B0E, unused */ + /* case SIOCGIWSTATS: + get statistics, intercepted by wireless_process_ioctl() in wireless.c, + redirected to dev_iwstats(), dev->get_wireless_stats(). + */ + /* case SIOCSIWSPY: 0x8B10, unsupported */ + /* case SIOCGIWSPY: 0x8B11, unsupported */ + /* case SIOCSIWTHRSPY: 0x8B12, unsupported */ + /* case SIOCGIWTHRSPY: 0x8B13, unsupported */ + + case SIOCSIWAP: /* 0x8B14, set access point MAC addresses (BSSID) */ + if (iwr->u.ap_addr.sa_data[0] == 0 && + iwr->u.ap_addr.sa_data[1] == 0 && + iwr->u.ap_addr.sa_data[2] == 0 && + iwr->u.ap_addr.sa_data[3] == 0 && + iwr->u.ap_addr.sa_data[4] == 0 && iwr->u.ap_addr.sa_data[5] == 0) { + /* WPA Supplicant will set 000000000000 in + ** wpa_driver_wext_deinit(), do nothing here or disassoc again? + */ + ret = 0; + break; + } + ret = wext_set_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + + break; + + case SIOCGIWAP: /* 0x8B15, get access point MAC addresses (BSSID) */ + ret = wext_get_ap(prDev, NULL, &iwr->u.ap_addr, NULL); + break; + + case SIOCSIWMLME: /* 0x8B16, request MLME operation */ + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_mlme)) { + DBGLOG(REQ, ERROR, "MLME buffer strange:%d\n", iwr->u.data.length); + ret = -EINVAL; + break; + } + + if (!iwr->u.data.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(sizeof(struct iw_mlme), VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_mlme))) + ret = -EFAULT; + else + ret = wext_set_mlme(prDev, NULL, &(iwr->u.data), prExtraBuf); + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, sizeof(struct iw_mlme)); + prExtraBuf = NULL; + break; + + /* case SIOCGIWAPLIST: 0x8B17, deprecated */ + case SIOCSIWSCAN: /* 0x8B18, scan request */ + if (iwr->u.data.pointer == NULL) + ret = wext_set_scan(prDev, NULL, NULL, NULL); +#if WIRELESS_EXT > 17 + else if (iwr->u.data.length == sizeof(struct iw_scan_req)) { + prExtraBuf = kalMemAlloc(MAX_SSID_LEN, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, ((struct iw_scan_req *)(iwr->u.data.pointer))->essid, + ((struct iw_scan_req *)(iwr->u.data.pointer))->essid_len)) { + ret = -EFAULT; + } else { + ret = wext_set_scan(prDev, NULL, (union iwreq_data *)&(iwr->u.data), prExtraBuf); + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, MAX_SSID_LEN); + prExtraBuf = NULL; + } +#endif + else + ret = -EINVAL; + break; +#if 1 + case SIOCGIWSCAN: /* 0x8B19, get scan results */ + if (!iwr->u.data.pointer || !iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + u4ExtraSize = iwr->u.data.length; + /* allocate the same size of kernel buffer to store scan results. */ + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* iwr->u.data.length may be updated by wext_get_scan() */ + ret = wext_get_scan(prDev, NULL, &iwr->u.data, prExtraBuf); + if (ret != 0) { + if (ret == -E2BIG) + DBGLOG(REQ, WARN, "[wifi] wext_get_scan -E2BIG\n"); + } else { + /* check updated length is valid */ + ASSERT(iwr->u.data.length <= u4ExtraSize); + if (iwr->u.data.length > u4ExtraSize) { + DBGLOG(REQ, INFO, "Updated result length is larger than allocated (%d > %u)\n", + iwr->u.data.length, u4ExtraSize); + iwr->u.data.length = u4ExtraSize; + } + + if (copy_to_user(iwr->u.data.pointer, prExtraBuf, iwr->u.data.length)) + ret = -EFAULT; + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + + break; + +#endif + +#if 1 + case SIOCSIWESSID: /* 0x8B1A, set SSID (network name) */ + if (iwr->u.essid.length > IW_ESSID_MAX_SIZE) { + ret = -E2BIG; + break; + } + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE + 4, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.essid.pointer, iwr->u.essid.length)) { + ret = -EFAULT; + } else { + /* Add trailing '\0' for printk */ + /* prExtraBuf[iwr->u.essid.length] = 0; */ + /* printk(KERN_INFO "wext_set_essid: %s (%d)\n", prExtraBuf, iwr->u.essid.length); */ + ret = wext_set_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); + /* printk ("set essid %d\n", ret); */ + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE + 4); + prExtraBuf = NULL; + break; + +#endif + + case SIOCGIWESSID: /* 0x8B1B, get SSID */ + if (!iwr->u.essid.pointer) { + ret = -EINVAL; + break; + } + + if (iwr->u.essid.length < IW_ESSID_MAX_SIZE) { + DBGLOG(REQ, ERROR, "[wifi] iwr->u.essid.length:%d too small\n", iwr->u.essid.length); + ret = -E2BIG; /* let caller try larger buffer */ + break; + } + + prExtraBuf = kalMemAlloc(IW_ESSID_MAX_SIZE, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + /* iwr->u.essid.length is updated by wext_get_essid() */ + + ret = wext_get_essid(prDev, NULL, &iwr->u.essid, prExtraBuf); + if (ret == 0) { + if (copy_to_user(iwr->u.essid.pointer, prExtraBuf, iwr->u.essid.length)) + ret = -EFAULT; + } + + kalMemFree(prExtraBuf, VIR_MEM_TYPE, IW_ESSID_MAX_SIZE); + prExtraBuf = NULL; + + break; + + /* case SIOCSIWNICKN: 0x8B1C, not supported */ + /* case SIOCGIWNICKN: 0x8B1D, not supported */ + + case SIOCSIWRATE: /* 0x8B20, set default bit rate (bps) */ + /* ret = wext_set_rate(prDev, &rIwReqInfo, &iwr->u.bitrate, NULL); */ + break; + + case SIOCGIWRATE: /* 0x8B21, get current bit rate (bps) */ + ret = wext_get_rate(prDev, NULL, &iwr->u.bitrate, NULL); + break; + + case SIOCSIWRTS: /* 0x8B22, set rts/cts threshold */ + ret = wext_set_rts(prDev, NULL, &iwr->u.rts, NULL); + break; + + case SIOCGIWRTS: /* 0x8B23, get rts/cts threshold */ + ret = wext_get_rts(prDev, NULL, &iwr->u.rts, NULL); + break; + + /* case SIOCSIWFRAG: 0x8B24, unsupported */ + case SIOCGIWFRAG: /* 0x8B25, get frag threshold */ + ret = wext_get_frag(prDev, NULL, &iwr->u.frag, NULL); + break; + + case SIOCSIWTXPOW: /* 0x8B26, set relative tx power (in %) */ + ret = wext_set_txpow(prDev, NULL, &iwr->u.txpower, NULL); + break; + + case SIOCGIWTXPOW: /* 0x8B27, get relative tx power (in %) */ + ret = wext_get_txpow(prDev, NULL, &iwr->u.txpower, NULL); + break; + + /* case SIOCSIWRETRY: 0x8B28, unsupported */ + /* case SIOCGIWRETRY: 0x8B29, unsupported */ + +#if 1 + case SIOCSIWENCODE: /* 0x8B2A, set encoding token & mode */ + /* Only DISABLED case has NULL pointer and length == 0 */ + if (iwr->u.encoding.pointer) { + if (iwr->u.encoding.length > 16) { + ret = -E2BIG; + break; + } + + u4ExtraSize = iwr->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, iwr->u.encoding.length)) + ret = -EFAULT; + } else if (iwr->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = wext_set_encode(prDev, NULL, &iwr->u.encoding, prExtraBuf); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + break; + + case SIOCGIWENCODE: /* 0x8B2B, get encoding token & mode */ + /* check pointer */ + ret = wext_get_encode(prDev, NULL, &iwr->u.encoding, NULL); + break; + + case SIOCSIWPOWER: /* 0x8B2C, set power management */ + ret = wext_set_power(prDev, NULL, &iwr->u.power, NULL); + break; + + case SIOCGIWPOWER: /* 0x8B2D, get power management */ + ret = wext_get_power(prDev, NULL, &iwr->u.power, NULL); + break; + +#if WIRELESS_EXT > 17 + case SIOCSIWGENIE: /* 0x8B30, set gen ie */ + if (iwr->u.data.pointer == NULL) + break; + + if (0 /* wlanQueryWapiMode(prGlueInfo->prAdapter) */) + break; + + /* Fixed length structure */ +#if CFG_SUPPORT_WAPI + if (iwr->u.data.length > 42 /* The max wapi ie buffer */) { + ret = -EINVAL; + break; + } +#endif + u4ExtraSize = iwr->u.data.length; + if (u4ExtraSize == 0) + break; + + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, iwr->u.data.length)) { + ret = -EFAULT; + } else { +#if CFG_SUPPORT_WAPI + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWapiAssocInfo, + prExtraBuf, + u4ExtraSize, FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO "[wapi] set wapi assoc info error:%lx\n", + rStatus); */ +#endif +#if CFG_SUPPORT_WPS2 + PUINT_8 prDesiredIE = NULL; + + if (wextSrchDesiredWPSIE(prExtraBuf, + u4ExtraSize, + 0xDD, (PUINT_8 *) &prDesiredIE)) { + rStatus = kalIoctl(prGlueInfo, + wlanoidSetWSCAssocInfo, + prDesiredIE, + IE_SIZE(prDesiredIE), + FALSE, + FALSE, TRUE, FALSE, &u4BufLen); + if (rStatus != WLAN_STATUS_SUCCESS) { + /* printk(KERN_INFO "[WSC] set WSC assoc info + error:%lx\n", rStatus); */ + } + } +#endif +#if CFG_SUPPORT_WAPI + } +#endif + } + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + break; + + case SIOCGIWGENIE: /* 0x8B31, get gen ie, unused */ + break; + +#endif + + case SIOCSIWAUTH: /* 0x8B32, set auth mode params */ + ret = wext_set_auth(prDev, NULL, &iwr->u.param, NULL); + break; + + /* case SIOCGIWAUTH: 0x8B33, unused? */ + case SIOCSIWENCODEEXT: /* 0x8B34, set extended encoding token & mode */ + if (iwr->u.encoding.pointer) { + u4ExtraSize = iwr->u.encoding.length; + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.encoding.pointer, iwr->u.encoding.length)) + ret = -EFAULT; + } else if (iwr->u.encoding.length != 0) { + ret = -EINVAL; + break; + } + + if (ret == 0) + ret = wext_set_encode_ext(prDev, NULL, &iwr->u.encoding, prExtraBuf); + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + break; + + /* case SIOCGIWENCODEEXT: 0x8B35, unused? */ + + case SIOCSIWPMKSA: /* 0x8B36, pmksa cache operation */ +#if 1 + if (iwr->u.data.pointer) { + /* Fixed length structure */ + if (iwr->u.data.length != sizeof(struct iw_pmksa)) { + ret = -EINVAL; + break; + } + + u4ExtraSize = sizeof(struct iw_pmksa); + prExtraBuf = kalMemAlloc(u4ExtraSize, VIR_MEM_TYPE); + if (!prExtraBuf) { + ret = -ENOMEM; + break; + } + + if (copy_from_user(prExtraBuf, iwr->u.data.pointer, sizeof(struct iw_pmksa))) { + ret = -EFAULT; + } else { + switch (((struct iw_pmksa *)prExtraBuf)->cmd) { + case IW_PMKSA_ADD: + /* + printk(KERN_INFO "IW_PMKSA_ADD [ %pM ]\n", + (((struct iw_pmksa *)pExtraBuf)->bssid.sa_data)); + */ + prPmkid = + (P_PARAM_PMKID_T) kalMemAlloc(8 + sizeof(PARAM_BSSID_INFO_T), + VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, "Can not alloc memory for IW_PMKSA_ADD\n"); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8 + sizeof(PARAM_BSSID_INFO_T); + prPmkid->u4BSSIDInfoCount = 1; + kalMemCopy(prPmkid->arBSSIDInfo->arBSSID, + ((struct iw_pmksa *)prExtraBuf)->bssid.sa_data, 6); + kalMemCopy(prPmkid->arBSSIDInfo->arPMKID, + ((struct iw_pmksa *)prExtraBuf)->pmkid, IW_PMKID_LEN); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "add pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8 + sizeof(PARAM_BSSID_INFO_T)); + break; + case IW_PMKSA_REMOVE: + /* + printk(KERN_INFO "IW_PMKSA_REMOVE [ %pM ]\n", + (((struct iw_pmksa *)buf)->bssid.sa_data)); + */ + break; + case IW_PMKSA_FLUSH: + /* + printk(KERN_INFO "IW_PMKSA_FLUSH\n"); + */ + prPmkid = (P_PARAM_PMKID_T) kalMemAlloc(8, VIR_MEM_TYPE); + if (!prPmkid) { + DBGLOG(REQ, ERROR, + "Can not alloc memory for IW_PMKSA_FLUSH\n"); + ret = -ENOMEM; + break; + } + + prPmkid->u4Length = 8; + prPmkid->u4BSSIDInfoCount = 0; + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetPmkid, + prPmkid, + sizeof(PARAM_PMKID_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "flush pmkid error:%x\n", rStatus); + kalMemFree(prPmkid, VIR_MEM_TYPE, 8); + break; + default: + DBGLOG(REQ, WARN, "UNKNOWN iw_pmksa command:%d\n", + ((struct iw_pmksa *)prExtraBuf)->cmd); + ret = -EFAULT; + break; + } + } + + if (prExtraBuf) { + kalMemFree(prExtraBuf, VIR_MEM_TYPE, u4ExtraSize); + prExtraBuf = NULL; + } + } else if (iwr->u.data.length != 0) { + ret = -EINVAL; + break; + } +#endif + break; + +#endif + + default: + /* printk(KERN_NOTICE "unsupported IOCTL: 0x%x\n", i4Cmd); */ + ret = -EOPNOTSUPP; + break; + } + + /* printk("%ld CMD:0x%x ret:%d\n", jiffies_to_msecs(jiffies), i4Cmd, ret); */ + + return ret; +} /* wext_support_ioctl */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief To send an event (RAW socket pacekt) to user process actively. +* +* \param[in] prGlueInfo Glue layer info. +* \param[in] u4cmd Whcih event command we want to indicate to user process. +* \param[in] pData Data buffer to be indicated. +* \param[in] dataLen Available data size in pData. +* +* \return (none) +* +* \note Event is indicated to upper layer if cmd is supported and data is valid. +* Using of kernel symbol wireless_send_event(), which is defined in +* after WE-14 (2.4.20). +*/ +/*----------------------------------------------------------------------------*/ +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4dataLen) +{ + union iwreq_data wrqu; + unsigned char *pucExtraInfo = NULL; +#if WIRELESS_EXT >= 15 + unsigned char *pucDesiredIE = NULL; + unsigned char aucExtraInfoBuf[200]; +#endif +#if WIRELESS_EXT < 18 + int i; +#endif + + memset(&wrqu, 0, sizeof(wrqu)); + + switch (u4Cmd) { + case SIOCGIWTXPOW: + memcpy(&wrqu.power, pucData, u4dataLen); + break; + case SIOCGIWSCAN: + complete_all(&prGlueInfo->rScanComp); + break; + + case SIOCGIWAP: + if (pucData) + ether_addr_copy((u8 *)&(wrqu.ap_addr.sa_data), pucData); + /*memcpy(&wrqu.ap_addr.sa_data, pucData, ETH_ALEN);*/ + else + memset(&wrqu.ap_addr.sa_data, 0, ETH_ALEN); + break; + + case IWEVASSOCREQIE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + /* do supplicant a favor, parse to the start of WPA/RSN IE */ + if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0x30, &pucDesiredIE)) { + /* RSN IE found */ + /* Do nothing */ +#if 0 + } else if (wextSrchDesiredWPSIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPS IE found */ + /* Do nothing */ +#endif + } else if (wextSrchDesiredWPAIE(pucData, u4dataLen, 0xDD, &pucDesiredIE)) { + /* WPA IE found */ + /* Do nothing*/ +#if CFG_SUPPORT_WAPI /* Android+ */ + } else if (wextSrchDesiredWAPIIE(pucData, u4dataLen, &pucDesiredIE)) { + /* WAPI IE found */ + /* printk("wextSrchDesiredWAPIIE!!\n"); */ +#endif + } else { + /* no WPA/RSN IE found, skip this event */ + goto skip_indicate_event; + } +#if WIRELESS_EXT < 18 + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, "ASSOCINFO(ReqIEs="); + /* printk(KERN_DEBUG "assoc info buffer size needed:%d\n", infoElemLen * 2 + 17); */ + /* translate binary string to hex string, requirement of IWEVCUSTOM */ + for (i = 0; i < pucDesiredIE[1] + 2; ++i) + pucExtraInfo += sprintf(pucExtraInfo, "%02x", pucDesiredIE[i]); + pucExtraInfo = aucExtraInfoBuf; + wrqu.data.length = 17 + (pucDesiredIE[1] + 2) * 2; +#else + /* IWEVASSOCREQIE, indicate binary string */ + pucExtraInfo = pucDesiredIE; + wrqu.data.length = pucDesiredIE[1] + 2; +#endif +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVMICHAELMICFAILURE: +#if WIRELESS_EXT < 15 + /* under WE-15, no suitable Event can be used */ + goto skip_indicate_event; +#else + if (pucData) { + P_PARAM_AUTH_REQUEST_T pAuthReq = (P_PARAM_AUTH_REQUEST_T) pucData; + /* under WE-18, only IWEVCUSTOM can be used */ + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + pucExtraInfo += sprintf(pucExtraInfo, "MLME-MICHAELMICFAILURE.indication "); + pucExtraInfo += sprintf(pucExtraInfo, + "%s", + (pAuthReq->u4Flags == PARAM_AUTH_REQUEST_GROUP_ERROR) ? + "groupcast " : "unicast "); + + wrqu.data.length = pucExtraInfo - aucExtraInfoBuf; + pucExtraInfo = aucExtraInfoBuf; + } +#endif /* WIRELESS_EXT < 15 */ + break; + + case IWEVPMKIDCAND: + if (prGlueInfo->rWpaInfo.u4WpaVersion == IW_AUTH_WPA_VERSION_WPA2 && + prGlueInfo->rWpaInfo.u4KeyMgmt == IW_AUTH_KEY_MGMT_802_1X) { + + /* only used in WPA2 */ +#if WIRELESS_EXT >= 18 + P_PARAM_PMKID_CANDIDATE_T prPmkidCand = (P_PARAM_PMKID_CANDIDATE_T) pucData; + + struct iw_pmkid_cand rPmkidCand; + + pucExtraInfo = aucExtraInfoBuf; + + rPmkidCand.flags = prPmkidCand->u4Flags; + rPmkidCand.index = 0; + rPmkidCand.bssid.sa_family = 0; + kalMemCopy(rPmkidCand.bssid.sa_data, prPmkidCand->arBSSID, 6); + + kalMemCopy(pucExtraInfo, (PUINT_8) &rPmkidCand, sizeof(struct iw_pmkid_cand)); + wrqu.data.length = sizeof(struct iw_pmkid_cand); + + /* pmkid canadidate list is supported after WE-18 */ + /* indicate struct iw_pmkid_cand */ +#else + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, WE < 18\n"); */ + goto skip_indicate_event; +#endif + } else { + /* printk(KERN_INFO "IWEVPMKIDCAND event skipped, NOT WPA2\n"); */ + goto skip_indicate_event; + } + break; + + case IWEVCUSTOM: + u4Cmd = IWEVCUSTOM; + pucExtraInfo = aucExtraInfoBuf; + kalMemCopy(pucExtraInfo, pucData, sizeof(PTA_IPC_T)); + wrqu.data.length = sizeof(PTA_IPC_T); + break; + + default: + /* printk(KERN_INFO "Unsupported wext event:%x\n", cmd); */ + goto skip_indicate_event; + } + + /* Send event to user space */ + wireless_send_event(prGlueInfo->prDevHandler, u4Cmd, &wrqu, pucExtraInfo); + +skip_indicate_event: + return; +} /* wext_indicate_wext_event */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief A method of struct net_device, to get the network interface statistical +* information. +* +* Whenever an application needs to get statistics for the interface, this method +* is called. This happens, for example, when ifconfig or netstat -i is run. +* +* \param[in] pDev Pointer to struct net_device. +* +* \return net_device_stats buffer pointer. +* +*/ +/*----------------------------------------------------------------------------*/ +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev) +{ + + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + P_GLUE_INFO_T prGlueInfo = NULL; + struct iw_statistics *pStats = NULL; + INT_32 i4Rssi; + UINT_32 bufLen = 0; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) + goto stat_out; + + pStats = (struct iw_statistics *)(&(prGlueInfo->rIwStats)); + + if (!prDev || !netif_carrier_ok(prDev)) { + /* network not connected */ + goto stat_out; + } + + rStatus = kalIoctl(prGlueInfo, wlanoidQueryRssi, &i4Rssi, sizeof(i4Rssi), TRUE, TRUE, TRUE, FALSE, &bufLen); + +stat_out: + return pStats; +} /* wlan_get_wireless_stats */ + + +#endif /* WIRELESS_EXT */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c new file mode 100644 index 0000000000000..2b6c3df845942 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/gl_wext_priv.c @@ -0,0 +1,3142 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/gl_wext_priv.c#4 +*/ + +/*! \file gl_wext_priv.c + \brief This file includes private ioctl support. +*/ + +/* +** Log: gl_wext_priv.c + * + * 07 17 2012 yuche.tsai + * NULL + * Let netdev bring up. + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 03 20 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * [WCXRP00001202] [MT6628 Wi-Fi][FW] Adding the New PN init code + * use return to avoid the ioctl return not supported + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 11 02 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Fixed typo. + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 07 28 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings + * Add BWCS cmd and event. + * + * 07 18 2011 chinghwa.yu + * [WCXRP00000063] Update BCM CoEx design and settings[WCXRP00000612] [MT6620 Wi-Fi] [FW] CSD update SWRDD algorithm + * Add CMD/Event for RDD and BWCS. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 26 2011 wh.su + * [WCXRP00000396] [MT6620 Wi-Fi][Driver] Support Sw Ctrl ioctl at linux + * adding the SW cmd ioctl support, use set/get structure ioctl. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Adjust OID order. + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 12 15 2010 george.huang + * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function + * Support set PS profile and set WMM-PS related iwpriv. + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * [WCXRP00000086] [MT6620 Wi-Fi][Driver] The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 24 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * correct typo for NVRAM access. + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * enable OID_CUSTOM_MTK_WIFI_TEST for RFTest & META tool + * + * 05 29 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * fix private ioctl for rftest + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support +** \main\maintrunk.MT5921\32 2009-10-08 10:33:25 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input +** parameters and pointers. +** \main\maintrunk.MT5921\31 2009-09-29 16:46:21 GMT mtk01090 +** Remove unused functions +** \main\maintrunk.MT5921\30 2009-09-29 14:46:47 GMT mtk01090 +** Fix compile warning +** \main\maintrunk.MT5921\29 2009-09-29 14:28:48 GMT mtk01090 +** Fix compile warning +** \main\maintrunk.MT5921\28 2009-09-28 22:21:38 GMT mtk01090 +** Refine lines to suppress compile warning +** \main\maintrunk.MT5921\27 2009-09-28 20:19:14 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\26 2009-08-18 22:56:53 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\25 2009-05-07 22:26:15 GMT mtk01089 +** Add mandatory and private IO control for Linux BWCS +** \main\maintrunk.MT5921\24 2009-04-29 10:07:05 GMT mtk01088 +** fixed the compiling error at linux +** \main\maintrunk.MT5921\23 2009-04-24 09:09:45 GMT mtk01088 +** mark the code not used at linux supplicant v0.6.7 +** \main\maintrunk.MT5921\22 2008-11-24 21:03:51 GMT mtk01425 +** 1. Add PTA_ENABLED flag +** \main\maintrunk.MT5921\21 2008-08-29 14:55:59 GMT mtk01088 +** adjust the code for meet the coding style, and add assert check +** \main\maintrunk.MT5921\20 2008-07-16 15:23:20 GMT mtk01104 +** Support GPIO2 mode +** \main\maintrunk.MT5921\19 2008-07-15 17:43:11 GMT mtk01084 +** modify variable name +** \main\maintrunk.MT5921\18 2008-07-14 14:37:58 GMT mtk01104 +** Add exception handle about length in function priv_set_struct() +** \main\maintrunk.MT5921\17 2008-07-14 13:55:32 GMT mtk01104 +** Support PRIV_CMD_BT_COEXIST +** \main\maintrunk.MT5921\16 2008-07-09 00:20:15 GMT mtk01461 +** Add priv oid to support WMM_PS_TEST +** \main\maintrunk.MT5921\15 2008-06-02 11:15:22 GMT mtk01461 +** Update after wlanoidSetPowerMode changed +** \main\maintrunk.MT5921\14 2008-05-30 19:31:07 GMT mtk01461 +** Add IOCTL for Power Mode +** \main\maintrunk.MT5921\13 2008-05-30 18:57:15 GMT mtk01461 +** Not use wlanoidSetCSUMOffloadForLinux() +** \main\maintrunk.MT5921\12 2008-05-30 15:13:18 GMT mtk01084 +** rename wlanoid +** \main\maintrunk.MT5921\11 2008-05-29 14:16:31 GMT mtk01084 +** rename for wlanoidSetBeaconIntervalForLinux +** \main\maintrunk.MT5921\10 2008-04-17 23:06:37 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\9 2008-03-31 21:00:55 GMT mtk01461 +** Add priv IOCTL for VOIP setting +** \main\maintrunk.MT5921\8 2008-03-31 13:49:43 GMT mtk01461 +** Add priv ioctl to turn on / off roaming +** \main\maintrunk.MT5921\7 2008-03-26 15:35:14 GMT mtk01461 +** Add CSUM offload priv ioctl for Linux +** \main\maintrunk.MT5921\6 2008-03-11 14:50:59 GMT mtk01461 +** Unify priv ioctl +** \main\maintrunk.MT5921\5 2007-11-06 19:32:30 GMT mtk01088 +** add WPS code +** \main\maintrunk.MT5921\4 2007-10-30 12:01:39 GMT MTK01425 +** 1. Update wlanQueryInformation and wlanSetInformation +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "precomp.h" + +#include "gl_os.h" +#include "gl_wext_priv.h" +#if CFG_SUPPORT_WAPI +#include "gl_sec.h" +#endif +#if CFG_ENABLE_WIFI_DIRECT +#include "gl_p2p_os.h" +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define NUM_SUPPORTED_OIDS (sizeof(arWlanOidReqTable) / sizeof(WLAN_REQ_ENTRY)) +#define CMD_START "START" +#define CMD_STOP "STOP" +#define CMD_SCAN_ACTIVE "SCAN-ACTIVE" +#define CMD_SCAN_PASSIVE "SCAN-PASSIVE" +#define CMD_RSSI "RSSI" +#define CMD_LINKSPEED "LINKSPEED" +#define CMD_RXFILTER_START "RXFILTER-START" +#define CMD_RXFILTER_STOP "RXFILTER-STOP" +#define CMD_RXFILTER_ADD "RXFILTER-ADD" +#define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" +#define CMD_BTCOEXMODE "BTCOEXMODE" +#define CMD_SETSUSPENDOPT "SETSUSPENDOPT" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" +#define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" +#define CMD_SETFWPATH "SETFWPATH" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_COUNTRY "COUNTRY" +#define CMD_P2P_SET_NOA "P2P_SET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_SET_PS "P2P_SET_PS" +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" +#define CMD_MIRACAST "MIRACAST" + +#define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" +#define CMD_PNOSETUP_SET "PNOSETUP " +#define CMD_PNOENABLE_SET "PNOFORCE" +#define CMD_PNODEBUG_SET "PNODEBUG" +#define CMD_WLS_BATCHING "WLS_BATCHING" + +#define CMD_OKC_SET_PMK "SET_PMK" +#define CMD_OKC_ENABLE "OKC_ENABLE" + +/* miracast related definition */ +#define MIRACAST_MODE_OFF 0 +#define MIRACAST_MODE_SOURCE 1 +#define MIRACAST_MODE_SINK 2 + +#ifndef MIRACAST_AMPDU_SIZE +#define MIRACAST_AMPDU_SIZE 8 +#endif + +#ifndef MIRACAST_MCHAN_ALGO +#define MIRACAST_MCHAN_ALGO 1 +#endif + +#ifndef MIRACAST_MCHAN_BW +#define MIRACAST_MCHAN_BW 25 +#endif + +#define CMD_BAND_AUTO 0 +#define CMD_BAND_5G 1 +#define CMD_BAND_2G 2 +#define CMD_BAND_ALL 3 + +/* Mediatek private command */ + +#define CMD_SET_SW_CTRL "SET_SW_CTRL" +#define CMD_GET_SW_CTRL "GET_SW_CTRL" +#define CMD_SET_CFG "SET_CFG" +#define CMD_GET_CFG "GET_CFG" +#define CMD_SET_CHIP "SET_CHIP" +#define CMD_GET_CHIP "GET_CHIP" +#define CMD_SET_DBG_LEVEL "SET_DBG_LEVEL" +#define CMD_GET_DBG_LEVEL "GET_DBG_LEVEL" +#define PRIV_CMD_SIZE 512 + +static UINT_32 g_ucMiracastMode = MIRACAST_MODE_OFF; + +typedef struct cmd_tlv { + char prefix; + char version; + char subver; + char reserved; +} cmd_tlv_t; + +typedef struct priv_driver_cmd_s { + char buf[PRIV_CMD_SIZE]; + int used_len; + int total_len; +} priv_driver_cmd_t; + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); + +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen); + +#if 0 /* CFG_SUPPORT_WPS */ +static int +priv_set_appie(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); + +static int +priv_set_filter(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, OUT char *pcExtra); +#endif /* CFG_SUPPORT_WPS */ + +static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY * ppWlanReqEntry); + +#if 0 +static WLAN_STATUS +reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +static WLAN_STATUS +reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); +#endif + +static WLAN_STATUS +reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen); + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +static UINT_8 aucOidBuf[4096] = { 0 }; + +/* OID processing table */ +/* Order is important here because the OIDs should be in order of + increasing value for binary searching. */ +static WLAN_REQ_ENTRY arWlanOidReqTable[] = { + /* + {(NDIS_OID)rOid, + (PUINT_8)pucOidName, + fgQryBufLenChecking, fgSetBufLenChecking, fgIsHandleInGlueLayerOnly, u4InfoBufLen, + pfOidQueryHandler, + pfOidSetHandler} + */ + /* General Operational Characteristics */ + + /* Ethernet Operational Characteristics */ + {OID_802_3_CURRENT_ADDRESS, + DISP_STRING("OID_802_3_CURRENT_ADDRESS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 6, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCurrentAddr, + NULL}, + + /* OID_802_3_MULTICAST_LIST */ + /* OID_802_3_MAXIMUM_LIST_SIZE */ + /* Ethernet Statistics */ + + /* NDIS 802.11 Wireless LAN OIDs */ + {OID_802_11_SUPPORTED_RATES, + DISP_STRING("OID_802_11_SUPPORTED_RATES"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_RATES_EX), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySupportedRates, + NULL} + , + /* + {OID_802_11_CONFIGURATION, + DISP_STRING("OID_802_11_CONFIGURATION"), + TRUE, TRUE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_802_11_CONFIG_T), + (PFN_OID_HANDLER_FUNC_REQ)reqExtQueryConfiguration, + (PFN_OID_HANDLER_FUNC_REQ)reqExtSetConfiguration}, + */ + {OID_PNP_SET_POWER, + DISP_STRING("OID_PNP_SET_POWER"), + TRUE, FALSE, ENUM_OID_GLUE_EXTENSION, sizeof(PARAM_DEVICE_POWER_STATE), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) reqExtSetAcpiDevicePowerState} + , + + /* Custom OIDs */ + {OID_CUSTOM_OID_INTERFACE_VERSION, + DISP_STRING("OID_CUSTOM_OID_INTERFACE_VERSION"), + TRUE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryOidInterfaceVersion, + NULL} + , + + /* + #if PTA_ENABLED + {OID_CUSTOM_BT_COEXIST_CTRL, + DISP_STRING("OID_CUSTOM_BT_COEXIST_CTRL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_BT_COEXIST_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtCoexistCtrl}, + #endif + */ + + /* + {OID_CUSTOM_POWER_MANAGEMENT_PROFILE, + DISP_STRING("OID_CUSTOM_POWER_MANAGEMENT_PROFILE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPwrMgmtProfParam, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPwrMgmtProfParam}, + {OID_CUSTOM_PATTERN_CONFIG, + DISP_STRING("OID_CUSTOM_PATTERN_CONFIG"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_PATTERN_SEARCH_CONFIG_STRUCT_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPatternConfig}, + {OID_CUSTOM_BG_SSID_SEARCH_CONFIG, + DISP_STRING("OID_CUSTOM_BG_SSID_SEARCH_CONFIG"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBgSsidParam}, + {OID_CUSTOM_VOIP_SETUP, + DISP_STRING("OID_CUSTOM_VOIP_SETUP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryVoipConnectionStatus, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetVoipConnectionStatus}, + {OID_CUSTOM_ADD_TS, + DISP_STRING("OID_CUSTOM_ADD_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidAddTS}, + {OID_CUSTOM_DEL_TS, + DISP_STRING("OID_CUSTOM_DEL_TS"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidDelTS}, + */ + + /* + #if CFG_LP_PATTERN_SEARCH_SLT + {OID_CUSTOM_SLT, + DISP_STRING("OID_CUSTOM_SLT"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQuerySltResult, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetSltMode}, + #endif + + {OID_CUSTOM_ROAMING_EN, + DISP_STRING("OID_CUSTOM_ROAMING_EN"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRoamingFunction, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetRoamingFunction}, + {OID_CUSTOM_WMM_PS_TEST, + DISP_STRING("OID_CUSTOM_WMM_PS_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetWiFiWmmPsTest}, + {OID_CUSTOM_COUNTRY_STRING, + DISP_STRING("OID_CUSTOM_COUNTRY_STRING"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryCurrentCountry, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetCurrentCountry}, + + #if CFG_SUPPORT_802_11D + {OID_CUSTOM_MULTI_DOMAIN_CAPABILITY, + DISP_STRING("OID_CUSTOM_MULTI_DOMAIN_CAPABILITY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryMultiDomainCap, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetMultiDomainCap}, + #endif + + {OID_CUSTOM_GPIO2_MODE, + DISP_STRING("OID_CUSTOM_GPIO2_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_PARAM_GPIO2_MODE_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetGPIO2Mode}, + {OID_CUSTOM_CONTINUOUS_POLL, + DISP_STRING("OID_CUSTOM_CONTINUOUS_POLL"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CONTINUOUS_POLL_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryContinuousPollInterval, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetContinuousPollProfile}, + {OID_CUSTOM_DISABLE_BEACON_DETECTION, + DISP_STRING("OID_CUSTOM_DISABLE_BEACON_DETECTION"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryDisableBeaconDetectionFunc, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisableBeaconDetectionFunc}, + */ + + /* WPS */ + /* + {OID_CUSTOM_DISABLE_PRIVACY_CHECK, + DISP_STRING("OID_CUSTOM_DISABLE_PRIVACY_CHECK"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetDisablePriavcyCheck}, + */ + + {OID_CUSTOM_MCR_RW, + DISP_STRING("OID_CUSTOM_MCR_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MCR_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMcrRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetMcrWrite} + , + + {OID_CUSTOM_EEPROM_RW, + DISP_STRING("OID_CUSTOM_EEPROM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_EEPROM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetEepromWrite} + , + + {OID_CUSTOM_SW_CTRL, + DISP_STRING("OID_CUSTOM_SW_CTRL"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_SW_CTRL_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQuerySwCtrlRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetSwCtrlWrite} + , + + {OID_CUSTOM_MEM_DUMP, + DISP_STRING("OID_CUSTOM_MEM_DUMP"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_MEM_DUMP_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryMemDump, + NULL} + , + + {OID_CUSTOM_TEST_MODE, + DISP_STRING("OID_CUSTOM_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetTestMode} + , + + /* + {OID_CUSTOM_TEST_RX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_RX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_RX_STATUS_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestRxStatus, + NULL}, + {OID_CUSTOM_TEST_TX_STATUS, + DISP_STRING("OID_CUSTOM_TEST_TX_STATUS"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_RFTEST_TX_STATUS_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryRfTestTxStatus, + NULL}, + */ + {OID_CUSTOM_ABORT_TEST_MODE, + DISP_STRING("OID_CUSTOM_ABORT_TEST_MODE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAbortTestMode} + , + {OID_CUSTOM_MTK_WIFI_TEST, + DISP_STRING("OID_CUSTOM_MTK_WIFI_TEST"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_MTK_WIFI_TEST_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestQueryAutoTest, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidRftestSetAutoTest} + , + + /* OID_CUSTOM_EMULATION_VERSION_CONTROL */ + + /* BWCS */ +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS + {OID_CUSTOM_BWCS_CMD, + DISP_STRING("OID_CUSTOM_BWCS_CMD"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PTA_IPC_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryBT, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetBT} + , +#endif + +/* {OID_CUSTOM_SINGLE_ANTENNA, + DISP_STRING("OID_CUSTOM_SINGLE_ANTENNA"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryBtSingleAntenna, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetBtSingleAntenna}, + {OID_CUSTOM_SET_PTA, + DISP_STRING("OID_CUSTOM_SET_PTA"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 4, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidQueryPta, + (PFN_OID_HANDLER_FUNC_REQ)wlanoidSetPta}, + */ + + {OID_CUSTOM_MTK_NVRAM_RW, + DISP_STRING("OID_CUSTOM_MTK_NVRAM_RW"), + TRUE, TRUE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_CUSTOM_NVRAM_RW_STRUCT_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryNvramRead, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetNvramWrite} + , + + {OID_CUSTOM_CFG_SRC_TYPE, + DISP_STRING("OID_CUSTOM_CFG_SRC_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_CFG_SRC_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryCfgSrcType, + NULL} + , + + {OID_CUSTOM_EEPROM_TYPE, + DISP_STRING("OID_CUSTOM_EEPROM_TYPE"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(ENUM_EEPROM_TYPE_T), + (PFN_OID_HANDLER_FUNC_REQ) wlanoidQueryEepromType, + NULL} + , + +#if CFG_SUPPORT_WAPI + {OID_802_11_WAPI_MODE, + DISP_STRING("OID_802_11_WAPI_MODE"), + FALSE, TRUE, ENUM_OID_DRIVER_CORE, 4, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiMode} + , + {OID_802_11_WAPI_ASSOC_INFO, + DISP_STRING("OID_802_11_WAPI_ASSOC_INFO"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiAssocInfo} + , + {OID_802_11_SET_WAPI_KEY, + DISP_STRING("OID_802_11_SET_WAPI_KEY"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, sizeof(PARAM_WPI_KEY_T), + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWapiKey} + , +#endif + +#if CFG_SUPPORT_WPS2 + {OID_802_11_WSC_ASSOC_INFO, + DISP_STRING("OID_802_11_WSC_ASSOC_INFO"), + FALSE, FALSE, ENUM_OID_DRIVER_CORE, 0, + NULL, + (PFN_OID_HANDLER_FUNC_REQ) wlanoidSetWSCAssocInfo} + , +#endif +}; + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dispatching function for private ioctl region (SIOCIWFIRSTPRIV ~ +* SIOCIWLASTPRIV). +* +* \param[in] prNetDev Net device requested. +* \param[in] prIfReq Pointer to ifreq structure. +* \param[in] i4Cmd Command ID between SIOCIWFIRSTPRIV and SIOCIWLASTPRIV. +* +* \retval 0 for success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +int priv_support_ioctl(IN struct net_device *prNetDev, IN OUT struct ifreq *prIfReq, IN int i4Cmd) +{ + /* prIfReq is verified in the caller function wlanDoIOCTL() */ + struct iwreq *prIwReq = (struct iwreq *)prIfReq; + struct iw_request_info rIwReqInfo; + + /* prDev is verified in the caller function wlanDoIOCTL() */ + + /* Prepare the call */ + rIwReqInfo.cmd = (__u16) i4Cmd; + rIwReqInfo.flags = 0; + + switch (i4Cmd) { + case IOCTL_SET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_set_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); + + case IOCTL_GET_INT: + /* NOTE(Kevin): 1/3 INT Type <= IFNAMSIZ, so we don't need copy_from/to_user() */ + return priv_get_int(prNetDev, &rIwReqInfo, &(prIwReq->u), (char *)&(prIwReq->u)); + + case IOCTL_SET_STRUCT: + case IOCTL_SET_STRUCT_FOR_EM: + return priv_set_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); + + case IOCTL_GET_STRUCT: + return priv_get_struct(prNetDev, &rIwReqInfo, &prIwReq->u, (char *)&(prIwReq->u)); + + default: + return -EOPNOTSUPP; + + } /* end of switch */ + +} /* priv_support_ioctl */ + +#if CFG_SUPPORT_BATCH_SCAN + +EVENT_BATCH_RESULT_T g_rEventBatchResult[CFG_BATCH_MAX_MSCAN]; + +UINT_32 batchChannelNum2Freq(UINT_32 u4ChannelNum) +{ + UINT_32 u4ChannelInMHz; + + if (u4ChannelNum >= 1 && u4ChannelNum <= 13) + u4ChannelInMHz = 2412 + (u4ChannelNum - 1) * 5; + else if (u4ChannelNum == 14) + u4ChannelInMHz = 2484; + else if (u4ChannelNum == 133) + u4ChannelInMHz = 3665; /* 802.11y */ + else if (u4ChannelNum == 137) + u4ChannelInMHz = 3685; /* 802.11y */ + else if (u4ChannelNum >= 34 && u4ChannelNum <= 165) + u4ChannelInMHz = 5000 + u4ChannelNum * 5; + else if (u4ChannelNum >= 183 && u4ChannelNum <= 196) + u4ChannelInMHz = 4000 + u4ChannelNum * 5; + else + u4ChannelInMHz = 0; + + return u4ChannelInMHz; +} + +#define TMP_TEXT_LEN_S 40 +#define TMP_TEXT_LEN_L 60 +static UCHAR text1[TMP_TEXT_LEN_S], text2[TMP_TEXT_LEN_L], text3[TMP_TEXT_LEN_L]; /* A safe len */ + +WLAN_STATUS +batchConvertResult(IN P_EVENT_BATCH_RESULT_T prEventBatchResult, + OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + CHAR *p = pvBuffer; + CHAR ssid[ELEM_MAX_LEN_SSID + 1]; + INT_32 nsize = 0, nsize1, nsize2, nsize3, scancount; + INT_32 i, j, nleft; + UINT_32 freq; + + P_EVENT_BATCH_RESULT_ENTRY_T prEntry; + P_EVENT_BATCH_RESULT_T pBr; + + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + pBr = prEventBatchResult; + scancount = 0; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + scancount += pBr->ucScanCount; + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "scancount=%x\nnextcount=%x\n", scancount, scancount); + if (nsize1 < nleft) { + p += nsize1 = kalSprintf(p, "%s", text1); + nleft -= nsize1; + } else + goto short_buf; + + pBr = prEventBatchResult; + for (j = 0; j < CFG_BATCH_MAX_MSCAN; j++) { + DBGLOG(SCN, TRACE, "convert mscan = %d, apcount=%d, nleft=%d\n", j, pBr->ucScanCount, nleft); + + if (pBr->ucScanCount == 0) { + pBr++; + continue; + } + + nleft -= 5; /* -5 for "####\n" */ + + /* We only support one round scan result now. */ + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "apcount=%d\n", pBr->ucScanCount); + if (nsize1 < nleft) { + p += nsize1 = kalSprintf(p, "%s", text1); + nleft -= nsize1; + } else + goto short_buf; + + for (i = 0; i < pBr->ucScanCount; i++) { + prEntry = &pBr->arBatchResult[i]; + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "bssid=" MACSTR "\n", + prEntry->aucBssid[0], + prEntry->aucBssid[1], + prEntry->aucBssid[2], + prEntry->aucBssid[3], + prEntry->aucBssid[4], prEntry->aucBssid[5]); + + kalMemCopy(ssid, + prEntry->aucSSID, + (prEntry->ucSSIDLen < ELEM_MAX_LEN_SSID ? prEntry->ucSSIDLen : ELEM_MAX_LEN_SSID)); + ssid[(prEntry->ucSSIDLen < + (ELEM_MAX_LEN_SSID - 1) ? prEntry->ucSSIDLen : (ELEM_MAX_LEN_SSID - 1))] = '\0'; + nsize2 = kalSnprintf(text2, TMP_TEXT_LEN_L, "ssid=%s\n", ssid); + + freq = batchChannelNum2Freq(prEntry->ucFreq); + nsize3 = + kalSnprintf(text3, TMP_TEXT_LEN_L, + "freq=%u\nlevel=%d\ndist=%u\ndistSd=%u\n====\n", freq, + prEntry->cRssi, prEntry->u4Dist, prEntry->u4Distsd); + + nsize = nsize1 + nsize2 + nsize3; + if (nsize < nleft) { + + kalStrnCpy(p, text1, TMP_TEXT_LEN_S); + p += nsize1; + + kalStrnCpy(p, text2, TMP_TEXT_LEN_L); + p += nsize2; + + kalStrnCpy(p, text3, TMP_TEXT_LEN_L); + p += nsize3; + + nleft -= nsize; + } else { + DBGLOG(SCN, TRACE, "Warning: Early break! (%d)\n", i); + break; /* discard following entries, TODO: apcount? */ + } + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "####\n"); + p += kalSprintf(p, "%s", text1); + + pBr++; + } + + nsize1 = kalSnprintf(text1, TMP_TEXT_LEN_S, "%s", "----\n"); + kalSprintf(p, "%s", text1); + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, + "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), + u4MaxBufferLen, (char *)pvBuffer); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +#if CFG_SUPPORT_GET_CH_ENV +WLAN_STATUS +scanEnvResult(P_GLUE_INFO_T prGlueInfo, OUT PVOID pvBuffer, IN UINT_32 u4MaxBufferLen, OUT PUINT_32 pu4RetLen) +{ + P_ADAPTER_T prAdapter = NULL; + CHAR *p = pvBuffer; + INT_32 nsize; + INT_32 i, nleft; + P_SCAN_INFO_T prScanInfo; + P_LINK_T prBSSDescList; + P_BSS_DESC_T prBssDesc; + CH_ENV_T chEnvInfo[54]; /* 54: from FW define; TODO: sync MAXIMUM_OPERATION_CHANNEL_LIST */ + UINT_32 i4GetCh = 0; + INT_32 i4Argc = 0; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = { 0 }; + UINT_8 ucTextLen = 40; + UCHAR text[ucTextLen]; + INT_32 u4Ret; + + prAdapter = prGlueInfo->prAdapter; + prScanInfo = &(prAdapter->rWifiVar.rScanInfo); + prBSSDescList = &prScanInfo->rBSSDescList; + + kalMemZero(chEnvInfo, sizeof(chEnvInfo)); + + DBGLOG(SCN, TRACE, "pvBuffer:%s, pu4RetLen:%d\n", (char *)pvBuffer, *pu4RetLen); + + wlanCfgParseArgument(pvBuffer, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &i4GetCh); + if (u4Ret) + DBGLOG(SCN, TRACE, "parse pvBuffer error u4Ret=%d\n", u4Ret); + /* i4GetCh = kalStrtoul(apcArgv[1], NULL, 0); */ + } + + nleft = u4MaxBufferLen - 5; /* -5 for "----\n" */ + + nsize = kalSnprintf(text, ucTextLen, "%s", "scanEnvResult\nResult:1\n");/* Always return 1 for alpha version. */ + + if (nsize < nleft) { + p += nsize = kalSnprintf(p, ucTextLen, "%s", text); + nleft -= nsize; + } else + goto short_buf; + + /* Search BSS Desc from current SCAN result list. */ + LINK_FOR_EACH_ENTRY(prBssDesc, prBSSDescList, rLinkEntry, BSS_DESC_T) { + if (prBssDesc->ucChannelNum > 0) { + if (prBssDesc->ucChannelNum <= 14) { /* 1~14 */ + chEnvInfo[prBssDesc->ucChannelNum - 1].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum - 1].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 64) { /* 15~22 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 + 5].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 116) { /* 23~27 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 - 3].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 140) { /* 28~30 */ + chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[prBssDesc->ucChannelNum / 4 - 6].ucApNum++; + } else if (prBssDesc->ucChannelNum <= 165) { /* 31~35 */ + chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucChNum = prBssDesc->ucChannelNum; + chEnvInfo[(prBssDesc->ucChannelNum - 1) / 4 - 7].ucApNum++; + } + } + } + + for (i = 0; i < 54; i++) { + if (chEnvInfo[i].ucChNum != 0) { + if (i4GetCh == 0 || (chEnvInfo[i].ucChNum == (UINT_8)i4GetCh)) { + DBGLOG(SCN, TRACE, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, chEnvInfo[i].ucApNum); + p += nsize = + kalSnprintf(p, ucTextLen, "chNum=%d,apNum=%d\n", chEnvInfo[i].ucChNum, + chEnvInfo[i].ucApNum); + nleft -= nsize; + } + } + } + + p += nsize = kalSnprintf(p, ucTextLen, "%s", "----\n"); + nleft -= nsize; + + *pu4RetLen = u4MaxBufferLen - nleft; + DBGLOG(SCN, TRACE, "total len = %d (max len = %d)\n", *pu4RetLen, u4MaxBufferLen); + + return WLAN_STATUS_SUCCESS; + +short_buf: + DBGLOG(SCN, TRACE, "Short buffer issue! %d > %d, %s\n", u4MaxBufferLen + (nsize - nleft), u4MaxBufferLen, p); + return WLAN_STATUS_INVALID_LENGTH; +} +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_PTA_IPC_T prPtaIpc; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_MODE: + /* printk("TestMode=%ld\n", pu4IntBuf[1]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY) { + prNdisReq->ndisOidCmd = OID_CUSTOM_TEST_MODE; + } else if (pu4IntBuf[1] == 0) { + prNdisReq->ndisOidCmd = OID_CUSTOM_ABORT_TEST_MODE; + } else { + status = 0; + break; + } + prNdisReq->inNdisOidlength = 0; + prNdisReq->outNdisOidLength = 0; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + case PRIV_CMD_TEST_CMD: + /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + if (pu4IntBuf[1] == PRIV_CMD_TEST_MAGIC_KEY && pu4IntBuf[2] == PRIV_CMD_TEST_MAGIC_KEY) + prGlueInfo->fgMcrAccessAllowed = TRUE; + status = 0; + break; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; +#endif + + case PRIV_CMD_SW_CTRL: + /* printk("addr=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetBeaconInterval, + (PVOID)&pu4IntBuf[1],/* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), &u4BufLen); + break; +#endif + +#if CFG_TCP_IP_CHKSUM_OFFLOAD + case PRIV_CMD_CSUM_OFFLOAD: + { + UINT_32 u4CSUMFlags; + + if (pu4IntBuf[1] == 1) + u4CSUMFlags = CSUM_OFFLOAD_EN_ALL; + else if (pu4IntBuf[1] == 0) + u4CSUMFlags = 0; + else + return -EINVAL; + + if (kalIoctl(prGlueInfo, + wlanoidSetCSUMOffload, + (PVOID)&u4CSUMFlags, + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { + if (pu4IntBuf[1] == 1) + prNetDev->features |= NETIF_F_HW_CSUM; + else if (pu4IntBuf[1] == 0) + prNetDev->features &= ~NETIF_F_HW_CSUM; + } + } + break; +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + + case PRIV_CMD_POWER_MODE: + kalIoctl(prGlueInfo, wlanoidSet802dot11PowerSaveProfile, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + break; + + case PRIV_CMD_WMM_PS: + { + PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T rWmmPsTest; + + rWmmPsTest.bmfgApsdEnAc = (UINT_8) pu4IntBuf[1]; + rWmmPsTest.ucIsEnterPsAtOnce = (UINT_8) pu4IntBuf[2]; + rWmmPsTest.ucIsDisableUcTrigger = (UINT_8) pu4IntBuf[3]; + rWmmPsTest.reserved = 0; + + kalIoctl(prGlueInfo, + wlanoidSetWiFiWmmPsTest, + (PVOID)&rWmmPsTest, + sizeof(PARAM_CUSTOM_WMM_PS_TEST_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + } + break; + +#if 0 + case PRIV_CMD_ADHOC_MODE: + rStatus = wlanSetInformation(prGlueInfo->prAdapter, wlanoidSetAdHocMode, + (PVOID)&pu4IntBuf[1], /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(UINT_32), &u4BufLen); + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + + DBGLOG(REQ, INFO, "pu4IntBuf[1] = %x, size of PTA_IPC_T = %zu.\n", + pu4IntBuf[1], sizeof(PARAM_PTA_IPC_T)); + + prPtaIpc = (P_PTA_IPC_T) aucOidBuf; + prPtaIpc->u.aucBTPParams[0] = (UINT_8) (pu4IntBuf[1] >> 24); + prPtaIpc->u.aucBTPParams[1] = (UINT_8) (pu4IntBuf[1] >> 16); + prPtaIpc->u.aucBTPParams[2] = (UINT_8) (pu4IntBuf[1] >> 8); + prPtaIpc->u.aucBTPParams[3] = (UINT_8) (pu4IntBuf[1]); + + DBGLOG(REQ, INFO, + "BCM BWCS CMD : BTPParams[0]=%02x, BTPParams[1]=%02x, BTPParams[2]=%02x, BTPParams[3]=%02x.\n", + prPtaIpc->u.aucBTPParams[0], prPtaIpc->u.aucBTPParams[1], prPtaIpc->u.aucBTPParams[2], + prPtaIpc->u.aucBTPParams[3]); + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + status = wlanoidSetBT(prGlueInfo->prAdapter, + (PVOID)&aucOidBuf[0], sizeof(PARAM_PTA_IPC_T), &u4BufLen); + + if (WLAN_STATUS_SUCCESS != status) + status = -EFAULT; + + break; + + case PRIV_CMD_BAND_CONFIG: + { + DBGLOG(REQ, INFO, "CMD set_band=%u\n", (UINT_32) pu4IntBuf[1]); + } + break; + +#if CFG_ENABLE_WIFI_DIRECT + case PRIV_CMD_P2P_MODE: + { + /* no use, move to set_p2p_mode_handler() */ + PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode; + + p2pmode.u4Enable = pu4IntBuf[1]; + p2pmode.u4Mode = pu4IntBuf[2]; + set_p2p_mode_handler(prNetDev, p2pmode); +#if 0 + PARAM_CUSTOM_P2P_SET_STRUCT_T rSetP2P; + WLAN_STATUS rWlanStatus = WLAN_STATUS_SUCCESS; + BOOLEAN fgIsP2PEnding; + + GLUE_SPIN_LOCK_DECLARATION(); + + /* avoid remove & p2p off command simultaneously */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + fgIsP2PEnding = g_u4P2PEnding; + g_u4P2POnOffing = 1; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + + if (fgIsP2PEnding == 1) { + /* skip the command if we are removing */ + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); + break; + } + rSetP2P.u4Enable = pu4IntBuf[1]; + rSetP2P.u4Mode = pu4IntBuf[2]; + + if (!rSetP2P.u4Enable) + p2pNetUnregister(prGlueInfo, TRUE); + + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + /* + Scenario: + 1. System enters suspend/resume but not yet enter wlanearlysuspend() + or wlanlateresume(); + + 2. System switches to do PRIV_CMD_P2P_MODE and execute kalIoctl() + and get g_halt_sem then do glRegisterEarlySuspend() or + glUnregisterEarlySuspend(); + + But system suspend/resume procedure is not yet finished so we + suspend; + + 3. System switches back to do suspend/resume procedure and execute + kalIoctl(). But driver does not yet release g_halt_sem so system + suspend in wlanearlysuspend() or wlanlateresume(); + + ==> deadlock occurs. + */ + if ((!rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { + /* fgIsP2PRegistered == TRUE means P2P is enabled */ + DBGLOG(P2P, INFO, "p2pEalySuspendReg\n"); + p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p remove */ + } + + DBGLOG(P2P, INFO, + "wlanoidSetP2pMode 0x%p %d %d\n", &rSetP2P, rSetP2P.u4Enable, rSetP2P.u4Mode); + rWlanStatus = kalIoctl(prGlueInfo, wlanoidSetP2pMode, + (PVOID)&rSetP2P, /* pu4IntBuf[0] is used as input SubCmd */ + sizeof(PARAM_CUSTOM_P2P_SET_STRUCT_T), + FALSE, FALSE, TRUE, FALSE, &u4BufLen); + DBGLOG(P2P, INFO, "wlanoidSetP2pMode ok\n"); + + /* move out to caller to avoid kalIoctrl & suspend/resume deadlock problem ALPS00844864 */ + if ((rSetP2P.u4Enable) && (g_u4HaltFlag == 0) && (fgIsResetting == FALSE)) { + /* fgIsP2PRegistered == TRUE means P2P on successfully */ + p2pEalySuspendReg(prGlueInfo, rSetP2P.u4Enable); /* p2p on */ + } + + if (rSetP2P.u4Enable) + p2pNetRegister(prGlueInfo, TRUE); + + GLUE_ACQUIRE_THE_SPIN_LOCK(&g_p2p_lock); + g_u4P2POnOffing = 0; + GLUE_RELEASE_THE_SPIN_LOCK(&g_p2p_lock); +#endif + } + break; +#endif + +#if (CFG_SUPPORT_MET_PROFILING == 1) + case PRIV_CMD_MET_PROFILING: + { + /* PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; */ + /* rWfdDebugModeInfo.ucWFDDebugMode=(UINT_8)pu4IntBuf[1]; */ + /* rWfdDebugModeInfo.u2SNPeriod=(UINT_16)pu4IntBuf[2]; */ + /* DBGLOG(REQ, INFO,("WFD Debug Mode:%d Period:%d\n", + rWfdDebugModeInfo.ucWFDDebugMode,rWfdDebugModeInfo.u2SNPeriod)); */ + prGlueInfo->u8MetProfEnable = (UINT_8) pu4IntBuf[1]; + prGlueInfo->u16MetUdpPort = (UINT_16) pu4IntBuf[2]; + DBGLOG(REQ, INFO, "MET_PROF: Enable=%d UDP_PORT=%d\n", prGlueInfo->u8MetProfEnable, + prGlueInfo->u16MetUdpPort); + + } + break; + +#endif + case PRIV_CMD_WFD_DEBUG_CODE: + { + PARAM_CUSTOM_WFD_DEBUG_STRUCT_T rWfdDebugModeInfo; + + rWfdDebugModeInfo.ucWFDDebugMode = (UINT_8) pu4IntBuf[1]; + rWfdDebugModeInfo.u2SNPeriod = (UINT_16) pu4IntBuf[2]; + DBGLOG(REQ, INFO, "WFD Debug Mode:%d Period:%d\n", rWfdDebugModeInfo.ucWFDDebugMode, + rWfdDebugModeInfo.u2SNPeriod); + kalIoctl(prGlueInfo, wlanoidSetWfdDebugMode, (PVOID)&rWfdDebugModeInfo, + sizeof(PARAM_CUSTOM_WFD_DEBUG_STRUCT_T), FALSE, FALSE, TRUE, FALSE, &u4BufLen); + + } + break; + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +UINT_8 gucBufDbgCode[1000]; + +static int +_priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd; + PUINT_32 pu4IntBuf; + P_GLUE_INFO_T prGlueInfo; + UINT_32 u4BufLen = 0; + int status = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->mode; + pu4IntBuf = (PUINT_32) pcExtra; + + switch (u4SubCmd) { + case PRIV_CMD_TEST_CMD: + /* printk("CMD=0x%08lx, data=0x%08lx\n", pu4IntBuf[1], pu4IntBuf[2]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MTK_WIFI_TEST; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + /* + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], 4)) { + printk(KERN_NOTICE "priv_get_int() copy_to_user oidBuf fail(3)\n"); + return -EFAULT; + } + */ + } + return status; + +#if CFG_SUPPORT_PRIV_MCR_RW + case PRIV_CMD_ACCESS_MCR: + /* printk("addr=0x%08lx\n", pu4IntBuf[1]); */ + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MCR_RW; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + } + return status; +#endif + + case PRIV_CMD_DUMP_MEM: + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + +#if 1 + if (!prGlueInfo->fgMcrAccessAllowed) { + status = 0; + return status; + } +#endif + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_MEM_DUMP; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[0]; + return status; + + case PRIV_CMD_SW_CTRL: + /* printk(" addr=0x%08lx\n", pu4IntBuf[1]); */ + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + kalMemCopy(&prNdisReq->ndisOidContent[0], &pu4IntBuf[1], 8); + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + /* printk("Result=%ld\n", *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + prIwReqData->mode = *(PUINT_32) &prNdisReq->ndisOidContent[4]; + } + return status; + +#if 0 + case PRIV_CMD_BEACON_PERIOD: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; + + case PRIV_CMD_POWER_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQuery802dot11PowerSaveProfile, + (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; + + case PRIV_CMD_ADHOC_MODE: + status = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAdHocMode, (PVOID) pu4IntBuf, sizeof(UINT_32), &u4BufLen); + return status; +#endif + + case PRIV_CMD_BAND_CONFIG: + DBGLOG(REQ, INFO, "CMD get_band=\n"); + prIwReqData->mode = 0; + return status; + + default: + break; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i, j = 0; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + INT_32 ch[50]; + /*RF_CHANNEL_INFO_T aucChannelList[50];*/ + P_RF_CHANNEL_INFO_T paucChannelList; + P_RF_CHANNEL_INFO_T ChannelList_t; + + paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); + if (paucChannelList == NULL) { + DBGLOG(REQ, INFO, "alloc ChannelList fail\n"); + return -EFAULT; + } + kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); + if (NumOfChannel > 50) { + ASSERT(0); + NumOfChannel = 50; + } + + ChannelList_t = paucChannelList; + if (kalIsAPmode(prGlueInfo)) { + for (i = 0; i < NumOfChannel; i++) { + if ((ChannelList_t->ucChannelNum <= 13) + || (ChannelList_t->ucChannelNum == 36 + || ChannelList_t->ucChannelNum == 40 + || ChannelList_t->ucChannelNum == 44 + || ChannelList_t->ucChannelNum == 48)) { + ch[j] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + j++; + } + } + } else { + for (j = 0; j < NumOfChannel; j++) { + ch[j] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + } + } + + kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); + + prIwReqData->data.length = j; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) + return -EFAULT; + else + return status; + } + + case PRIV_CMD_GET_BUILD_DATE_CODE: + { + UINT_8 aucBuffer[16]; + + if (kalIoctl(prGlueInfo, + wlanoidQueryBuildDateCode, + (PVOID) aucBuffer, + sizeof(UINT_8) * 16, TRUE, TRUE, TRUE, FALSE, &u4BufLen) == WLAN_STATUS_SUCCESS) { + prIwReqData->data.length = sizeof(UINT_8) * 16; + + if (copy_to_user(prIwReqData->data.pointer, aucBuffer, prIwReqData->data.length)) + return -EFAULT; + else + return status; + } else { + return -EFAULT; + } + } + + case PRIV_CMD_GET_DEBUG_CODE: + { + wlanQueryDebugCode(prGlueInfo->prAdapter); + + kalMemSet(gucBufDbgCode, '.', sizeof(gucBufDbgCode)); + if (copy_to_user(prIwReqData->data.pointer, gucBufDbgCode, prIwReqData->data.length)) + return -EFAULT; + else + return status; + } + + default: + return -EOPNOTSUPP; + } + + return status; +} /* priv_get_int */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set int array handler. +* +* \param[in] prNetDev Net device requested. +* \param[in] prIwReqInfo Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl data structure, use the field of sub-command. +* \param[in] pcExtra The buffer with input value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd, u4BufLen; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_SET_TXPWR_CTRL_T prTxpwr; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_SET_TX_POWER: + { + INT_32 *setting = prIwReqData->data.pointer; + UINT_16 i; + +#if 0 + DBGLOG(REQ, INFO, "Tx power num = %d\n", prIwReqData->data.length); + + DBGLOG(REQ, INFO, "Tx power setting = %d %d %d %d\n", + setting[0], setting[1], setting[2], setting[3]); +#endif + prTxpwr = &prGlueInfo->rTxPwr; + if (setting[0] == 0 && prIwReqData->data.length == 4 /* argc num */) { + /* 0 (All networks), 1 (legacy STA), 2 (Hotspot AP), 3 (P2P), 4 (BT over Wi-Fi) */ + if (setting[1] == 1 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GLegacyStaPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GLegacyStaPwrOffset = setting[3]; + } + if (setting[1] == 2 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GHotspotPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GHotspotPwrOffset = setting[3]; + } + if (setting[1] == 3 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GP2pPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GP2pPwrOffset = setting[3]; + } + if (setting[1] == 4 || setting[1] == 0) { + if (setting[2] == 0 || setting[2] == 1) + prTxpwr->c2GBowPwrOffset = setting[3]; + if (setting[2] == 0 || setting[2] == 2) + prTxpwr->c5GBowPwrOffset = setting[3]; + } + } else if (setting[0] == 1 && prIwReqData->data.length == 2) { + prTxpwr->ucConcurrencePolicy = setting[1]; + } else if (setting[0] == 2 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 14; i++) + prTxpwr->acTxPwrLimit2G[i] = setting[2]; + } else if (setting[1] <= 14) + prTxpwr->acTxPwrLimit2G[setting[1] - 1] = setting[2]; + } else if (setting[0] == 3 && prIwReqData->data.length == 3) { + if (setting[1] == 0) { + for (i = 0; i < 4; i++) + prTxpwr->acTxPwrLimit5G[i] = setting[2]; + } else if (setting[1] <= 4) + prTxpwr->acTxPwrLimit5G[setting[1] - 1] = setting[2]; + } else if (setting[0] == 4 && prIwReqData->data.length == 2) { + if (setting[1] == 0) + wlanDefTxPowerCfg(prGlueInfo->prAdapter); + rStatus = kalIoctl(prGlueInfo, + wlanoidSetTxPower, + prTxpwr, + sizeof(SET_TXPWR_CTRL_T), TRUE, FALSE, FALSE, FALSE, &u4BufLen); + } else + return -EFAULT; + } + return status; + default: + break; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get int array handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] prIwReqData The ioctl req structure, use the field of sub-command. +* \param[out] pcExtra The buffer with put the return value +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EFAULT For fail. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd; + P_GLUE_INFO_T prGlueInfo; + int status = 0; + INT_32 ch[50]; + + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + + switch (u4SubCmd) { + case PRIV_CMD_GET_CH_LIST: + { + UINT_16 i; + UINT_8 NumOfChannel = 50; + UINT_8 ucMaxChannelNum = 50; + /*RF_CHANNEL_INFO_T aucChannelList[50];*/ + P_RF_CHANNEL_INFO_T paucChannelList; + P_RF_CHANNEL_INFO_T ChannelList_t; + + paucChannelList = kalMemAlloc(sizeof(RF_CHANNEL_INFO_T) * 50, VIR_MEM_TYPE); + if (paucChannelList == NULL) { + DBGLOG(REQ, INFO, "alloc fail\n"); + return -EINVAL; + } + kalMemZero(paucChannelList, sizeof(RF_CHANNEL_INFO_T) * 50); + + kalGetChannelList(prGlueInfo, BAND_NULL, ucMaxChannelNum, &NumOfChannel, paucChannelList); + if (NumOfChannel > 50) + NumOfChannel = 50; + + ChannelList_t = paucChannelList; + for (i = 0; i < NumOfChannel; i++) { + ch[i] = (INT_32) ChannelList_t->ucChannelNum; + ChannelList_t++; + } + + kalMemFree(paucChannelList, VIR_MEM_TYPE, sizeof(RF_CHANNEL_INFO_T) * 50); + prIwReqData->data.length = NumOfChannel; + if (copy_to_user(prIwReqData->data.pointer, ch, NumOfChannel * sizeof(INT_32))) + return -EFAULT; + else + return status; + } + default: + break; + } + + return status; +} /* priv_get_int */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl set structure handler. +* +* \param[in] pDev Net device requested. +* \param[in] prIwReqData Pointer to iwreq_data structure. +* +* \retval 0 For success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL If a value is out of range. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + int status = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + UINT_32 u4CmdLen = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq; + PUINT_32 pu4IntBuf = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + + ASSERT(prNetDev); + /* ASSERT(prIwReqInfo); */ + ASSERT(prIwReqData); + /* ASSERT(pcExtra); */ + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + if (FALSE == GLUE_CHK_PR2(prNetDev, prIwReqData)) + return -EINVAL; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + +#if 0 + DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + + switch (u4SubCmd) { +#if 0 /* PTA_ENABLED */ + case PRIV_CMD_BT_COEXIST: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_CUSTOM_BT_COEXIST_T) >= u4CmdLen); + if (sizeof(PARAM_CUSTOM_BT_COEXIST_T) < u4CmdLen) + return -EFAULT; + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } + + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBtCoexistCtrl, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); + if (WLAN_STATUS_SUCCESS != rStatus) + status = -EFAULT; + break; +#endif + + case PRIV_CUSTOM_BWCS_CMD: + u4CmdLen = prIwReqData->data.length * sizeof(UINT_32); + ASSERT(sizeof(PARAM_PTA_IPC_T) >= u4CmdLen); + if (sizeof(PARAM_PTA_IPC_T) < u4CmdLen) + return -EFAULT; +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, + "ucCmdLen = %d, size of PTA_IPC_T = %d, prIwReqData->data = 0x%x.\n", u4CmdLen, + sizeof(PARAM_PTA_IPC_T), prIwReqData->data); + + DBGLOG(REQ, INFO, "priv_set_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%u)\n", + prIwReqInfo->cmd, u4SubCmd); + + DBGLOG(REQ, INFO, "*pcExtra = 0x%x\n", *pcExtra); +#endif + + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, u4CmdLen)) { + status = -EFAULT; /* return -EFAULT; */ + break; + } +#if CFG_SUPPORT_BCM && CFG_SUPPORT_BCM_BWCS && CFG_SUPPORT_BCM_BWCS_DEBUG + DBGLOG(REQ, INFO, "priv_set_struct(): BWCS CMD = %02x%02x%02x%02x\n", + aucOidBuf[2], aucOidBuf[3], aucOidBuf[4], aucOidBuf[5]); +#endif + +#if 0 + status = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBT, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + +#if 1 + status = wlanoidSetBT(prGlueInfo->prAdapter, (PVOID)&aucOidBuf[0], u4CmdLen, &u4BufLen); +#endif + + if (WLAN_STATUS_SUCCESS != status) + status = -EFAULT; + + break; + +#if CFG_SUPPORT_WPS2 + case PRIV_CMD_WSC_PROBE_REQ: + { + /* retrieve IE for Probe Request */ + if (prIwReqData->data.length > 0) { + if (copy_from_user(prGlueInfo->aucWSCIE, prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + break; + } + prGlueInfo->u2WSCIELen = prIwReqData->data.length; + } else { + prGlueInfo->u2WSCIELen = 0; + } + } + break; +#endif + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, prIwReqData->data.length)) { + status = -EFAULT; + break; + } + if (!kalMemCmp(&aucOidBuf[0], pcExtra, prIwReqData->data.length)) + DBGLOG(REQ, INFO, "pcExtra buffer is valid\n"); + else + DBGLOG(REQ, INFO, "pcExtra 0x%p\n", pcExtra); + /* Execute this OID */ + status = priv_set_ndis(prNetDev, (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0], &u4BufLen); + /* Copy result to user space */ + ((P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0])->outNdisOidLength = u4BufLen; + + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "copy_to_user oidBuf fail\n"); + status = -EFAULT; + } + + break; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + /* kalMemCopy(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, 8); */ + if (copy_from_user(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, + prIwReqData->data.length)) { + status = -EFAULT; + break; + } + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + /* Execute this OID */ + status = priv_set_ndis(prNetDev, prNdisReq, &u4BufLen); + break; + + default: + return -EOPNOTSUPP; + } + + return status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Private ioctl get struct handler. +* +* \param[in] pDev Net device requested. +* \param[out] pIwReq Pointer to iwreq structure. +* \param[in] cmd Private sub-command. +* +* \retval 0 For success. +* \retval -EFAULT If copy from user space buffer fail. +* \retval -EOPNOTSUPP Parameter "cmd" not recognized. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + UINT_32 u4SubCmd = 0; + P_NDIS_TRANSPORT_STRUCT prNdisReq = NULL; + + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4BufLen = 0; + PUINT_32 pu4IntBuf = NULL; + int status = 0; + + kalMemZero(&aucOidBuf[0], sizeof(aucOidBuf)); + + ASSERT(prNetDev); + ASSERT(prIwReqData); + if (!prNetDev || !prIwReqData) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid param(0x%p, 0x%p)\n", prNetDev, prIwReqData); + return -EINVAL; + } + + u4SubCmd = (UINT_32) prIwReqData->data.flags; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_struct(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_struct(): prIwReqInfo->cmd(0x%X), u4SubCmd(%ld)\n", + prIwReqInfo->cmd, u4SubCmd); +#endif + memset(aucOidBuf, 0, sizeof(aucOidBuf)); + + switch (u4SubCmd) { + case PRIV_CMD_OID: + if (copy_from_user(&aucOidBuf[0], prIwReqData->data.pointer, sizeof(NDIS_TRANSPORT_STRUCT))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; +#if 0 + DBGLOG(REQ, INFO, "\n priv_get_struct cmd 0x%02x len:%d OID:0x%08x OID Len:%d\n", + cmd, pIwReq->u.data.length, ndisReq->ndisOidCmd, ndisReq->inNdisOidlength); +#endif + if (priv_get_ndis(prNetDev, prNdisReq, &u4BufLen) == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], + u4BufLen + sizeof(NDIS_TRANSPORT_STRUCT) - + sizeof(prNdisReq->ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(1)\n"); + return -EFAULT; + } + return 0; + } + prNdisReq->outNdisOidLength = u4BufLen; + if (copy_to_user(prIwReqData->data.pointer, + &aucOidBuf[0], OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent))) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + return -EFAULT; + + case PRIV_CMD_SW_CTRL: + pu4IntBuf = (PUINT_32) prIwReqData->data.pointer; + prNdisReq = (P_NDIS_TRANSPORT_STRUCT) &aucOidBuf[0]; + + if (copy_from_user(&prNdisReq->ndisOidContent[0], prIwReqData->data.pointer, + prIwReqData->data.length)) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_from_user oidBuf fail\n"); + return -EFAULT; + } + + prNdisReq->ndisOidCmd = OID_CUSTOM_SW_CTRL; + prNdisReq->inNdisOidlength = 8; + prNdisReq->outNdisOidLength = 8; + + status = priv_get_ndis(prNetDev, prNdisReq, &u4BufLen); + if (status == 0) { + prNdisReq->outNdisOidLength = u4BufLen; + /* printk("len=%d Result=%08lx\n", u4BufLen, *(PUINT_32)&prNdisReq->ndisOidContent[4]); */ + + if (copy_to_user(prIwReqData->data.pointer, + &prNdisReq->ndisOidContent[4], + 4 /* OFFSET_OF(NDIS_TRANSPORT_STRUCT, ndisOidContent) */)) { + DBGLOG(REQ, INFO, "priv_get_struct() copy_to_user oidBuf fail(2)\n"); + } + } + return 0; + + default: + DBGLOG(REQ, WARN, "get struct cmd:0x%x\n", u4SubCmd); + return -EOPNOTSUPP; + } +} /* priv_get_struct */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_set_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 u4SetInfoLen = 0; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_set_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_set_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry)) { + /* WARNLOG(("Set OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (NULL == prWlanReqEntry->pfOidSetHandler) { + /* WARNLOG(("Set %s: Null set handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(REQ, INFO, "priv_set_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgSetBufLenChecking) { + if (prNdisReq->inNdisOidlength != prWlanReqEntry->u4InfoBufLen) { + DBGLOG(REQ, WARN, "Set %s: Invalid length (current=%u, needed=%u)\n", + prWlanReqEntry->pucOidName, + prNdisReq->inNdisOidlength, prWlanReqEntry->u4InfoBufLen); + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidSetHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4SetInfoLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidSetHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + } else { + DBGLOG(REQ, INFO, "priv_set_ndis(): unsupported OID method:0x%x\n", prWlanReqEntry->eOidMethod); + return -EOPNOTSUPP; + } + + *pu4OutputLen = u4SetInfoLen; + + switch (status) { + case WLAN_STATUS_SUCCESS: + break; + + case WLAN_STATUS_INVALID_LENGTH: + /* WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* u4SetInfoLen)); */ + break; + } + + if (WLAN_STATUS_SUCCESS != status) + return -EFAULT; + + return 0; +} /* priv_set_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a query operation for a single OID. Basically we +* return information about the current state of the OID in question. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* \retval -EINVAL invalid input parameters +* +*/ +/*----------------------------------------------------------------------------*/ +static int +priv_get_ndis(IN struct net_device *prNetDev, IN NDIS_TRANSPORT_STRUCT * prNdisReq, OUT PUINT_32 pu4OutputLen) +{ + P_WLAN_REQ_ENTRY prWlanReqEntry = NULL; + UINT_32 u4BufLen = 0; + WLAN_STATUS status = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + + ASSERT(prNetDev); + ASSERT(prNdisReq); + ASSERT(pu4OutputLen); + + if (!prNetDev || !prNdisReq || !pu4OutputLen) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid param(0x%p, 0x%p, 0x%p)\n", + prNetDev, prNdisReq, pu4OutputLen); + return -EINVAL; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + ASSERT(prGlueInfo); + if (!prGlueInfo) { + DBGLOG(REQ, INFO, "priv_get_ndis(): invalid prGlueInfo(0x%p, 0x%p)\n", + prNetDev, *((P_GLUE_INFO_T *) netdev_priv(prNetDev))); + return -EINVAL; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_ndis(): prNdisReq->ndisOidCmd(0x%lX)\n", prNdisReq->ndisOidCmd); +#endif + + if (FALSE == reqSearchSupportedOidEntry(prNdisReq->ndisOidCmd, &prWlanReqEntry)) { + /* WARNLOG(("Query OID: 0x%08lx (unknown)\n", prNdisReq->ndisOidCmd)); */ + return -EOPNOTSUPP; + } + + if (NULL == prWlanReqEntry->pfOidQueryHandler) { + /* WARNLOG(("Query %s: Null query handler\n", prWlanReqEntry->pucOidName)); */ + return -EOPNOTSUPP; + } +#if 0 + DBGLOG(REQ, INFO, "priv_get_ndis(): %s\n", prWlanReqEntry->pucOidName); +#endif + + if (prWlanReqEntry->fgQryBufLenChecking) { + if (prNdisReq->inNdisOidlength < prWlanReqEntry->u4InfoBufLen) { + /* Not enough room in InformationBuffer. Punt */ + /* WARNLOG(("Query %s: Buffer too short (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* prWlanReqEntry->u4InfoBufLen)); */ + + *pu4OutputLen = prWlanReqEntry->u4InfoBufLen; + + status = WLAN_STATUS_INVALID_LENGTH; + return -EINVAL; + } + } + + if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_ONLY) { + /* GLUE sw info only */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_GLUE_EXTENSION) { + /* multiple sw operations */ + status = prWlanReqEntry->pfOidQueryHandler(prGlueInfo, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, &u4BufLen); + } else if (prWlanReqEntry->eOidMethod == ENUM_OID_DRIVER_CORE) { + /* driver core */ + + status = kalIoctl(prGlueInfo, + (PFN_OID_HANDLER_FUNC) prWlanReqEntry->pfOidQueryHandler, + prNdisReq->ndisOidContent, + prNdisReq->inNdisOidlength, TRUE, TRUE, TRUE, FALSE, &u4BufLen); + } else { + DBGLOG(REQ, INFO, "priv_set_ndis(): unsupported OID method:0x%x\n", prWlanReqEntry->eOidMethod); + return -EOPNOTSUPP; + } + + *pu4OutputLen = u4BufLen; + + switch (status) { + case WLAN_STATUS_SUCCESS: + break; + + case WLAN_STATUS_INVALID_LENGTH: + /* WARNLOG(("Set %s: Invalid length (current=%ld, needed=%ld)\n", */ + /* prWlanReqEntry->pucOidName, */ + /* prNdisReq->inNdisOidlength, */ + /* u4BufLen)); */ + break; + } + + if (WLAN_STATUS_SUCCESS != status) + return -EOPNOTSUPP; + + return 0; +} /* priv_get_ndis */ + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse command value in a string. +* +* @param InStr Pointer to the string buffer. +* @param OutStr Pointer to the next command value. +* @param OutLen Record the resident buffer length. +* +* @retval Command value. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen) +{ + unsigned char Charc, *Buf; + unsigned int Num; + int Maxloop; + int ReadId; + int TotalLen; + + /* init */ + Num = 0; + Maxloop = 0; + ReadId = 0; + Buf = (unsigned char *)InStr; + TotalLen = *OutLen; + *OutStr = Buf; + + /* sanity check */ + if (Buf[0] == 0x00) + return 0; + + /* check the value is decimal or hex */ + if ((Buf[ReadId] == 'x') || ((Buf[ReadId] == '0') && (Buf[ReadId + 1] == 'x'))) { + /* skip x or 0x */ + if (Buf[ReadId] == 'x') + ReadId++; + else + ReadId += 2; + + /* translate the hex number */ + while (Maxloop++ < 10) { + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc -= 'a'; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc -= 'A'; + else + break; /* exit the parsing */ + Num = Num * 16 + Charc + 10; + ReadId++; + TotalLen--; + } + } else { + /* translate the decimal number */ + while (Maxloop++ < 10) { + Charc = Buf[ReadId]; + if ((Charc < 0x30) || (Charc > 0x39)) + break; /* exit the parsing */ + Charc -= 0x30; + Num = Num * 10 + Charc; + ReadId++; + TotalLen--; + } + } + + if (Buf[ReadId] == 0x00) + *OutStr = &Buf[ReadId]; + else + *OutStr = &Buf[ReadId + 1]; /* skip the character: _ */ + + *OutLen = TotalLen - 1; /* skip the character: _ */ + return Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* @brief Parse command MAC address in a string. +* +* @param InStr Pointer to the string buffer. +* @param OutStr Pointer to the next command value. +* @param OutLen Record the resident buffer length. +* +* @retval Command value. +*/ +/*----------------------------------------------------------------------------*/ +UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac) +{ + unsigned char Charc, *Buf; + unsigned int Num; + int Maxloop; + int ReadId; + int TotalLen; + + /* init */ + Num = 0; + Maxloop = 0; + ReadId = 0; + Buf = (unsigned char *)InStr; + TotalLen = *OutLen; + *OutStr = Buf; + + /* sanity check */ + if (Buf[0] == 0x00) + return 0; + + /* parse MAC */ + while (Maxloop < 6) { + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc = Charc - 'a' + 10; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc = Charc - 'A' + 10; + else + return -1; /* error, exit the parsing */ + + Num = Charc; + ReadId++; + TotalLen--; + + Charc = Buf[ReadId]; + if ((Charc >= 0x30) && (Charc <= 0x39)) + Charc -= 0x30; + else if ((Charc >= 'a') && (Charc <= 'f')) + Charc = Charc - 'a' + 10; + else if ((Charc >= 'A') && (Charc <= 'F')) + Charc = Charc - 'A' + 10; + else + return -1; /* error, exit the parsing */ + + Num = Num * 16 + Charc; + ReadId += 2; /* skip the character and ':' */ + TotalLen -= 2; + + OutMac[Maxloop] = Num; + Maxloop++; + } + + *OutStr = &Buf[ReadId]; /* skip the character: _ */ + *OutLen = TotalLen; /* skip the character: _ */ + return Num; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief The routine handles a set operation for a single OID. +* +* \param[in] pDev Net device requested. +* \param[in] ndisReq Ndis request OID information copy from user. +* \param[out] outputLen_p If the call is successful, returns the number of +* bytes written into the query buffer. If the +* call failed due to invalid length of the query +* buffer, returns the amount of storage needed.. +* +* \retval 0 On success. +* \retval -EOPNOTSUPP If cmd is not supported. +* +*/ +/*----------------------------------------------------------------------------*/ +static int +_priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + P_GLUE_INFO_T GlueInfo; + INT_32 Status; + UINT_32 Subcmd; + UINT_8 *InBuf; + UINT_32 InBufLen; + + /* sanity check */ + ASSERT(prNetDev); + ASSERT(prIwReqInfo); + ASSERT(prIwReqData); + ASSERT(pcExtra); + + /* init */ + DBGLOG(REQ, INFO, "priv_set_string (%s)(%d)\n", + (UINT8 *) prIwReqData->data.pointer, (INT32) prIwReqData->data.length); + + if (FALSE == GLUE_CHK_PR3(prNetDev, prIwReqData, pcExtra)) + return -EINVAL; + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + InBuf = aucOidBuf; + InBufLen = prIwReqData->data.length; + Status = 0; + + if (copy_from_user(InBuf, prIwReqData->data.pointer, prIwReqData->data.length)) + return -EFAULT; + + Subcmd = CmdStringDecParse(prIwReqData->data.pointer, &InBuf, &InBufLen); + DBGLOG(REQ, INFO, "priv_set_string> command = %u\n", (UINT32) Subcmd); + + /* handle the command */ + switch (Subcmd) { +#if (CFG_SUPPORT_TDLS == 1) + case PRIV_CMD_OTHER_TDLS: + TdlsexCmd(GlueInfo, InBuf, InBufLen); + break; +#endif /* CFG_SUPPORT_TDLS */ + +#if (CFG_SUPPORT_TXR_ENC == 1) + case PRIV_CMD_OTHER_TAR: + { + rlmCmd(GlueInfo, InBuf, InBufLen); + break; + } +#endif /* CFG_SUPPORT_TXR_ENC */ + default: + break; + } + + return Status; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to search desired OID. +* +* \param rOid[in] Desired NDIS_OID +* \param ppWlanReqEntry[out] Found registered OID entry +* +* \retval TRUE: Matched OID is found +* \retval FALSE: No matched OID is found +*/ +/*----------------------------------------------------------------------------*/ +static BOOLEAN reqSearchSupportedOidEntry(IN UINT_32 rOid, OUT P_WLAN_REQ_ENTRY *ppWlanReqEntry) +{ + INT_32 i, j, k; + + i = 0; + j = NUM_SUPPORTED_OIDS - 1; + + while (i <= j) { + k = (i + j) / 2; + + if (rOid == arWlanOidReqTable[k].rOid) { + *ppWlanReqEntry = &arWlanOidReqTable[k]; + return TRUE; + } else if (rOid < arWlanOidReqTable[k].rOid) { + j = k - 1; + } else { + i = k + 1; + } + } + + return FALSE; +} /* reqSearchSupportedOidEntry */ + +#if 0 +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to query the radio configuration used in IBSS +* mode and RF test mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[out] pvQueryBuffer Pointer to the buffer that holds the result of the query. +* \param[in] u4QueryBufferLen The length of the query buffer. +* \param[out] pu4QueryInfoLen If the call is successful, returns the number of +* bytes written into the query buffer. If the call +* failed due to invalid length of the query buffer, +* returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtQueryConfiguration(IN P_GLUE_INFO_T prGlueInfo, + OUT PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen) +{ + P_PARAM_802_11_CONFIG_T prQueryConfig = (P_PARAM_802_11_CONFIG_T) pvQueryBuffer; + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + UINT_32 u4QueryInfoLen = 0; + + DEBUGFUNC("wlanoidQueryConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4QueryInfoLen); + + *pu4QueryInfoLen = sizeof(PARAM_802_11_CONFIG_T); + if (u4QueryBufferLen < sizeof(PARAM_802_11_CONFIG_T)) + return WLAN_STATUS_INVALID_LENGTH; + + ASSERT(pvQueryBuffer); + + kalMemZero(prQueryConfig, sizeof(PARAM_802_11_CONFIG_T)); + + /* Update the current radio configuration. */ + prQueryConfig->u4Length = sizeof(PARAM_802_11_CONFIG_T); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryBeaconInterval, + &prQueryConfig->u4BeaconPeriod, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryAtimWindow, + &prQueryConfig->u4ATIMWindow, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(UINT_32), TRUE, TRUE, &u4QueryInfoLen); +#else + rStatus = wlanQueryInformation(prGlueInfo->prAdapter, + wlanoidQueryFrequency, + &prQueryConfig->u4DSConfig, sizeof(UINT_32), &u4QueryInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + prQueryConfig->rFHConfig.u4Length = sizeof(PARAM_802_11_CONFIG_FH_T); + + return rStatus; + +} /* end of reqExtQueryConfiguration() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set the radio configuration used in IBSS +* mode. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set. +* \param[in] u4SetBufferLen The length of the set buffer. +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed +* due to invalid length of the set buffer, returns +* the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_LENGTH +* \retval WLAN_STATUS_NOT_ACCEPTED +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetConfiguration(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_PARAM_802_11_CONFIG_T prNewConfig = (P_PARAM_802_11_CONFIG_T) pvSetBuffer; + UINT_32 u4SetInfoLen = 0; + + DEBUGFUNC("wlanoidSetConfiguration"); + + ASSERT(prGlueInfo); + ASSERT(pu4SetInfoLen); + + *pu4SetInfoLen = sizeof(PARAM_802_11_CONFIG_T); + + if (u4SetBufferLen < *pu4SetInfoLen) + return WLAN_STATUS_INVALID_LENGTH; + + /* OID_802_11_CONFIGURATION. If associated, NOT_ACCEPTED shall be returned. */ + if (prGlueInfo->eParamMediaStateIndicated == PARAM_MEDIA_STATE_CONNECTED) + return WLAN_STATUS_NOT_ACCEPTED; + + ASSERT(pvSetBuffer); + +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetBeaconInterval, + &prNewConfig->u4BeaconPeriod, sizeof(UINT_32), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetAtimWindow, + &prNewConfig->u4ATIMWindow, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetAtimWindow, &prNewConfig->u4ATIMWindow, sizeof(UINT_32), &u4SetInfoLen); +#endif + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; +#if defined(_HIF_SDIO) + rStatus = sdio_io_ctrl(prGlueInfo, + wlanoidSetFrequency, + &prNewConfig->u4DSConfig, sizeof(UINT_32), FALSE, TRUE, &u4SetInfoLen); +#else + rStatus = wlanSetInformation(prGlueInfo->prAdapter, + wlanoidSetFrequency, &prNewConfig->u4DSConfig, sizeof(UINT_32), &u4SetInfoLen); +#endif + + if (rStatus != WLAN_STATUS_SUCCESS) + return rStatus; + + return rStatus; + +} /* end of reqExtSetConfiguration() */ + +#endif +/*----------------------------------------------------------------------------*/ +/*! +* \brief This routine is called to set beacon detection function enable/disable state +* This is mainly designed for usage under BT inquiry state (disable function). +* +* \param[in] pvAdapter Pointer to the Adapter structure +* \param[in] pvSetBuffer A pointer to the buffer that holds the data to be set +* \param[in] u4SetBufferLen The length of the set buffer +* \param[out] pu4SetInfoLen If the call is successful, returns the number of +* bytes read from the set buffer. If the call failed due to invalid length of +* the set buffer, returns the amount of storage needed. +* +* \retval WLAN_STATUS_SUCCESS +* \retval WLAN_STATUS_INVALID_DATA If new setting value is wrong. +* \retval WLAN_STATUS_INVALID_LENGTH +* +*/ +/*----------------------------------------------------------------------------*/ +static WLAN_STATUS +reqExtSetAcpiDevicePowerState(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvSetBuffer, IN UINT_32 u4SetBufferLen, OUT PUINT_32 pu4SetInfoLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + + ASSERT(prGlueInfo); + ASSERT(pvSetBuffer); + ASSERT(pu4SetInfoLen); + + /* WIFI is enabled, when ACPI is D0 (ParamDeviceStateD0 = 1). And vice versa */ + + /* rStatus = wlanSetInformation(prGlueInfo->prAdapter, */ + /* wlanoidSetAcpiDevicePowerState, */ + /* pvSetBuffer, */ + /* u4SetBufferLen, */ + /* pu4SetInfoLen); */ + return rStatus; +} + +int priv_driver_set_chip_config(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; + P_GLUE_INFO_T prGlueInfo = NULL; + P_ADAPTER_T prAdapter = NULL; + UINT_32 u4BufLen = 0; + INT_32 i4BytesWritten = 0; + UINT_32 u4CmdLen = 0; + UINT_32 u4PrefixLen = 0; + /* INT_32 i4Argc = 0; */ + /* PCHAR apcArgv[WLAN_CFG_ARGV_MAX] = {0}; */ + + PARAM_CUSTOM_CHIP_CONFIG_STRUCT_T rChipConfigInfo; + + ASSERT(prNetDev); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + prAdapter = prGlueInfo->prAdapter; + DBGLOG(REQ, INFO, "priv_driver_set_chip_config command is %s\n", pcCommand); + /* wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); */ + /* DBGLOG(REQ, LOUD,("argc is %i\n",i4Argc)); */ + /* */ + u4CmdLen = kalStrnLen(pcCommand, i4TotalLen); + u4PrefixLen = kalStrLen(CMD_SET_CHIP) + 1 /*space */; + + kalMemZero(&rChipConfigInfo, sizeof(rChipConfigInfo)); + + /* if(i4Argc >= 2) { */ + if (u4CmdLen > u4PrefixLen) { + + rChipConfigInfo.ucType = CHIP_CONFIG_TYPE_WO_RESPONSE; + /* rChipConfigInfo.u2MsgSize = kalStrnLen(apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + rChipConfigInfo.u2MsgSize = u4CmdLen - u4PrefixLen; + /* kalStrnCpy(rChipConfigInfo.aucCmd,apcArgv[1],CHIP_CONFIG_RESP_SIZE); */ + if (u4PrefixLen <= CHIP_CONFIG_RESP_SIZE) { + kalStrnCpy(rChipConfigInfo.aucCmd, pcCommand + u4PrefixLen, + CHIP_CONFIG_RESP_SIZE - u4PrefixLen); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetChipConfig, + &rChipConfigInfo, + sizeof(rChipConfigInfo), FALSE, FALSE, TRUE, TRUE, &u4BufLen); + } else { + + DBGLOG(REQ, INFO, "%s: kalIoctl Command Len > %d\n", __func__, CHIP_CONFIG_RESP_SIZE); + rStatus = WLAN_STATUS_FAILURE; + } + + if (rStatus != WLAN_STATUS_SUCCESS) { + DBGLOG(REQ, INFO, "%s: kalIoctl ret=%d\n", __func__, rStatus); + i4BytesWritten = -1; + } + } + + return i4BytesWritten; + +} + +int priv_driver_set_miracast(IN struct net_device *prNetDev, IN char *pcCommand, IN int i4TotalLen) +{ + P_ADAPTER_T prAdapter = NULL; + P_GLUE_INFO_T prGlueInfo = NULL; + UINT_32 i4BytesWritten = 0; + /* WLAN_STATUS rStatus = WLAN_STATUS_SUCCESS; */ + /* UINT_32 u4BufLen = 0; */ + INT_32 i4Argc = 0; + UINT_32 ucMode = 0; + P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T) NULL; + P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T prMsgWfdCfgUpdate = (P_MSG_WFD_CONFIG_SETTINGS_CHANGED_T) NULL; + PCHAR apcArgv[WLAN_CFG_ARGV_MAX]; + INT_32 u4Ret; + + ASSERT(prNetDev); + if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) + return -1; + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + DBGLOG(REQ, LOUD, "command is %s\n", pcCommand); + wlanCfgParseArgument(pcCommand, &i4Argc, apcArgv); + DBGLOG(REQ, LOUD, "argc is %i\n", i4Argc); + + prAdapter = prGlueInfo->prAdapter; + if (i4Argc >= 2) { + u4Ret = kalkStrtou32(apcArgv[1], 0, &ucMode); /* ucMode = kalStrtoul(apcArgv[1], NULL, 0); */ + if (u4Ret) + DBGLOG(REQ, LOUD, "parse pcCommand error u4Ret=%d\n", u4Ret); + + if (g_ucMiracastMode == ucMode) + ; + /* XXX: continue or skip */ + + g_ucMiracastMode = ucMode; + prMsgWfdCfgUpdate = cnmMemAlloc(prAdapter, RAM_TYPE_MSG, sizeof(MSG_WFD_CONFIG_SETTINGS_CHANGED_T)); + + if (prMsgWfdCfgUpdate != NULL) { + + prWfdCfgSettings = &(prGlueInfo->prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings); + prMsgWfdCfgUpdate->rMsgHdr.eMsgId = MID_MNY_P2P_WFD_CFG_UPDATE; + prMsgWfdCfgUpdate->prWfdCfgSettings = prWfdCfgSettings; + + if (ucMode == MIRACAST_MODE_OFF) { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } else if (ucMode == MIRACAST_MODE_SOURCE) { + prWfdCfgSettings->ucWfdEnable = 1; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 1"); + } else if (ucMode == MIRACAST_MODE_SINK) { + prWfdCfgSettings->ucWfdEnable = 2; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 2"); + } else { + prWfdCfgSettings->ucWfdEnable = 0; + snprintf(pcCommand, i4TotalLen, CMD_SET_CHIP " mira 0"); + } + mboxSendMsg(prAdapter, MBOX_ID_0, (P_MSG_HDR_T) prMsgWfdCfgUpdate, MSG_SEND_METHOD_BUF); + + priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + + } /* prMsgWfdCfgUpdate */ + else { + ASSERT(FALSE); + i4BytesWritten = -1; + } + } + + /* i4Argc */ + return i4BytesWritten; +} + +int priv_support_driver_cmd(IN struct net_device *prNetDev, IN OUT struct ifreq *prReq, IN int i4Cmd) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + int ret = 0; + char *pcCommand = NULL; + priv_driver_cmd_t *priv_cmd = NULL; + int i4BytesWritten = 0; + int i4TotalLen = 0; + + if (!prReq->ifr_data) { + ret = -EINVAL; + goto exit; + } + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (!prGlueInfo) { + DBGLOG(REQ, WARN, "No glue info\n"); + ret = -EFAULT; + goto exit; + } + if (prGlueInfo->u4ReadyFlag == 0) { + ret = -EINVAL; + goto exit; + } + + priv_cmd = kzalloc(sizeof(priv_driver_cmd_t), GFP_KERNEL); + if (!priv_cmd) { + DBGLOG(REQ, WARN, "%s, alloc mem failed\n", __func__); + return -ENOMEM; + } + + if (copy_from_user(priv_cmd, prReq->ifr_data, sizeof(priv_driver_cmd_t))) { + DBGLOG(REQ, INFO, "%s: copy_from_user fail\n", __func__); + ret = -EFAULT; + goto exit; + } + + i4TotalLen = priv_cmd->total_len; + + if (i4TotalLen <= 0) { + ret = -EINVAL; + DBGLOG(REQ, INFO, "%s: i4TotalLen invalid\n", __func__); + goto exit; + } + + pcCommand = priv_cmd->buf; + + DBGLOG(REQ, INFO, "%s: driver cmd \"%s\" on %s\n", __func__, pcCommand, prReq->ifr_name); + + i4BytesWritten = priv_driver_cmds(prNetDev, pcCommand, i4TotalLen); + + if (i4BytesWritten < 0) { + DBGLOG(REQ, INFO, "%s: command %s failed; Written is %d\n", + __func__, pcCommand, i4BytesWritten); + ret = -EFAULT; + } + +exit: + kfree(priv_cmd); + + return ret; +} + +#if CFG_SUPPORT_BATCH_SCAN +#define CMD_BATCH_SET "WLS_BATCHING SET" +#define CMD_BATCH_GET "WLS_BATCHING GET" +#define CMD_BATCH_STOP "WLS_BATCHING STOP" +#endif + +#if CFG_SUPPORT_GET_CH_ENV +#define CMD_CH_ENV_GET "CH_ENV_GET" +#endif + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen) +{ + P_GLUE_INFO_T prGlueInfo = NULL; + INT_32 i4BytesWritten = 0; + INT_32 i4CmdFound = 0; + + if (FALSE == GLUE_CHK_PR2(prNetDev, pcCommand)) + return -1; + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDev)); + + if (i4CmdFound == 0) { + i4CmdFound = 1; + + if (strnicmp(pcCommand, CMD_MIRACAST, strlen(CMD_MIRACAST)) == 0) + i4BytesWritten = priv_driver_set_miracast(prNetDev, pcCommand, i4TotalLen); +#if CFG_SUPPORT_BATCH_SCAN + else if (strnicmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, FALSE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, + i4BytesWritten, TRUE); */ + + } else if (strnicmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, FALSE, &i4BytesWritten); + } +#endif +#if CFG_SUPPORT_GET_CH_ENV + else if (strnicmp(pcCommand, CMD_CH_ENV_GET, strlen(CMD_CH_ENV_GET)) == 0) + scanEnvResult(prGlueInfo, pcCommand, i4TotalLen, &i4BytesWritten); +#endif + +#if 0 + + else if (strnicmp(pcCommand, CMD_RSSI, strlen(CMD_RSSI)) == 0) { + /* i4BytesWritten = wl_android_get_rssi(net, command, i4TotalLen); */ + } else if (strnicmp(pcCommand, CMD_LINKSPEED, strlen(CMD_LINKSPEED)) == 0) { + i4BytesWritten = priv_driver_get_linkspeed(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { + /* Do nothing */ + } else if (strnicmp(pcCommand, CMD_PNOSETUP_SET, strlen(CMD_PNOSETUP_SET)) == 0) { + /* Do nothing */ + } else if (strnicmp(pcCommand, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) { + /* Do nothing */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { + /* i4BytesWritten = wl_android_set_suspendopt(net, pcCommand, i4TotalLen); */ + } else if (strnicmp(pcCommand, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + i4BytesWritten = priv_driver_set_suspend_mode(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { + i4BytesWritten = priv_driver_set_band(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { + /* i4BytesWritten = wl_android_get_band(net, pcCommand, i4TotalLen); */ + } else if (strnicmp(pcCommand, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) { + i4BytesWritten = priv_driver_set_country(prNetDev, pcCommand, i4TotalLen); + } + /* Mediatek private command */ + else if (strnicmp(pcCommand, CMD_SET_SW_CTRL, strlen(CMD_SET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_set_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_SW_CTRL, strlen(CMD_GET_SW_CTRL)) == 0) { + i4BytesWritten = priv_driver_get_sw_ctrl(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_CFG, strlen(CMD_SET_CFG)) == 0) { + i4BytesWritten = priv_driver_set_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CFG, strlen(CMD_GET_CFG)) == 0) { + i4BytesWritten = priv_driver_get_cfg(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_CHIP, strlen(CMD_SET_CHIP)) == 0) { + i4BytesWritten = priv_driver_set_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_CHIP, strlen(CMD_GET_CHIP)) == 0) { + i4BytesWritten = priv_driver_get_chip_config(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_SET_DBG_LEVEL, strlen(CMD_SET_DBG_LEVEL)) == 0) { + i4BytesWritten = priv_driver_set_dbg_level(prNetDev, pcCommand, i4TotalLen); + } else if (strnicmp(pcCommand, CMD_GET_DBG_LEVEL, strlen(CMD_GET_DBG_LEVEL)) == 0) { + i4BytesWritten = priv_driver_get_dbg_level(prNetDev, pcCommand, i4TotalLen); + } +#if CFG_SUPPORT_BATCH_SCAN + else if (strnicmp(pcCommand, CMD_BATCH_SET, strlen(CMD_BATCH_SET)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } else if (strnicmp(pcCommand, CMD_BATCH_GET, strlen(CMD_BATCH_GET)) == 0) { + /* strcpy(pcCommand, "BATCH SCAN DATA FROM FIRMWARE"); */ + /* i4BytesWritten = strlen("BATCH SCAN DATA FROM FIRMWARE") + 1; */ + /* i4BytesWritten = priv_driver_get_linkspeed (prNetDev, pcCommand, i4TotalLen); */ + + UINT_32 u4BufLen; + int i; + /* int rlen=0; */ + + for (i = 0; i < CFG_BATCH_MAX_MSCAN; i++) { + g_rEventBatchResult[i].ucScanCount = i + 1; /* for get which mscan */ + kalIoctl(prGlueInfo, + wlanoidQueryBatchScanResult, + (PVOID)&g_rEventBatchResult[i], + sizeof(EVENT_BATCH_RESULT_T), TRUE, TRUE, TRUE, &u4BufLen); + } + +#if 0 + DBGLOG(SCN, INFO, "Batch Scan Results, scan count = %u\n", g_rEventBatchResult.ucScanCount); + for (i = 0; i < g_rEventBatchResult.ucScanCount; i++) { + prEntry = &g_rEventBatchResult.arBatchResult[i]; + DBGLOG(SCN, INFO, "Entry %u\n", i); + DBGLOG(SCN, INFO, " BSSID = %pM\n", prEntry->aucBssid); + DBGLOG(SCN, INFO, " SSID = %s\n", prEntry->aucSSID); + DBGLOG(SCN, INFO, " SSID len = %u\n", prEntry->ucSSIDLen); + DBGLOG(SCN, INFO, " RSSI = %d\n", prEntry->cRssi); + DBGLOG(SCN, INFO, " Freq = %u\n", prEntry->ucFreq); + } +#endif + + batchConvertResult(&g_rEventBatchResult[0], pcCommand, i4TotalLen, &i4BytesWritten); + + /* Dump for debug */ + /* print_hex_dump(KERN_INFO, "BATCH", DUMP_PREFIX_ADDRESS, 16, 1, pcCommand, i4BytesWritten, + TRUE); */ + + } else if (strnicmp(pcCommand, CMD_BATCH_STOP, strlen(CMD_BATCH_STOP)) == 0) { + kalIoctl(prGlueInfo, + wlanoidSetBatchScanReq, + (PVOID) pcCommand, i4TotalLen, FALSE, FALSE, TRUE, &i4BytesWritten); + } +#endif + +#endif + + else + i4CmdFound = 0; + } + + /* i4CmdFound */ + if (i4CmdFound == 0) + DBGLOG(REQ, TRACE, "Unknown driver command %s - ignored\n", pcCommand); + + if (i4BytesWritten >= 0) { + if ((i4BytesWritten == 0) && (i4TotalLen > 0)) { + /* reset the command buffer */ + pcCommand[0] = '\0'; + } + + if (i4BytesWritten >= i4TotalLen) { + DBGLOG(REQ, INFO, + "%s: i4BytesWritten %d > i4TotalLen < %d\n", __func__, i4BytesWritten, i4TotalLen); + i4BytesWritten = i4TotalLen; + } else { + pcCommand[i4BytesWritten] = '\0'; + i4BytesWritten++; + } + } + + return i4BytesWritten; + +} + +static int compat_priv(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra, + int (*priv_func)(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra)) +{ + struct iw_point *prIwp; + int ret = 0; +#ifdef CONFIG_COMPAT + struct compat_iw_point *iwp_compat = NULL; + struct iw_point iwp; +#endif + + if (!prIwReqData) + return -EINVAL; + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat = (struct compat_iw_point *) &prIwReqData->data; + iwp.pointer = compat_ptr(iwp_compat->pointer); + iwp.length = iwp_compat->length; + iwp.flags = iwp_compat->flags; + prIwp = &iwp; + } else +#endif + prIwp = &prIwReqData->data; + + + ret = priv_func(prNetDev, prIwReqInfo, (union iwreq_data *)prIwp, pcExtra); + +#ifdef CONFIG_COMPAT + if (prIwReqInfo->flags & IW_REQUEST_FLAG_COMPAT) { + iwp_compat->pointer = ptr_to_compat(iwp.pointer); + iwp_compat->length = iwp.length; + iwp_compat->flags = iwp.flags; + } +#endif + return ret; +} + +int +priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_int); +} + +int +priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_int); +} + +int +priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_ints); +} + +int +priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_ints); +} + +int +priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_struct); +} + +int +priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_get_struct); +} + +int +priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra) +{ + return compat_priv(prNetDev, prIwReqInfo, prIwReqData, pcExtra, _priv_set_string); +} + diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c new file mode 100644 index 0000000000000..c13d24906bf88 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/ahb.c @@ -0,0 +1,1643 @@ +/****************************************************************************** +*[File] ahb.c +*[Version] v1.0 +*[Revision Date] 2013-01-16 +*[Author] +*[Description] +* The program provides AHB HIF driver +*[Copyright] +* Copyright (C) 2013 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/* +** Log: ahb.c + * + * 01 16 2013 vend_samp.lin + * Port sdio.c to ahb.c on MT6572/MT6582 + * 1) Initial version + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + * + * 02 14 2012 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * include correct header file upon setting. + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 09 20 2011 cp.wu + * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized + * 1. always show error message for SDIO bus errors. + * 2. reset bus error flag when re-initialization + * + * 08 17 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * add MT6628 related definitions for Linux/Android driver. + * + * 05 18 2011 cp.wu + * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC + * add device ID for MT5931. + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 18 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK. + * + * 03 15 2011 cp.wu + * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous + * memory consumption + * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK + * 2. Use common coalescing buffer for both TX/RX directions + * + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 11 15 2010 jeffrey.chang + * [WCXRP00000181] [MT6620 Wi-Fi][Driver] fix the driver message "GLUE_FLAG_HALT skip INT" during unloading + * Fix GLUE_FALG_HALT message which cause driver to hang + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * correct typo + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add code to run WlanIST in SDIO callback. + * + * 10 19 2010 cp.wu + * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration + * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time. + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK + * HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 08 21 2010 jeffrey.chang + * NULL + * 1) add sdio two setting + * 2) bug fix of sdio glue + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 18 2010 cp.wu + * NULL + * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86. + * + * 08 17 2010 cp.wu + * NULL + * add ENE SDIO host workaround for x86 linux platform. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Fix hotplug bug + * + * 03 28 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * clear sdio interrupt + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +/* #include */ +#include +/* #include */ +#include +/* #include */ +/* #include */ +/* #include */ + +#include +#ifndef CONFIG_X86 +#include +#endif + +#ifdef CONFIG_OF +#include +#include +#include +#else + +#endif + +/* #include +#include */ + +#include "gl_os.h" + +#if defined(MT6620) +#include "mt6620_reg.h" +#elif defined(MT6628) +#include "mtreg.h" +#endif + +#if !defined(CONFIG_MTK_CLKMGR) +#include +#endif + +/* #define MTK_DMA_BUF_MEMCPY_SUP */ /* no virt_to_phys() use */ +/* #define HIF_DEBUG_SUP */ +/* #define HIF_DEBUG_SUP_TX */ + +#ifdef HIF_DEBUG_SUP +#define HIF_DBG(msg) (printk msg) +#else +#define HIF_DBG(msg) +#endif /* HIF_DEBUG_SUP */ + +#ifdef HIF_DEBUG_SUP_TX +#define HIF_DBG_TX(msg) (printk msg) +#else +#define HIF_DBG_TX(msg) +#endif /* HIF_DEBUG_SUP */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +static UINT_32 +HifAhbDmaEnhanceModeConf(IN GLUE_INFO_T *GlueInfo, IN UINT_32 BurstLen, IN UINT_32 PortId, IN UINT_32 TransByte); + +static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg); + +static int HifAhbProbe(VOID); + +static int HifAhbRemove(VOID); + +#if (MTK_WCN_SINGLE_MODULE == 0) +static int HifAhbBusCntGet(VOID); + +static int HifAhbBusCntClr(VOID); + +static int HifTxCnt; +#endif /* MTK_WCN_SINGLE_MODULE */ + +#if (CONF_HIF_DEV_MISC == 1) +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos); + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos); + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg); + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp); + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp); +#else + +static int HifAhbPltmProbe(IN struct platform_device *PDev); + +static int __exit HifAhbPltmRemove(IN struct platform_device *PDev); + +#ifdef CONFIG_PM +static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message); + +static int HifAhbPltmResume(IN struct platform_device *PDev); +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ +static VOID HifAhbLoopbkAuto(IN unsigned long arg); +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) +static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg); +#endif /* CONF_HIF_DMA_INT */ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/* initialiation function from other module */ +static probe_card pfWlanProbe; + +/* release function from other module */ +static remove_card pfWlanRemove; + +static BOOLEAN WlanDmaFatalErr; + +#if (CONF_HIF_DEV_MISC == 1) +static const struct file_operations MtkAhbOps = { + .owner = THIS_MODULE, + .read = HifAhbMiscRead, + .write = HifAhbMiscWrite, + .unlocked_ioctl = HifAhbMiscIoctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = HifAhbMiscIoctl, +#endif + .open = HifAhbMiscOpen, + .release = HifAhbMiscClose, +}; + +static struct miscdevice MtkAhbDriver = { + .minor = MISC_DYNAMIC_MINOR, /* any minor number */ + .name = HIF_MOD_NAME, + .fops = &MtkAhbOps, +}; +#else + +#ifdef CONFIG_OF +static const struct of_device_id apwifi_of_ids[] = { + {.compatible = "mediatek,wifi", .data = (void *)0}, + {.compatible = "mediatek,mt7623-wifi", .data = (void *)0x7623}, + {} +}; +#endif + +struct platform_driver MtkPltmAhbDriver = { + .driver = { + .name = "mt-wifi", + .owner = THIS_MODULE, +#ifdef CONFIG_OF + .of_match_table = apwifi_of_ids, +#endif + }, + .probe = HifAhbPltmProbe, +#ifdef CONFIG_PM + .suspend = HifAhbPltmSuspend, + .resume = HifAhbPltmResume, +#else + .suspend = NULL, + .resume = NULL, +#endif /* CONFIG_PM */ + .remove = __exit_p(HifAhbPltmRemove), +}; + +static struct platform_device *HifAhbPDev; + +#endif /* CONF_HIF_DEV_MISC */ + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will register sdio bus to the os +* +* \param[in] pfProbe Function pointer to detect card +* \param[in] pfRemove Function pointer to remove card +* +* \return The result of registering HIF driver (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove) +{ + WLAN_STATUS Ret; + + ASSERT(pfProbe); + ASSERT(pfRemove); + + pfWlanProbe = pfProbe; /* wlan card initialization in other modules = wlanProbe() */ + pfWlanRemove = pfRemove; + +#if (CONF_HIF_DEV_MISC == 1) + Ret = misc_register(&MtkAhbDriver); + if (Ret != 0) + return Ret; + HifAhbProbe(); +#else + Ret = platform_driver_register(&MtkPltmAhbDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return Ret; + +} /* end of glRegisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will unregister sdio bus to the os +* +* \param[in] pfRemove Function pointer to remove card +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glUnregisterBus(remove_card pfRemove) +{ + ASSERT(pfRemove); + + pfRemove(); + +#if (CONF_HIF_DEV_MISC == 1) + HifAhbRemove(); + + if ((misc_deregister(&MtkAhbDriver)) != 0) + ; +#else + + platform_driver_unregister(&MtkPltmAhbDriver); +#endif /* CONF_HIF_DEV_MISC */ + + return; + +} /* end of glUnregisterBus() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will inform us whole chip reset start event. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glResetHif(GLUE_INFO_T *GlueInfo) +{ + GL_HIF_INFO_T *HifInfo; + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + if (HifInfo->DmaOps) + HifInfo->DmaOps->DmaReset(HifInfo); +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function stores hif related info, which is initialized before. +* +* \param[in] GlueInfo Pointer to glue info structure +* \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glSetHifInfo(GLUE_INFO_T *GlueInfo, ULONG ulCookie) +{ + GL_HIF_INFO_T *HifInfo; + const struct of_device_id *of_id; + + /* Init HIF */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; +#if (CONF_HIF_DEV_MISC == 1) + HifInfo->Dev = MtkAhbDriver.this_device; +#else + HifInfo->Dev = &HifAhbPDev->dev; +#endif /* CONF_HIF_DEV_MISC */ + SET_NETDEV_DEV(GlueInfo->prDevHandler, HifInfo->Dev); + + HifInfo->HifRegBaseAddr = ioremap(HIF_DRV_BASE, HIF_DRV_LENGTH); + HifInfo->McuRegBaseAddr = ioremap(CONN_MCU_DRV_BASE, CONN_MCU_REG_LENGTH); + DBGLOG(INIT, INFO, "[WiFi/HIF]HifInfo->HifRegBaseAddr=0x%p, HifInfo->McuRegBaseAddr=0x%p\n", + HifInfo->HifRegBaseAddr, HifInfo->McuRegBaseAddr); + + /* default disable DMA */ + HifInfo->fgDmaEnable = FALSE; + HifInfo->DmaRegBaseAddr = 0; + HifInfo->DmaOps = NULL; + of_id = of_match_node(apwifi_of_ids, HifAhbPDev->dev.of_node); + if (of_id && of_id->data) { + HifInfo->ChipID = (UINT_32)(unsigned long)of_id->data; + } else { + /* read chip ID */ + HifInfo->ChipID = HIF_REG_READL(HifInfo, MCR_WCIR) & 0xFFFF; + if (HifInfo->ChipID == 0x0321 || HifInfo->ChipID == 0x0335 || HifInfo->ChipID == 0x0337) + HifInfo->ChipID = 0x6735; /* Denali ChipID transition */ + if (HifInfo->ChipID == 0x0326) + HifInfo->ChipID = 0x6755; + } + DBGLOG(INIT, INFO, "[WiFi/HIF] ChipID = 0x%x\n", HifInfo->ChipID); +#ifdef CONFIG_OF +#if !defined(CONFIG_MTK_CLKMGR) + HifInfo->clk_wifi_dma = devm_clk_get(&HifAhbPDev->dev, "wifi-dma"); + if (IS_ERR(HifInfo->clk_wifi_dma)) + DBGLOG(INIT, ERROR, "[WiFi/HIF][CCF]cannot get HIF clk_wifi_dma clock.\n"); + DBGLOG(INIT, TRACE, "[WiFi/HIF][CCF]HIF clk_wifi_dma=0x%p\n", HifInfo->clk_wifi_dma); +#endif +#endif + + /* Init DMA */ + WlanDmaFatalErr = 0; /* reset error flag */ + +#if (CONF_MTK_AHB_DMA == 1) + spin_lock_init(&HifInfo->DdmaLock); + + HifPdmaInit(HifInfo); +#endif /* CONF_MTK_AHB_DMA */ + + /* Start loopback test after 10 seconds */ +#if (CONF_HIF_LOOPBACK_AUTO == 1) /* only for development test */ + { + init_timer(&(HifInfo->HifTmrLoopbkFn)); + HifInfo->HifTmrLoopbkFn.function = HifAhbLoopbkAuto; + HifInfo->HifTmrLoopbkFn.data = (unsigned long)GlueInfo; + + init_waitqueue_head(&HifInfo->HifWaitq); + HifInfo->HifTaskLoopbkFn = kthread_run(kalDevLoopbkThread, GlueInfo->prDevHandler, "LoopbkThread"); + HifInfo->HifLoopbkFlg = 0; + + /* Note: in FPGA, clock is not accuracy so 3000 here, not 10000 */ + HifInfo->HifTmrLoopbkFn.expires = jiffies + MSEC_TO_SYSTIME(30000); + add_timer(&(HifInfo->HifTmrLoopbkFn)); + + HIF_DBG(("[WiFi/HIF] Start loopback test after 10 seconds (jiffies = %u)...\n", jiffies)); + } +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) + init_waitqueue_head(&HifInfo->HifDmaWaitq); + HifInfo->HifDmaWaitFlg = 0; +#endif /* CONF_HIF_DMA_INT */ + +} /* end of glSetHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glClearHifInfo(GLUE_INFO_T *GlueInfo) +{ + iounmap(GlueInfo->rHifInfo.HifRegBaseAddr); + iounmap(GlueInfo->rHifInfo.DmaRegBaseAddr); + iounmap(GlueInfo->rHifInfo.McuRegBaseAddr); + return; + +} /* end of glClearHifInfo() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function clears hif related info. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf) +{ + GL_HIF_INFO_T *HifInfo; + + HifInfo = &GlueInfo->rHifInfo; + DBGLOG(INIT, TRACE, "glGetChipInfo ChipID = 0x%x\n", HifInfo->ChipID); + switch (HifInfo->ChipID) { + case MTK_CHIP_ID_6571: + case MTK_CHIP_ID_8127: + case MTK_CHIP_ID_6752: + case MTK_CHIP_ID_8163: + case MTK_CHIP_ID_6735: + case MTK_CHIP_ID_6580: + case MTK_CHIP_ID_6755: + case MTK_CHIP_ID_7623: + kalSprintf(pucChipBuf, "%04x", HifInfo->ChipID); + break; + default: + kalMemCopy(pucChipBuf, "SOC", strlen("SOC")); + } +} /* end of glGetChipInfo() */ + +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function to check if we need wakelock under Hotspot mode. +* +* \param[in] GlueInfo Pointer to glue info structure +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo) +{ + GL_HIF_INFO_T *HifInfo; + + HifInfo = &GlueInfo->rHifInfo; + if (HifInfo->ChipID == MTK_CHIP_ID_6572 || HifInfo->ChipID == MTK_CHIP_ID_6582) + return TRUE; + else + return FALSE; +} /* end of glIsChipNeedWakelock() */ +#endif /* CFG_SPM_WORKAROUND_FOR_HOTSPOT */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Initialize bus operation and hif related information, request resources. +* +* \param[out] pvData A pointer to HIF-specific data type buffer. +* For eHPI, pvData is a pointer to UINT_32 type and stores a +* mapped base address. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN glBusInit(PVOID pvData) +{ + return TRUE; +} /* end of glBusInit() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus operation and release resources. +* +* \param[in] pvData A pointer to struct net_device. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusRelease(PVOID pvData) +{ +} /* end of glBusRelease() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Setup bus interrupt operation and interrupt handler for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pfnIsr A pointer to interrupt handler function. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \retval WLAN_STATUS_SUCCESS if success +* NEGATIVE_VALUE if fail +*/ +/*----------------------------------------------------------------------------*/ +#ifdef CONFIG_OF +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = { 0, 0, 0 }; + /* unsigned int phy_base; */ + unsigned int irq_id = 0; + unsigned int irq_flags = 0; + + struct net_device *prNetDevice; + + ASSERT(pvData); + if (!pvData) + return -1; + prNetDevice = (struct net_device *)pvData; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) { + irq_id = irq_of_parse_and_map(node, 0); + DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); + } else { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + } + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); + } else { + irq_flags = irq_info[2]; + DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); + } + + /* Register AHB IRQ */ + if (request_irq(irq_id, HifAhbISR, irq_flags, HIF_MOD_NAME, prNetDevice)) { + DBGLOG(INIT, ERROR, "WIFI-OF: request irq %d fail!\n", irq_id); + return -1; + } + + return 0; +} + +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct device_node *node = NULL; + unsigned int irq_info[3] = { 0, 0, 0 }; + /* unsigned int phy_base; */ + unsigned int irq_id = 0; + unsigned int irq_flags = 0; + + struct net_device *prNetDevice; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return; + prNetDevice = (struct net_device *)pvData; + + node = of_find_compatible_node(NULL, NULL, "mediatek,wifi"); + if (node) { + irq_id = irq_of_parse_and_map(node, 0); + DBGLOG(INIT, INFO, "WIFI-OF: get wifi irq(%d)\n", irq_id); + } else { + DBGLOG(INIT, ERROR, "WIFI-OF: get wifi device node fail\n"); + } + + /* get the interrupt line behaviour */ + if (of_property_read_u32_array(node, "interrupts", irq_info, ARRAY_SIZE(irq_info))) { + DBGLOG(INIT, ERROR, "WIFI-OF: get interrupt flag from DTS fail\n"); + } else { + irq_flags = irq_info[2]; + DBGLOG(INIT, LOUD, "WIFI-OF: get interrupt flag(0x%x)\n", irq_flags); + } + + /* Free the IRQ */ + free_irq(irq_id, prNetDevice); + return; + +} +#else +/* the name is different in 72 and 82 */ +#ifndef MT_WF_HIF_IRQ_ID /* for MT6572/82/92 */ +#define MT_WF_HIF_IRQ_ID WF_HIF_IRQ_ID +#endif /* MT_WF_HIF_IRQ_ID */ + +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie) +{ + int ret = 0; + struct net_device *prNetDevice; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return -1; + + prNetDevice = (struct net_device *)pvData; + GlueInfo = (GLUE_INFO_T *) pvCookie; + ASSERT(GlueInfo); + if (!GlueInfo) { + DBGLOG(INIT, ERROR, "GlueInfo == NULL!\n"); + return -1; + } + + HifInfo = &GlueInfo->rHifInfo; + + /* Register AHB IRQ */ + if (request_irq(MT_WF_HIF_IRQ_ID, HifAhbISR, IRQF_TRIGGER_LOW, HIF_MOD_NAME, prNetDevice)) { + DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_WF_HIF_IRQ_ID); + return -1; + } +#if (CONF_HIF_DMA_INT == 1) + if (request_irq(MT_GDMA2_IRQ_ID, HifDmaISR, IRQF_TRIGGER_LOW, "AHB_DMA", prNetDevice)) { + DBGLOG(INIT, ERROR, "request irq %d fail!\n", MT_GDMA2_IRQ_ID); + free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); + return -1; + } +#endif /* CONF_HIF_DMA_INT */ + + return ret; + +} /* end of glBusSetIrq() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop bus interrupt operation and disable interrupt handling for os. +* +* \param[in] pvData A pointer to struct net_device. +* \param[in] pvCookie Private data for pfnIsr function. +* +* \return (none) +*/ +/*----------------------------------------------------------------------------*/ +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie) +{ + struct net_device *prNetDevice; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(pvData); + if (!pvData) + return; + + prNetDevice = (struct net_device *)pvData; + GlueInfo = (GLUE_INFO_T *) pvCookie; + ASSERT(GlueInfo); + if (!GlueInfo) + return; + + HifInfo = &GlueInfo->rHifInfo; + + /* Free the IRQ */ + free_irq(MT_WF_HIF_IRQ_ID, prNetDevice); + return; + +} /* end of glBusreeIrq() */ +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] pu4Value Pointer to variable used to store read value +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegRead(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, OUT UINT_32 *pu4Value) +{ + GL_HIF_INFO_T *HifInfo; + + /* sanity check and init */ + ASSERT(GlueInfo); + ASSERT(pu4Value); + HifInfo = &GlueInfo->rHifInfo; + + /* use PIO mode to read register */ + if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) + return FALSE; + *pu4Value = HIF_REG_READL(HifInfo, RegOffset); + + if ((RegOffset == MCR_WRDR0) || (RegOffset == MCR_WRDR1)) + HIF_DBG(("[WiFi/HIF] kalDevRegRead from Data Port 0 or 1\n")); + + return TRUE; + +} /* end of kalDevRegRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write a 32-bit device register +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] RegOffset Register offset +* \param[in] RegValue RegValue to be written +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegWrite(IN GLUE_INFO_T *GlueInfo, IN UINT_32 RegOffset, IN UINT_32 RegValue) +{ + GL_HIF_INFO_T *HifInfo; + + /* sanity check and init */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + /* use PIO mode to write register */ + if (WlanDmaFatalErr && RegOffset != MCR_WCIR && RegOffset != MCR_WHLPCR) + return FALSE; + HIF_REG_WRITEL(HifInfo, RegOffset, RegValue); + + if ((RegOffset == MCR_WTDR0) || (RegOffset == MCR_WTDR1)) + HIF_DBG(("[WiFi/HIF] kalDevRegWrite to Data Port 0 or 1\n")); + + return TRUE; + +} /* end of kalDevRegWrite() */ + + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Read device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be read +* \param[out] Buf Pointer to read buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortRead(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, OUT PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 u4HSTCRValue = 0; + UINT_32 RegWHLPCR = 0; + + /* sanity check */ + if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { + DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", + WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); + return FALSE; + } + /* Init */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + /* Note: burst length should be equal to the one used in DMA */ + if (Port == MCR_WRDR0) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD0, Size); + else if (Port == MCR_WRDR1) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_RXD1, Size); + else if (Port == MCR_WHISR) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_WHISR, Size); + + RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* Read */ +#if (CONF_MTK_AHB_DMA == 1) + if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) + && ((Port == MCR_WRDR0) || (Port == MCR_WRDR1))) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; + MTK_WCN_HIF_DMA_CONF DmaConf; + UINT_32 LoopCnt; + unsigned long PollTimeout; +#if (CONF_HIF_DMA_INT == 1) + INT_32 RtnVal = 0; +#endif + /* config DMA, Port = MCR_WRDR0 or MCR_WRDR1 */ + DmaConf.Count = Size; + DmaConf.Dir = HIF_DMA_DIR_RX; + DmaConf.Src = HIF_DRV_BASE + Port; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Dst = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Dst == NULL) { + HIF_DBG(("[WiFi/HIF] Use Dma Buffer to RX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); + ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); + + kalDmaBufGet(&DmaVBuf, &DmaPBuf); + DmaConf.Dst = (ULONG) DmaPBuf; + } +#else + /* + http://kernelnewbies.org/KernelMemoryAllocation + Since the cache-coherent mapping may be expensive, also a streaming allocation exists. + + This is a buffer for one-way communication, which means coherency is limited to + flushing the data from the cache after a write finishes. The buffer has to be + pre-allocated (e.g. using kmalloc()). DMA for it is set up with dma_map_single(). + + When the DMA is finished (e.g. when the device has sent an interrupt signaling end of + DMA), call dma_unmap_single(). Between map and unmap, the device is in control of the + buffer: if you write to the device, do it before dma_map_single(), if you read from + it, do it after dma_unmap_single(). + */ + /* DMA_FROM_DEVICE invalidated (without writeback) the cache */ + /* TODO: if dst_off was not cacheline aligned */ + DmaConf.Dst = dma_map_single(HifInfo->Dev, Buf, Size, DMA_FROM_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* start to read data */ + AP_DMA_HIF_LOCK(HifInfo); /* lock to avoid other codes config GDMA */ + + prDmaOps->DmaClockCtrl(TRUE); + prDmaOps->DmaConfig(HifInfo, &DmaConf); + prDmaOps->DmaStart(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); + if (RtnVal <= 0) + DBGLOG(RX, ERROR, "fatal error1! reset DMA!\n"); + HifInfo->HifDmaWaitFlg = 0; +#else + PollTimeout = jiffies + HZ * 5; + + do { + if (time_before(jiffies, PollTimeout)) + continue; + DBGLOG(RX, INFO, "RX DMA Timeout, HSTCR: 0x%08x, and dump WHISR EnhanceMode data\n", + u4HSTCRValue); + HifDumpEnhanceModeData(GlueInfo->prAdapter); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); +#endif /* CONF_HIF_DMA_INT */ + /* we should disable dma interrupt then clear dma interrupt, otherwise, + for dma timeout case, interrupt may be set after we clear it */ + prDmaOps->DmaStop(HifInfo); + prDmaOps->DmaAckIntr(HifInfo); + + LoopCnt = 0; + do { + if (LoopCnt++ > 100000) { + /* TODO: impossible! reset DMA */ + DBGLOG(RX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + + prDmaOps->DmaClockCtrl(FALSE); + + AP_DMA_HIF_UNLOCK(HifInfo); + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + if (DmaVBuf != NULL) + kalMemCopy(Buf, DmaVBuf, Size); +#else + dma_unmap_single(HifInfo->Dev, DmaConf.Dst, Size, DMA_FROM_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (WlanDmaFatalErr) { + if (!fgIsResetting) + glDoChipReset(); + return FALSE; + } + HIF_DBG(("[WiFi/HIF] DMA RX OK!\n")); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + UINT_32 IdLoop, MaxLoop; + UINT_32 *LoopBuf; + + /* default PIO mode */ + MaxLoop = Size >> 2; + if (Size & 0x3) + MaxLoop++; + LoopBuf = (UINT_32 *) Buf; + + for (IdLoop = 0; IdLoop < MaxLoop; IdLoop++) { + + *LoopBuf = HIF_REG_READL(HifInfo, Port); + LoopBuf++; + } + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + } + + return TRUE; + +} /* end of kalDevPortRead() */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Write device I/O port +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Port I/O port offset +* \param[in] Size Length to be write +* \param[in] Buf Pointer to write buffer +* \param[in] MaxBufSize Length of the buffer valid to be accessed +* +* \retval TRUE operation success +* \retval FALSE operation fail +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN +kalDevPortWrite(IN P_GLUE_INFO_T GlueInfo, IN UINT_16 Port, IN UINT_32 Size, IN PUINT_8 Buf, IN UINT_32 MaxBufSize) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 u4HSTCRValue = 0; + UINT_32 RegWHLPCR = 0; + + /* sanity check */ + if ((WlanDmaFatalErr == 1) || (fgIsResetting == TRUE) || (HifIsFwOwn(GlueInfo->prAdapter) == TRUE)) { + DBGLOG(RX, ERROR, "WlanDmaFatalErr: %d, fgIsResetting: %d, HifIsFwOwn: %d\n", + WlanDmaFatalErr, fgIsResetting, HifIsFwOwn(GlueInfo->prAdapter)); + return FALSE; + } + + /* Init */ + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + ASSERT(Buf); + ASSERT(Size <= MaxBufSize); + + HifTxCnt++; + + /* Note: burst length should be equal to the one used in DMA */ + if (Port == MCR_WTDR0) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD0, Size); + else if (Port == MCR_WTDR1) + u4HSTCRValue = HifAhbDmaEnhanceModeConf(GlueInfo, HIF_BURST_4DW, HIF_TARGET_TXD1, Size); + /* else other non-data port */ + + RegWHLPCR = HIF_REG_READL(HifInfo, MCR_WHLPCR); + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* Write */ +#if (CONF_MTK_AHB_DMA == 1) + if ((HifInfo->fgDmaEnable == TRUE) && (HifInfo->DmaOps != NULL) && ((Port == MCR_WTDR0) || + (Port == MCR_WTDR1))) { + /* only for data port */ +#ifdef MTK_DMA_BUF_MEMCPY_SUP + VOID *DmaVBuf = NULL, *DmaPBuf = NULL; +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + GL_HIF_DMA_OPS_T *prDmaOps = HifInfo->DmaOps; + MTK_WCN_HIF_DMA_CONF DmaConf; + UINT_32 LoopCnt; + unsigned long PollTimeout; +#if (CONF_HIF_DMA_INT == 1) + INT_32 RtnVal = 0; +#endif + + /* config GDMA */ + HIF_DBG_TX(("[WiFi/HIF/DMA] Prepare to send data...\n")); + DmaConf.Count = Size; + DmaConf.Dir = HIF_DMA_DIR_TX; + DmaConf.Dst = HIF_DRV_BASE + Port; /* must be physical addr */ + +#ifdef MTK_DMA_BUF_MEMCPY_SUP + DmaConf.Src = kalIOPhyAddrGet(Buf); /* must be physical addr */ + + /* TODO: use virt_to_phys() */ + if (DmaConf.Src == NULL) { + HIF_DBG_TX(("[WiFi/HIF] Use Dma Buffer to TX packet (%d %d)...\n", Size, CFG_RX_MAX_PKT_SIZE)); + ASSERT(Size <= CFG_RX_MAX_PKT_SIZE); + + kalDmaBufGet(&DmaVBuf, &DmaPBuf); + DmaConf.Src = (ULONG) DmaPBuf; + + kalMemCopy(DmaVBuf, Buf, Size); + } +#else + + /* DMA_TO_DEVICE writeback the cache */ + DmaConf.Src = dma_map_single(HifInfo->Dev, Buf, Size, DMA_TO_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + /* start to write */ + AP_DMA_HIF_LOCK(HifInfo); + + prDmaOps->DmaClockCtrl(TRUE); + prDmaOps->DmaConfig(HifInfo, &DmaConf); + prDmaOps->DmaStart(HifInfo); + +#if (CONF_HIF_DMA_INT == 1) + RtnVal = wait_event_interruptible_timeout(HifInfo->HifDmaWaitq, (HifInfo->HifDmaWaitFlg != 0), 1000); + if (RtnVal <= 0) + DBGLOG(TX, ERROR, "fatal error1! reset DMA!\n"); + HifInfo->HifDmaWaitFlg = 0; +#else + + LoopCnt = 0; + PollTimeout = jiffies + HZ * 5; + + do { + if (time_before(jiffies, PollTimeout)) + continue; + DBGLOG(TX, INFO, "TX DMA Timeout, HSTCR: 0x%08x\n", u4HSTCRValue); + if (prDmaOps->DmaRegDump != NULL) + prDmaOps->DmaRegDump(HifInfo); + WlanDmaFatalErr = 1; + /* we still need complete dma progress even dma timeout */ + break; + } while (!prDmaOps->DmaPollIntr(HifInfo)); +#endif /* CONF_HIF_DMA_INT */ + /* we should disable dma interrupt then clear dma interrupt, otherwise, + for dma timeout case, interrupt may be set after we clear it */ + prDmaOps->DmaStop(HifInfo); + prDmaOps->DmaAckIntr(HifInfo); + + LoopCnt = 0; + do { + if (LoopCnt++ > 100000) { + DBGLOG(TX, ERROR, "fatal error2! reset DMA!\n"); + break; + } + } while (prDmaOps->DmaPollStart(HifInfo) != 0); + + prDmaOps->DmaClockCtrl(FALSE); + + AP_DMA_HIF_UNLOCK(HifInfo); + +#ifndef MTK_DMA_BUF_MEMCPY_SUP + dma_unmap_single(HifInfo->Dev, DmaConf.Src, Size, DMA_TO_DEVICE); +#endif /* MTK_DMA_BUF_MEMCPY_SUP */ + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + if (WlanDmaFatalErr) { + if (!fgIsResetting) + glDoChipReset(); + return FALSE; + } + HIF_DBG_TX(("[WiFi/HIF] DMA TX OK!\n")); + } else +#endif /* CONF_MTK_AHB_DMA */ + { + UINT_32 IdLoop, MaxLoop; + UINT_32 *LoopBuf; + + /* PIO mode */ + MaxLoop = Size >> 2; + LoopBuf = (UINT_32 *) Buf; + + HIF_DBG_TX(("[WiFi/HIF/PIO] Prepare to send data (%d 0x%p-0x%p)...\n", + Size, LoopBuf, (((UINT8 *) LoopBuf) + (Size & (~0x03))))); + + if (Size & 0x3) + MaxLoop++; + + for (IdLoop = 0; IdLoop < MaxLoop; IdLoop++) { + HIF_REG_WRITEL(HifInfo, Port, *LoopBuf); + LoopBuf++; + } + + if ((RegWHLPCR & WHLPCR_INT_EN_SET) == 1) + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_SET); + + HIF_DBG_TX(("\n\n")); + } + + return TRUE; + +} /* end of kalDevPortWrite() */ + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static irqreturn_t HifAhbISR(IN int Irq, IN void *Arg) +{ + struct net_device *prNetDevice = (struct net_device *)Arg; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + IsrCnt++; + ASSERT(prNetDevice); + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + ASSERT(GlueInfo); + + if (!GlueInfo) + return IRQ_HANDLED; + + HifInfo = &GlueInfo->rHifInfo; + + GlueInfo->IsrCnt++; + + if (GlueInfo->ulFlag & GLUE_FLAG_HALT) { + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + return IRQ_HANDLED; + } + + HIF_REG_WRITEL(HifInfo, MCR_WHLPCR, WHLPCR_INT_EN_CLR); + + /* lock 100ms to avoid suspend */ + kalHifAhbKalWakeLockTimeout(GlueInfo); + + /* Wake up main thread */ + set_bit(GLUE_FLAG_INT_BIT, &GlueInfo->ulFlag); + + /* when we got sdio interrupt, we wake up the tx servie thread */ + wake_up_interruptible(&GlueInfo->waitq); + + IsrPassCnt++; + GlueInfo->IsrPassCnt++; + return IRQ_HANDLED; + +} + +#if (CONF_HIF_DMA_INT == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO interrupt callback function +* +* \param[in] func pointer to SDIO handle +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ + +static irqreturn_t HifDmaISR(IN int Irq, IN void *Arg) +{ + struct net_device *prNetDevice = (struct net_device *)Arg; + GLUE_INFO_T *GlueInfo; + GL_HIF_INFO_T *HifInfo; + + /* Init */ + ASSERT(prNetDevice); + GlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prNetDevice)); + ASSERT(GlueInfo); + + if (!GlueInfo) + return IRQ_HANDLED; + HifInfo = &GlueInfo->rHifInfo; + + /* disable interrupt */ + HifInfo->DmaOps->DmaAckIntr(HifInfo); + + /* Wake up main thread */ + set_bit(1, &HifInfo->HifDmaWaitFlg); + + /* when we got sdio interrupt, we wake up the tx servie thread */ + wake_up_interruptible(&HifInfo->HifDmaWaitq); + + return IRQ_HANDLED; + +} +#endif /* CONF_HIF_DMA_INT */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is a SDIO probe function +* +* \param[in] func pointer to SDIO handle +* \param[in] id pointer to SDIO device id table +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +#if defined(CONFIG_MTK_CLKMGR) +#if defined(MTK_EXTERNAL_LDO) || defined(MTK_ALPS_BOX_SUPPORT) +#include +#endif +#endif + +static int HifAhbProbe(VOID) +{ + int Ret = 0; + + DBGLOG(INIT, INFO, "HifAhbProbe()\n"); + + /* power on WiFi TX PA 3.3V and HIF GDMA clock */ + { +#ifdef CONFIG_MTK_PMIC_MT6397 +#if defined(CONFIG_MTK_CLKMGR) +#ifdef MTK_EXTERNAL_LDO + /* for 8127 tablet */ + mt_set_gpio_mode(GPIO51, GPIO_MODE_04); + mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO51, GPIO_PULL_UP); +#elif defined(MTK_ALPS_BOX_SUPPORT) + /* for 8127 box */ + mt_set_gpio_mode(GPIO89, GPIO_MODE_04); + mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO89, GPIO_PULL_UP); +#else + hwPowerOn(MT65XX_POWER_LDO_VGP4, VOL_3300, "WLAN"); +#endif +#endif +#else +#ifdef CONFIG_OF /*for MT6752 */ + mtk_wcn_consys_hw_wifi_paldo_ctrl(1); /* switch to HW mode */ +#else /*for MT6572/82/92 */ + hwPowerOn(MT6323_POWER_LDO_VCN33_WIFI, VOL_3300, "WLAN"); + upmu_set_vcn33_on_ctrl_wifi(1); /* switch to HW mode */ +#endif +#endif + + } + +#if (CONF_HIF_DEV_MISC == 1) + if (pfWlanProbe((PVOID) &MtkAhbDriver.this_device) != WLAN_STATUS_SUCCESS) { +#else + if (pfWlanProbe((PVOID) &HifAhbPDev->dev) != WLAN_STATUS_SUCCESS) { +#endif /* CONF_HIF_DEV_MISC */ + + pfWlanRemove(); + Ret = -1; + } + + return Ret; + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function will do module remove. +* +* \param[in] None +* +* \return The result of remove (WLAN_STATUS_SUCCESS = 0) +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbRemove(VOID) +{ + DBGLOG(INIT, INFO, "HifAhbRemove()\n"); + + pfWlanRemove(); + + { +#ifdef CONFIG_MTK_PMIC_MT6397 +#if defined(CONFIG_MTK_CLKMGR) +#ifdef MTK_EXTERNAL_LDO + /* for 8127 tablet */ + mt_set_gpio_mode(GPIO51, GPIO_MODE_04); + mt_set_gpio_dir(GPIO51, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO51, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO51, GPIO_PULL_DOWN); +#elif defined(MTK_ALPS_BOX_SUPPORT) + /* for 8127 box */ + mt_set_gpio_mode(GPIO89, GPIO_MODE_04); + mt_set_gpio_dir(GPIO89, GPIO_DIR_OUT); + mt_set_gpio_pull_enable(GPIO89, GPIO_PULL_ENABLE); + mt_set_gpio_pull_select(GPIO89, GPIO_PULL_DOWN); +#else + hwPowerDown(MT65XX_POWER_LDO_VGP4, "WLAN"); +#endif +#endif +#else +#ifdef CONFIG_OF /*for MT6752 */ + mtk_wcn_consys_hw_wifi_paldo_ctrl(0); /* switch to SW mode */ +#else /*for MT6572/82/92 */ + upmu_set_vcn33_on_ctrl_wifi(0); /* switch to SW mode */ + hwPowerDown(MT6323_POWER_LDO_VCN33_WIFI, "WLAN"); +#endif +#endif + + } + + return 0; +} + +#if (MTK_WCN_SINGLE_MODULE == 0) +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function gets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return TX count +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntGet(VOID) +{ + return HifTxCnt; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function resets the TX count pass through HIF AHB bus. +* +* \param[in] None +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbBusCntClr(VOID) +{ + HifTxCnt = 0; + return 0; +} +#endif /* MTK_WCN_SINGLE_MODULE */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function configs the DMA TX/RX settings before any real TX/RX. +* +* \param[in] GlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] BurstLen 0(1DW), 1(4DW), 2(8DW), Others(Reserved) +* \param[in] PortId 0(TXD0), 1(TXD1), 2(RXD0), 3(RXD1), 4(WHISR enhance) +* \param[in] TransByte Should be 4-byte align. +* +* \return void +*/ +/*----------------------------------------------------------------------------*/ +static UINT_32 HifAhbDmaEnhanceModeConf(IN GLUE_INFO_T * GlueInfo, UINT_32 BurstLen, UINT_32 PortId, UINT_32 TransByte) +{ + GL_HIF_INFO_T *HifInfo; + UINT_32 RegHSTCR; + + ASSERT(GlueInfo); + HifInfo = &GlueInfo->rHifInfo; + + RegHSTCR = HIF_REG_READL(HifInfo, MCR_WHIER); + + RegHSTCR = HIF_REG_READL(HifInfo, MCR_HSTCR); + RegHSTCR = + ((BurstLen << HSTCR_AFF_BURST_LEN_OFFSET) & HSTCR_AFF_BURST_LEN) | + ((PortId << HSTCR_TRANS_TARGET_OFFSET) & HSTCR_TRANS_TARGET) | + (((TransByte & 0x3) == 0) ? (TransByte & HSTCR_HSIF_TRANS_CNT) : ((TransByte + 4) & HSTCR_HSIF_TRANS_CNT)); + HIF_REG_WRITEL(HifInfo, MCR_HSTCR, RegHSTCR); + return RegHSTCR; +} + +VOID glSetPowerState(IN GLUE_INFO_T *GlueInfo, IN UINT_32 ePowerMode) +{ + +} + +#if (CONF_HIF_DEV_MISC == 1) +/* no use */ +static ssize_t HifAhbMiscRead(IN struct file *Filp, OUT char __user *DstBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static ssize_t HifAhbMiscWrite(IN struct file *Filp, IN const char __user *SrcBuf, IN size_t Size, IN loff_t *Ppos) +{ + return 0; +} + +static int HifAhbMiscIoctl(IN struct file *Filp, IN unsigned int Cmd, IN unsigned long arg) +{ + return 0; +} + +static int HifAhbMiscOpen(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} + +static int HifAhbMiscClose(IN struct inode *Inodep, IN struct file *Filp) +{ + return 0; +} +#else + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmProbe(IN struct platform_device *PDev) +{ + HifAhbPDev = PDev; + + DBGLOG(INIT, INFO, "HifAhbPltmProbe\n"); + +#if (CONF_HIF_PMIC_TEST == 1) + wmt_set_jtag_for_mcu(); + wmt_set_jtag_for_gps(); + +#endif /* CONF_HIF_PMIC_TEST */ + +#if (MTK_WCN_SINGLE_MODULE == 1) + HifAhbProbe(); /* only for test purpose without WMT module */ + +#else + + /* register WiFi function to WMT */ + DBGLOG(INIT, INFO, "mtk_wcn_wmt_wlan_reg\n"); + { + MTK_WCN_WMT_WLAN_CB_INFO WmtCb; + + WmtCb.wlan_probe_cb = HifAhbProbe; + WmtCb.wlan_remove_cb = HifAhbRemove; + WmtCb.wlan_bus_cnt_get_cb = HifAhbBusCntGet; + WmtCb.wlan_bus_cnt_clr_cb = HifAhbBusCntClr; + mtk_wcn_wmt_wlan_reg(&WmtCb); + } +#endif /* MTK_WCN_SINGLE_MODULE */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int __exit HifAhbPltmRemove(IN struct platform_device *PDev) +{ +#if (MTK_WCN_SINGLE_MODULE == 0) + mtk_wcn_wmt_wlan_unreg(); +#endif /* MTK_WCN_SINGLE_MODULE */ + return 0; +} + +#ifdef CONFIG_PM +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* \param[in] Message +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmSuspend(IN struct platform_device *PDev, pm_message_t Message) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is called by OS platform device module. +* +* \param[in] PDev Pointer to the platform device structure. +* +* \return 0 +*/ +/*----------------------------------------------------------------------------*/ +static int HifAhbPltmResume(IN struct platform_device *PDev) +{ + return 0; +} +#endif /* CONFIG_PM */ + +#endif /* CONF_HIF_DEV_MISC */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) +/*----------------------------------------------------------------------------*/ +/*! +* \brief Trigger to do HIF loopback test. +* +* \param[in] arg Pointer to the GLUE_INFO_T structure. +* +* \retval None +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifAhbLoopbkAuto(IN unsigned long arg) +{ + + P_GLUE_INFO_T GlueInfo = (P_GLUE_INFO_T) arg; + GL_HIF_INFO_T *HifInfo = &GlueInfo->rHifInfo; + + ASSERT(GlueInfo); + + HIF_DBG(("[WiFi/HIF] Trigger to do loopback test...\n")); + + set_bit(GLUE_FLAG_HIF_LOOPBK_AUTO_BIT, &HifInfo->HifLoopbkFlg); + wake_up_interruptible(&HifInfo->HifWaitq); + +} +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo) +{ + GL_HIF_INFO_T *prHifInfo = &prGlueInfo->rHifInfo; + unsigned short j; + + for (j = 0; j < 512; j++) { + DBGLOG(INIT, WARN, "0x%08x ", MCU_REG_READL(prHifInfo, CONN_MCU_CPUPCR)); + if ((j + 1) % 16 == 0) + DBGLOG(INIT, WARN, "\n"); + } +} + +/* End of ahb.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c new file mode 100644 index 0000000000000..6b719028ae934 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/arm.c @@ -0,0 +1,31 @@ +/****************************************************************************** +*[File] mt6516-evb.c +*[Version] v1.0 +*[Revision Date] 2010-03-01 +*[Author] +*[Description] +* dummy file for build system +*[Copyright] +* Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/* +** Log: mt6516-evb.c + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * remove debug message + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** +*/ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h new file mode 100644 index 0000000000000..1507d5560040e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif.h @@ -0,0 +1,340 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 +*/ + +/*! \file "hif.h" + \brief Functions for the driver to register bus and setup the IRQ + + Functions for the driver to register bus and setup the IRQ +*/ + +/* +** Log: hif.h + * + * 11 01 2010 yarco.yang + * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform + * Add GPIO debug function + * + * 10 19 2010 jeffrey.chang + * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK + * HIF by default + * Refine linux kernel module to the license of MTK and enable MTK HIF + * + * 08 18 2010 jeffrey.chang + * NULL + * support multi-function sdio + * + * 08 17 2010 cp.wu + * NULL + * add ENE SDIO host workaround for x86 linux platform. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\4 2009-10-20 17:38:28 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, +** and then stop hw. +** \main\maintrunk.MT5921\3 2009-09-28 20:19:20 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\2 2009-08-18 22:57:05 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\2 2008-09-22 23:18:17 GMT mtk01461 +** Update driver for code review +** Revision 1.1 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +*/ + +#ifndef _HIF_H +#define _HIF_H + +#include "gl_typedef.h" +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +#define CONF_MTK_AHB_DMA 1 /* PIO mode is default mode if DMA is disabled */ + +#define CONF_HIF_DEV_MISC 0 /* register as misc device */ +#define CONF_HIF_LOOPBACK_AUTO 0 /* hif loopback test triggered by open() */ + /* only for development test */ + +#define CONF_HIF_PMIC_TEST 0 /* test purpose: power on CONNSYS */ + +#define CONF_HIF_DMA_INT 0 /* DMA interrupt mode */ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +extern phys_addr_t gConEmiPhyBase; +extern BOOLEAN fgIsResetting; +extern UINT_32 IsrCnt, IsrPassCnt; +extern int kalDevLoopbkThread(IN void *data); + +#ifdef CONFIG_MTK_PMIC_MT6397 +#else +#ifdef CONFIG_OF /*for MT6752 */ +extern INT_32 mtk_wcn_consys_hw_wifi_paldo_ctrl(UINT_32 enable); +#else /*for MT6572/82/92 */ +extern void upmu_set_vcn33_on_ctrl_wifi(UINT_32 val); +#endif +#endif + +#if (CONF_HIF_DEV_MISC == 1) +#else +/* extern INT32 mtk_wcn_consys_hw_reg_ctrl(UINT32 on, UINT32 co_clock_en); */ +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#ifndef CONN_MCU_CONFIG_BASE +#define CONN_MCU_CONFIG_BASE 0xF8070000 /* MT6572 */ +#endif /* CONN_MCU_CONFIG_BASE */ + +#define CONSYS_CPUPCR_REG (CONN_MCU_CONFIG_BASE + 0x00000160) +#define CONSYS_REG_READ(addr) (*((volatile unsigned int *)(addr))) + +#define CONN_MCU_DRV_BASE 0x18070000 +#define CONN_MCU_REG_LENGTH 0x0200 +#define CONN_MCU_CPUPCR 0x0160 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/* host interface's private data structure, which is attached to os glue +** layer info structure. + */ +typedef struct _GL_HIF_DMA_OPS_T { /* DMA Operators */ + VOID (*DmaConfig)(IN VOID *HifInfo, IN VOID *Conf); + + VOID (*DmaStart)(IN VOID *HifInfo); + + VOID (*DmaStop)(IN VOID *HifInfo); + + MTK_WCN_BOOL (*DmaPollStart)(IN VOID *HifInfo); + + MTK_WCN_BOOL (*DmaPollIntr)(IN VOID *HifInfo); + + VOID (*DmaAckIntr)(IN VOID *HifInfo); + + VOID (*DmaClockCtrl)(IN UINT_32 FlgIsEnabled); + + VOID (*DmaRegDump)(IN VOID *HifInfo); + + VOID (*DmaReset)(IN VOID *HifInfo); + +} GL_HIF_DMA_OPS_T; + +typedef struct _GL_HIF_INFO_T { + + /* General */ + VOID *Dev; /* struct device */ + +#define MTK_CHIP_ID_6571 0x6571 +#define MTK_CHIP_ID_6572 0x6572 +#define MTK_CHIP_ID_6582 0x6582 +#define MTK_CHIP_ID_8127 0x8127 +#define MTK_CHIP_ID_6752 0x6752 +#define MTK_CHIP_ID_8163 0x8163 +#define MTK_CHIP_ID_6735 0x6735 +#define MTK_CHIP_ID_6580 0x6580 +#define MTK_CHIP_ID_6755 0x6755 +#define MTK_CHIP_ID_7623 0x7623 + + UINT_32 ChipID; + + /* Control flag */ + BOOLEAN fgIntReadClear; + BOOLEAN fgMbxReadClear; + BOOLEAN fgDmaEnable; /* TRUE: DMA mode is used (default) */ + + /* HIF related */ + UINT_8 *HifRegBaseAddr; /* HIF register base */ + UINT_8 *McuRegBaseAddr; /* CONN MCU register base */ + +#if (CONF_HIF_LOOPBACK_AUTO == 1) + struct timer_list HifTmrLoopbkFn; /* HIF loopback test trigger timer */ + wait_queue_head_t HifWaitq; + UINT_32 HifLoopbkFlg; + struct task_struct *HifTaskLoopbkFn; /* HIF loopback test task */ +#endif /* CONF_HIF_LOOPBACK_AUTO */ + +#if (CONF_HIF_DMA_INT == 1) + wait_queue_head_t HifDmaWaitq; + UINT_32 HifDmaWaitFlg; +#endif /* CONF_HIF_DMA_INT */ + + /* DMA related */ +#define AP_DMA_HIF_LOCK(_lock) /* spin_lock_bh(&(_lock)->DdmaLock) */ +#define AP_DMA_HIF_UNLOCK(_lock) /* spin_unlock_bh(&(_lock)->DdmaLock) */ + spinlock_t DdmaLock; /* protect DMA access */ + + UINT_8 *DmaRegBaseAddr; /* DMA register base */ + GL_HIF_DMA_OPS_T *DmaOps; /* DMA Operators */ + +#if !defined(CONFIG_MTK_CLKMGR) + struct clk *clk_wifi_dma; +#endif +} GL_HIF_INFO_T, *P_GL_HIF_INFO_T; + +#define HIF_MOD_NAME "AHB_SLAVE_HIF" + +#define HIF_DRV_BASE 0x180F0000 +#define HIF_DRV_LENGTH 0x005c + +typedef enum _MTK_WCN_HIF_BURST_LEN { + HIF_BURST_1DW = 0, + HIF_BURST_4DW, + HIF_BURST_8DW +} MTK_WCN_HIF_BURST_LEN; + +typedef enum _MTK_WCN_HIF_TXRX_TARGET { + HIF_TARGET_TXD0 = 0, + HIF_TARGET_TXD1, + HIF_TARGET_RXD0, + HIF_TARGET_RXD1, + HIF_TARGET_WHISR +} MTK_WCN_HIF_TXRX_TARGET; + +typedef enum _MTK_WCN_HIF_DMA_DIR { + HIF_DMA_DIR_TX = 0, + HIF_DMA_DIR_RX +} MTK_WCN_HIF_DMA_DIR; + +typedef struct _MTK_WCN_HIF_DMA_CONF { + UINT_32 Count; + MTK_WCN_HIF_DMA_DIR Dir; + UINT_32 Burst; + UINT_32 Wsize; + UINT_32 Ratio; + UINT_32 Connect; + UINT_32 Fix_en; + ULONG Src; + ULONG Dst; +} MTK_WCN_HIF_DMA_CONF; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define MCU_REG_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->McuRegBaseAddr + _addr)) + +/* PIO mode HIF register read/write */ +#define HIF_REG_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr)) + +#define HIF_REG_WRITEL(_hif, _addr, _val) \ + writel(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) + +#define HIF_REG_WRITEB(_hif, _addr, _val) \ + writeb(_val, ((volatile UINT_32 *)((_hif)->HifRegBaseAddr + _addr))) + +/* PIO mode DMA register read/write */ +#define HIF_DMAR_READL(_hif, _addr) \ + readl((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr)) + +#define HIF_DMAR_WRITEL(_hif, _addr, _val) \ + writel(_val, ((volatile UINT_32 *)((_hif)->DmaRegBaseAddr + _addr))) + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#ifndef MODULE_AHB_DMA +VOID HifDumpEnhanceModeData(P_ADAPTER_T prAdapter); + +VOID HifRegDump(P_ADAPTER_T prAdapter); + +BOOLEAN HifIsFwOwn(P_ADAPTER_T prAdapter); + +WLAN_STATUS glRegisterBus(probe_card pfProbe, remove_card pfRemove); + +VOID glUnregisterBus(remove_card pfRemove); + +VOID glResetHif(GLUE_INFO_T *GlueInfo); + +VOID glSetHifInfo(P_GLUE_INFO_T prGlueInfo, ULONG ulCookie); + +VOID glClearHifInfo(P_GLUE_INFO_T prGlueInfo); + +VOID glGetChipInfo(GLUE_INFO_T *GlueInfo, UINT_8 *pucChipBuf); + +#if CFG_SPM_WORKAROUND_FOR_HOTSPOT +BOOLEAN glIsChipNeedWakelock(GLUE_INFO_T *GlueInfo); +#endif + +BOOLEAN glBusInit(PVOID pvData); + +VOID glBusRelease(PVOID pData); + +INT_32 glBusSetIrq(PVOID pvData, PVOID pfnIsr, PVOID pvCookie); + +VOID glBusFreeIrq(PVOID pvData, PVOID pvCookie); + +VOID glSetPowerState(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 ePowerMode); + +VOID glDumpConnSysCpuInfo(P_GLUE_INFO_T prGlueInfo); + +#endif /* MODULE_AHB_DMA */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config GDMA TX/RX. +* +* \param[in] DmaRegBaseAddr Pointer to the IO register base. +* \param[in] Conf Pointer to the DMA operator. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifGdmaInit(GL_HIF_INFO_T *HifInfo); + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] DmaRegBaseAddr Pointer to the IO register base. +* \param[in] Conf Pointer to the DMA operator. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h new file mode 100644 index 0000000000000..094c07f98eff2 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_gdma.h @@ -0,0 +1,154 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 +*/ + +/*! \file "hif_gdma.h" + \brief MARCO, definition, structure for GDMA. + + MARCO, definition, structure for GDMA. +*/ + +/* +** Log: hif_gdma.h + * + * 01 16 2013 vend_samp.lin + * Add AHB GDMA support + * 1) Initial version +** +*/ + +#ifndef _HIF_GDMA_H +#define _HIF_GDMA_H + +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_GDMA_BURST_LEN { + HIF_GDMA_BURST_1_8 = 0, + HIF_GDMA_BURST_2_8, + HIF_GDMA_BURST_3_8, + HIF_GDMA_BURST_4_8, + HIF_GDMA_BURST_5_8, + HIF_GDMA_BURST_6_8, + HIF_GDMA_BURST_7_8, + HIF_GDMA_BURST_8_8 /* same as HIF_GDMA_BURST_7_8 */ +} MTK_WCN_HIF_GDMA_BURST_LEN; + +typedef enum _MTK_WCN_HIF_GDMA_WRITE_LEN { + HIF_GDMA_WRITE_0 = 0, /* transaction size is 1 byte */ + HIF_GDMA_WRITE_1, /* transaction size is 2 byte */ + HIF_GDMA_WRITE_2, /* transaction size is 4 byte */ + HIF_GDMA_WRITE_3 /* transaction size is 1 byte */ +} MTK_WCN_HIF_GDMA_WRITE_LEN; + +typedef enum _MTK_WCN_HIF_GDMA_RATIO { + HIF_GDMA_RATIO_0 = 0, /* 1/2 */ + HIF_GDMA_RATIO_1 /* 1/1 */ +} MTK_WCN_HIF_GDMA_RATIO; + +typedef enum _MTK_WCN_HIF_GDMA_CONNECT { + HIF_GDMA_CONNECT_NO = 0, /* no connect */ + HIF_GDMA_CONNECT_SET1, /* connect set1 (req/ack) */ + HIF_GDMA_CONNECT_SET2, /* connect set2 (req/ack) */ + HIF_GDMA_CONNECT_SET3 /* connect set3 (req/ack) */ +} MTK_WCN_HIF_GDMA_CONNECT; + +/* reference to MT6572_AP_P_DMA_Spec.doc */ +#define AP_DMA_HIF_BASE 0x11000100 + +#define AP_P_DMA_G_DMA_2_INT_FLAG (0x0000) +#define AP_P_DMA_G_DMA_2_CON (0x0018) +#define AP_P_DMA_G_DMA_2_CONNECT (0x0034) +#define AP_P_DMA_G_DMA_2_LEN1 (0x0024) +#define AP_P_DMA_G_DMA_2_SRC_ADDR (0x001C) +#define AP_P_DMA_G_DMA_2_DST_ADDR (0x0020) +#define AP_P_DMA_G_DMA_2_INT_EN (0x0004) +#define AP_P_DMA_G_DMA_2_EN (0x0008) +#define AP_P_DMA_G_DMA_2_RST (0x000C) +#define AP_P_DMA_G_DMA_2_STOP (0x0010) + +#define AP_DMA_HIF_0_LENGTH 0x0038 + +/* AP_DMA_HIF_0_INT_FLAG */ +#define ADH_CR_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_INT_EN */ +#define ADH_CR_INTEN_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_EN */ +#define ADH_CR_EN BIT(0) +#define ADH_CR_CONN_BUR_EN BIT(1) + +/* AP_DMA_HIF_0_STOP */ +#define ADH_CR_PAUSE BIT(1) +#define ADH_CR_STOP BIT(0) + +/* AP_P_DMA_G_DMA_2_CON */ +#define ADH_CR_FLAG_FINISH BIT(30) +#define ADH_CR_RSIZE BITS(28, 29) +#define ADH_CR_RSIZE_OFFSET 28 +#define ADH_CR_WSIZE BITS(24, 25) +#define ADH_CR_WSIZE_OFFSET 24 +#define ADH_CR_BURST_LEN BITS(16, 18) +#define ADH_CR_BURST_LEN_OFFSET 16 +#define ADH_CR_WADDR_FIX_EN BIT(3) +#define ADH_CR_WADDR_FIX_EN_OFFSET 3 +#define ADH_CR_RADDR_FIX_EN BIT(4) +#define ADH_CR_RADDR_FIX_EN_OFFSET 4 + +/* AP_P_DMA_G_DMA_2_CONNECT */ +#define ADH_CR_RATIO BIT(3) +#define ADH_CR_RATIO_OFFSET 3 +#define ADH_CR_DIR BIT(2) +#define ADH_CR_DIR_OFFSET 2 +#define ADH_CR_CONNECT BITS(0, 1) + +/* AP_DMA_HIF_0_LEN */ +#define ADH_CR_LEN BITS(0, 19) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_GDMA_H */ + +/* End of hif_gdma.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h new file mode 100644 index 0000000000000..32224e8f17d85 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/hif_pdma.h @@ -0,0 +1,141 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/hif/sdio/include/hif.h#1 +*/ + +/*! \file "hif_pdma.h" + \brief MARCO, definition, structure for PDMA. + + MARCO, definition, structure for PDMA. +*/ + +/* +** Log: hif_pdma.h + * + * 01 16 2013 vend_samp.lin + * Add AHB PDMA support + * 1) Initial version +** +*/ + +#ifndef _HIF_PDMA_H +#define _HIF_PDMA_H + +#include "mtk_porting.h" + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +typedef enum _MTK_WCN_HIF_PDMA_BURST_LEN { + HIF_PDMA_BURST_1_4 = 0, + HIF_PDMA_BURST_2_4, + HIF_PDMA_BURST_3_4, + HIF_PDMA_BURST_4_4 +} MTK_WCN_HIF_PDMA_BURST_LEN; + +/* reference to MT6572_AP_P_DMA_Spec.doc */ +#ifdef CONFIG_OF +/*for MT6752*/ +#define AP_DMA_HIF_BASE 0x11000080 +#else +/*for MT6572/82/92*/ +#define AP_DMA_HIF_BASE 0x11000180 +#endif + +#define AP_DMA_HIF_0_INT_FLAG (0x0000) +#define AP_DMA_HIF_0_INT_EN (0x0004) +#define AP_DMA_HIF_0_EN (0x0008) +#define AP_DMA_HIF_0_RST (0x000C) +#define AP_DMA_HIF_0_STOP (0x0010) +#define AP_DMA_HIF_0_FLUSH (0x0014) +#define AP_DMA_HIF_0_CON (0x0018) +#define AP_DMA_HIF_0_SRC_ADDR (0x001C) +#define AP_DMA_HIF_0_DST_ADDR (0x0020) +#define AP_DMA_HIF_0_LEN (0x0024) +#define AP_DMA_HIF_0_INT_BUF_SIZE (0x0038) +#define AP_DMA_HIF_0_DEBUG_STATUS (0x0050) +#define AP_DMA_HIF_0_SRC_ADDR2 (0x0054) +#define AP_DMA_HIF_0_DST_ADDR2 (0x0058) + +#define AP_DMA_HIF_0_LENGTH 0x0080 + +/* AP_DMA_HIF_0_INT_FLAG */ +#define ADH_CR_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_INT_EN */ +#define ADH_CR_INTEN_FLAG_0 BIT(0) + +/* AP_DMA_HIF_0_EN */ +#define ADH_CR_EN BIT(0) + +/* AP_DMA_HIF_0_RST */ +#define ADH_CR_HARD_RST BIT(1) +#define ADH_CR_WARM_RST BIT(0) + +/* AP_DMA_HIF_0_STOP */ +#define ADH_CR_PAUSE BIT(1) +#define ADH_CR_STOP BIT(0) + +/* AP_DMA_HIF_0_FLUSH */ +#define ADH_CR_FLUSH BIT(0) + +/* AP_DMA_HIF_0_CON */ +#define ADH_CR_BURST_LEN BITS(16, 17) +#define ADH_CR_BURST_LEN_OFFSET 16 +#define ADH_CR_SLOW_CNT BITS(5, 14) +#define ADH_CR_SLOW_EN BIT(2) +#define ADH_CR_FIX_EN BIT(1) +#define ADH_CR_FIX_EN_OFFSET 1 +#define ADH_CR_DIR BIT(0) + +/* AP_DMA_HIF_0_LEN */ +#define ADH_CR_LEN BITS(0, 19) + +/* AP_DMA_HIF_0_SRC_ADDR2 */ +#define ADH_CR_SRC_ADDR2 BIT(0) +/* AP_DMA_HIF_0_DST_ADDR2 */ +#define ADH_CR_DST_ADDR2 BIT(0) + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ +#endif /* _HIF_PDMA_H */ + +/* End of hif_gdma.h */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h new file mode 100644 index 0000000000000..91557137af9af --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/include/mtk_porting.h @@ -0,0 +1,91 @@ +/* porting layer */ +/* Android */ + +#ifndef _MTK_PORTING_H_ +#define _MTK_PORTING_H_ + +#include /* include stddef.h for NULL */ + +#define CONF_MTK_AHB_DMA 1 + +/* Type definition for signed integers */ +/*typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT_32, *PINT32;*/ + +/* Type definition for unsigned integers */ +/*typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32;*/ + +#ifndef VOID +/*typedef void VOID, *PVOID;*/ +#endif + +#ifndef IN +#define IN +#endif + +#ifndef OUT +#define OUT +#endif + +#ifndef INTOUT +#define INOUT +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef BIT +#define BIT(n) ((UINT_32) 1U << (n)) +#endif /* BIT */ + +#ifndef BITS +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + +#ifndef BOOLEAN +#define BOOLEAN unsigned char +#endif + +typedef int MTK_WCN_BOOL; +#ifndef MTK_WCN_BOOL_TRUE +#define MTK_WCN_BOOL_FALSE ((MTK_WCN_BOOL) 0) +#define MTK_WCN_BOOL_TRUE ((MTK_WCN_BOOL) 1) +#endif + +typedef int MTK_WCN_MUTEX; + +typedef int MTK_WCN_TIMER; + +/* system APIs */ +/* mutex */ +typedef MTK_WCN_MUTEX(*MUTEX_CREATE) (const char *const name); +typedef INT_32(*MUTEX_DESTROY) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_LOCK) (MTK_WCN_MUTEX mtx); +typedef INT_32(*MUTEX_UNLOCK) (MTK_WCN_MUTEX mtx, unsigned long flags); +/* debug */ +typedef INT_32(*DBG_PRINT) (const char *str, ...); +typedef INT_32(*DBG_ASSERT) (INT_32 expr, const char *file, INT_32 line); +/* timer */ +typedef void (*MTK_WCN_TIMER_CB) (void); +typedef MTK_WCN_TIMER(*TIMER_CREATE) (const char *const name); +typedef INT_32(*TIMER_DESTROY) (MTK_WCN_TIMER tmr); +typedef INT_32(*TIMER_START) (MTK_WCN_TIMER tmr, UINT_32 timeout, MTK_WCN_TIMER_CB tmr_cb, void *param); +typedef INT_32(*TIMER_STOP) (MTK_WCN_TIMER tmr); +/* kernel lib */ +typedef void *(*SYS_MEMCPY) (void *dest, const void *src, UINT_32 n); +typedef void *(*SYS_MEMSET) (void *s, INT_32 c, UINT_32 n); +typedef INT_32(*SYS_SPRINTF) (char *str, const char *format, ...); + +#endif /* _MTK_PORTING_H_ */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c new file mode 100644 index 0000000000000..94cc05ba32249 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/hif/ahb/mt8127/ahb_pdma.c @@ -0,0 +1,480 @@ +/****************************************************************************** +*[File] ahb_pdma.c +*[Version] v1.0 +*[Revision Date] 2013-03-13 +*[Author] +*[Description] +* The program provides AHB PDMA driver +*[Copyright] +* Copyright (C) 2013 MediaTek Incorporation. All Rights Reserved. +******************************************************************************/ + +/* +** Log: ahb_pdma.c + * + * 03 13 2013 vend_samp.lin + * Add AHB PDMA support + * 1) Initial version +** +*/ + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#define MODULE_AHB_DMA + +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if 0 +#if CONFIG_ANDROID +#include +#endif +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#include + +#include /* readw and writew */ + +#include + +#if defined(CONFIG_MTK_CLKMGR) +#include +#else +#include +#endif /* defined(CONFIG_MTK_CLKMGR) */ + +#include "hif.h" +#include "hif_pdma.h" +#include "gl_os.h" + +/* #include */ + +/* #if (CONF_MTK_AHB_DMA == 1) */ + +/* #define PDMA_DEBUG_SUP */ + +#ifdef PDMA_DEBUG_SUP +#define PDMA_DBG pr_debug +#else +#define PDMA_DBG(_fmt, ...) +#endif /* PDMA_DEBUG_SUP */ + +#if !defined(CONFIG_MTK_CLKMGR) +struct clk *g_clk_wifi_pdma; +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Conf); + +static VOID HifPdmaStart(IN void *HifInfoSrc); + +static VOID HifPdmaStop(IN void *HifInfoSrc); + +static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc); + +static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc); + +static VOID HifPdmaAckIntr(IN void *HifInfoSrc); + +static VOID HifPdmaClockCtrl(IN UINT32 FlgIsEnabled); + +static VOID HifPdmaRegDump(IN void *HifInfoSrc); + +static VOID HifPdmaReset(IN void *HifInfoSrc); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ +GL_HIF_DMA_OPS_T HifPdmaOps = { + .DmaConfig = HifPdmaConfig, + .DmaStart = HifPdmaStart, + .DmaStop = HifPdmaStop, + .DmaPollStart = HifPdmaPollStart, + .DmaPollIntr = HifPdmaPollIntr, + .DmaAckIntr = HifPdmaAckIntr, + .DmaClockCtrl = HifPdmaClockCtrl, + .DmaRegDump = HifPdmaRegDump, + .DmaReset = HifPdmaReset +}; + +/******************************************************************************* +* P U B L I C F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure. +* \param[in] Conf Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +VOID HifPdmaInit(GL_HIF_INFO_T *HifInfo) +{ + /* IO remap PDMA register memory */ +#ifdef AP_DMA_HIF_BASE +#undef AP_DMA_HIF_BASE +#define AP_DMA_HIF_BASE 0x11000180 +#endif + HifInfo->DmaRegBaseAddr = ioremap(AP_DMA_HIF_BASE, AP_DMA_HIF_0_LENGTH); + + /* assign PDMA operators */ + HifInfo->DmaOps = &HifPdmaOps; + + /* enable PDMA mode */ + HifInfo->fgDmaEnable = TRUE; + + /* Set EMI protection here */ +#if 0 +#ifdef MTK_TEE_CCCI_SECURE_SHARE_MEM_SUPPORT + DBGLOG(INIT, INFO, "WIFI set EMI MPU for TEE project\n"); + emi_mpu_set_region_protection(gConEmiPhyBase, + gConEmiPhyBase + SZ_1M / 2, + 5, SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN)); +#else + DBGLOG(INIT, INFO, "WIFI set EMI MPU for non-TEE project\n"); + emi_mpu_set_region_protection(gConEmiPhyBase, + gConEmiPhyBase + SZ_1M / 2, + 4, SET_ACCESS_PERMISSON(FORBIDDEN, NO_PROTECTION, FORBIDDEN, FORBIDDEN)); +#endif +#endif + +#if !defined(CONFIG_MTK_CLKMGR) + g_clk_wifi_pdma = HifInfo->clk_wifi_dma; +#endif + + PDMA_DBG("PDMA> HifPdmaInit ok!\n"); +} + +/******************************************************************************* +* P R I V A T E F U N C T I O N S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Config PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* \param[in] Param Pointer to the settings. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaConfig(IN void *HifInfoSrc, IN void *Param) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + MTK_WCN_HIF_DMA_CONF *Conf = (MTK_WCN_HIF_DMA_CONF *) Param; + UINT32 RegVal; + + /* Assign fixed value */ + Conf->Burst = HIF_PDMA_BURST_4_4; /* vs. HIF_BURST_4DW */ + Conf->Fix_en = FALSE; + + /* AP_P_DMA_G_DMA_2_CON */ + PDMA_DBG("PDMA> Conf->Dir = %d\n", Conf->Dir); + + /* AP_DMA_HIF_0_CON */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_CON); + RegVal &= ~(ADH_CR_BURST_LEN | ADH_CR_FIX_EN | ADH_CR_DIR); + RegVal |= (((Conf->Burst << ADH_CR_BURST_LEN_OFFSET) & ADH_CR_BURST_LEN) | + (Conf->Fix_en << ADH_CR_FIX_EN_OFFSET) | (Conf->Dir)); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_CON, RegVal); + PDMA_DBG("PDMA> AP_DMA_HIF_0_CON = 0x%08x\n", RegVal); + + /* AP_DMA_HIF_0_SRC_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_SRC_ADDR, Conf->Src); + PDMA_DBG("PDMA> AP_DMA_HIF_0_SRC_ADDR = 0x%08lx\n", Conf->Src); + + /* AP_DMA_HIF_0_DST_ADDR */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_DST_ADDR, Conf->Dst); + PDMA_DBG("PDMA> AP_DMA_HIF_0_DST_ADDR = 0x%08lx\n", Conf->Dst); + + /* AP_DMA_HIF_0_LEN */ + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_LEN, (Conf->Count & ADH_CR_LEN)); + PDMA_DBG("PDMA> AP_DMA_HIF_0_LEN = %u\n", (UINT_32)(Conf->Count & ADH_CR_LEN)); + +} /* End of HifPdmaConfig */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Start PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStart(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegVal; + + /* Enable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal | ADH_CR_INTEN_FLAG_0)); + + /* Start DMA */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_EN, (RegVal | ADH_CR_EN)); + + PDMA_DBG("PDMA> HifPdmaStart...\n"); + +} /* End of HifPdmaStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Stop PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaStop(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegVal; +/* UINT32 pollcnt; */ + + /* Disable interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_EN); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_EN, (RegVal & ~(ADH_CR_INTEN_FLAG_0))); + +#if 0 /* DE says we donot need to do it */ + /* Stop DMA */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_STOP); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_STOP, (RegVal | ADH_CR_STOP)); + + /* Polling START bit turn to 0 */ + pollcnt = 0; + do { + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + if (pollcnt++ > 100000) + ; /* TODO: warm reset PDMA */ + } while (RegVal & ADH_CR_EN); +#endif + +} /* End of HifPdmaStop */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Enable PDMA TX/RX. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static MTK_WCN_BOOL HifPdmaPollStart(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_EN); + return ((RegVal & ADH_CR_EN) != 0) ? TRUE : FALSE; + +} /* End of HifPdmaPollStart */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Poll PDMA TX/RX done. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static MTK_WCN_BOOL HifPdmaPollIntr(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegVal; + + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + return ((RegVal & ADH_CR_FLAG_0) != 0) ? TRUE : FALSE; + +} /* End of HifPdmaPollIntr */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge PDMA TX/RX done. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaAckIntr(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegVal; + + /* Write 0 to clear interrupt */ + RegVal = HIF_DMAR_READL(HifInfo, AP_DMA_HIF_0_INT_FLAG); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_INT_FLAG, (RegVal & ~ADH_CR_FLAG_0)); + +} /* End of HifPdmaAckIntr */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Acknowledge PDMA TX/RX done. +* +* \param[in] FlgIsEnabled TRUE: enable; FALSE: disable +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaClockCtrl(IN UINT32 FlgIsEnabled) +{ +#if !defined(CONFIG_MTK_CLKMGR) + int ret = 0; +#endif +#if defined(CONFIG_MTK_CLKMGR) + if (FlgIsEnabled == TRUE) + enable_clock(MT_CG_INFRA_APDMA, "WLAN"); + else + disable_clock(MT_CG_INFRA_APDMA, "WLAN"); +#else + if (FlgIsEnabled == TRUE) { + ret = clk_prepare_enable(g_clk_wifi_pdma); + if (ret) + DBGLOG(INIT, TRACE, "[CCF]clk_prepare_enable ret= %d\n", ret); + } else { + clk_disable_unprepare(g_clk_wifi_pdma); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Dump PDMA related registers. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaRegDump(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 RegId, RegVal; + UINT32 RegNum = 0; + + DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE); + for (RegId = 0; RegId < AP_DMA_HIF_0_LENGTH; RegId += 4) { + RegVal = HIF_DMAR_READL(HifInfo, RegId); + DBGLOG(INIT, INFO, "0x%08x ", RegVal); + + if (RegNum++ >= 3) { + DBGLOG(INIT, INFO, "\n"); + DBGLOG(INIT, INFO, "PDMA> Register content 0x%x=\n\t", AP_DMA_HIF_BASE + RegId + 4); + RegNum = 0; + } + } + +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Reset DMA. +* +* \param[in] HifInfo Pointer to the GL_HIF_INFO_T structure. +* +* \retval NONE +*/ +/*----------------------------------------------------------------------------*/ +static VOID HifPdmaReset(IN void *HifInfoSrc) +{ + GL_HIF_INFO_T *HifInfo = (GL_HIF_INFO_T *) HifInfoSrc; + UINT32 LoopCnt; + + /* do warm reset: DMA will wait for current traction finished */ + DBGLOG(INIT, INFO, "\nDMA> do warm reset...\n"); + + /* normally, we need to sure that bit0 of AP_P_DMA_G_DMA_2_EN is 1 here */ + + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x01); + + for (LoopCnt = 0; LoopCnt < 10000; LoopCnt++) { + if (!HifPdmaPollStart(HifInfo)) + break; /* reset ok */ + } + + if (HifPdmaPollStart(HifInfo)) { + /* do hard reset because warm reset fails */ + DBGLOG(INIT, INFO, "\nDMA> do hard reset...\n"); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x02); + mdelay(1); + HIF_DMAR_WRITEL(HifInfo, AP_DMA_HIF_0_RST, 0x00); + } +} + +/* #endif */ /* CONF_MTK_AHB_DMA */ + +/* End of ahb_pdma.c */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h new file mode 100644 index 0000000000000..ec9f46bdab2e4 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_cfg80211.h @@ -0,0 +1,341 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_cfg80211.h#1 +*/ + +/*! \file gl_cfg80211.h + \brief This file is for Portable Driver linux cfg80211 support. +*/ + +/* +** Log: gl_cfg80211.h +** +** 09 03 2013 cp.wu +** add path for reassociation +** +** 09 12 2012 wcpadmin +** [ALPS00276400] Remove MTK copyright and legal header on GPL/LGPL related packages +** . +** +** 08 30 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . + * +*/ + +#ifndef _GL_CFG80211_H +#define _GL_CFG80211_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include "gl_os.h" +extern void wlanHandleSystemResume(void); +extern void wlanHandleSystemSuspend(void); +extern void p2pHandleSystemResume(void); +extern void p2pHandleSystemSuspend(void); + +#if CFG_SUPPORT_WAPI +extern UINT_8 keyStructBuf[1024]; /* add/remove key shared buffer */ +#else +extern UINT_8 keyStructBuf[100]; /* add/remove key shared buffer */ +#endif + +extern struct delayed_work sched_workq; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#if CONFIG_NL80211_TESTMODE +#define NL80211_DRIVER_TESTMODE_VERSION 2 +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +#if CONFIG_NL80211_TESTMODE + +typedef struct _NL80211_DRIVER_GET_STA_STATISTICS_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4Version; + UINT_32 u4Flag; + UINT_8 aucMacAddr[MAC_ADDR_LEN]; +} NL80211_DRIVER_GET_STA_STATISTICS_PARAMS, *P_NL80211_DRIVER_GET_STA_STATISTICS_PARAMS; + +typedef struct _NL80211_DRIVER_POORLINK_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + INT_8 cRssi; /* cRssi=0 means it is a invalid value. */ + UINT_8 ucLinkSpeed; /* ucLinkSpeed=0 means it is a invalid value */ + UINT_16 u2Reserved; +} NL80211_DRIVER_POORLINK_PARAMS, *P_NL80211_DRIVER_POORLINK_PARAMS; + +typedef enum _ENUM_TESTMODE_STA_STATISTICS_ATTR { + NL80211_TESTMODE_STA_STATISTICS_INVALID = 0, + NL80211_TESTMODE_STA_STATISTICS_VERSION, + NL80211_TESTMODE_STA_STATISTICS_MAC, + NL80211_TESTMODE_STA_STATISTICS_LINK_SCORE, + NL80211_TESTMODE_STA_STATISTICS_FLAG, + + NL80211_TESTMODE_STA_STATISTICS_PER, + NL80211_TESTMODE_STA_STATISTICS_RSSI, + NL80211_TESTMODE_STA_STATISTICS_PHY_MODE, + NL80211_TESTMODE_STA_STATISTICS_TX_RATE, + + NL80211_TESTMODE_STA_STATISTICS_TOTAL_CNT, + NL80211_TESTMODE_STA_STATISTICS_THRESHOLD_CNT, + + NL80211_TESTMODE_STA_STATISTICS_AVG_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_AVG_HIF_PROCESS_TIME, + NL80211_TESTMODE_STA_STATISTICS_MAX_HIF_PROCESS_TIME, + + NL80211_TESTMODE_STA_STATISTICS_FAIL_CNT, + NL80211_TESTMODE_STA_STATISTICS_TIMEOUT_CNT, + NL80211_TESTMODE_STA_STATISTICS_AVG_AIR_TIME, + + NL80211_TESTMODE_STA_STATISTICS_TC_EMPTY_CNT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_QUE_LEN_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_TC_AVG_QUE_LEN_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_TC_CUR_QUE_LEN_ARRAY, + + /* + * how many packages TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_ENQUEUE, + + /* + * how many packages this TX during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_ENQUEUE, + + /* + * how many packages dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_DEQUEUE, + + /* + * how many packages this sta dequeue during statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_STA_DEQUEUE, + + /* + * how many TC[0-3] resource back from firmware during + * statistics interval + */ + NL80211_TESTMODE_STA_STATISTICS_RB_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_NO_TC_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_USED_BFCT_ARRAY, + NL80211_TESTMODE_STA_STATISTICS_WANTED_BFCT_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_ISR_PASS_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TASK_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_AB_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_SW_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_TX_CNT, + NL80211_TESTMODE_STA_STATISTICS_IRQ_RX_CNT, + + NL80211_TESTMODE_STA_STATISTICS_RESERVED_ARRAY, + + NL80211_TESTMODE_STA_STATISTICS_NUM +} ENUM_TESTMODE_STA_STATISTICS_ATTR; +typedef struct _NL80211_DRIVER_SET_NFC_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 NFC_Enable; + +} NL80211_DRIVER_SET_NFC_PARAMS, *P_NL80211_DRIVER_SET_NFC_PARAMS; +typedef struct _NL80211_DRIVER_GET_SCANDONE_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4ScanDone; + +} NL80211_DRIVER_GET_SCANDONE_PARAMS, *P_NL80211_DRIVER_GET_SCANDONE_PARAMS; + +typedef enum _ENUM_TESTMODE_LINK_DETECTION_ATTR { + NL80211_TESTMODE_LINK_INVALID = 0, + NL80211_TESTMODE_LINK_TX_FAIL_CNT, + NL80211_TESTMODE_LINK_TX_RETRY_CNT, + NL80211_TESTMODE_LINK_TX_MULTI_RETRY_CNT, + NL80211_TESTMODE_LINK_ACK_FAIL_CNT, + NL80211_TESTMODE_LINK_FCS_ERR_CNT, + + NL80211_TESTMODE_LINK_DETECT_NUM, +} ENUM_TESTMODE_LINK_DETECTION_ATTR; + +#if CFG_AUTO_CHANNEL_SEL_SUPPORT + +typedef struct _NL80211_DRIVER_GET_LTE_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_32 u4Version; + UINT_32 u4Flag; + +} NL80211_DRIVER_GET_LTE_PARAMS, *P_NL80211_DRIVER_GET_LTE_PARAMS; + +/*typedef enum _ENUM_TESTMODE_AVAILABLE_CHAN_ATTR{ + NL80211_TESTMODE_AVAILABLE_CHAN_INVALID = 0, + NL80211_TESTMODE_AVAILABLE_CHAN_2G_BASE_1, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_34, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_149, + NL80211_TESTMODE_AVAILABLE_CHAN_5G_BASE_184, + + NL80211_TESTMODE_AVAILABLE_CHAN_NUM, +}ENUM_TESTMODE_AVAILABLE_CHAN_ATTR;*/ + +#endif +#endif +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* cfg80211 hooks */ +int +mtk_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, enum nl80211_iftype type,/* u32 *flags,*/ struct vif_params *params); + +int +mtk_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); + +int +mtk_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) +); + +int +mtk_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr); + +int +mtk_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_index, bool unicast, bool multicast); + +int mtk_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index); + +int mtk_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac, struct station_info *sinfo); + +int mtk_cfg80211_add_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_parameters *params); + +int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, struct station_del_parameters *params); +//int mtk_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, const u8 *mac); + +int mtk_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); + +int mtk_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme); + +int mtk_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code); + +int mtk_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params); + +int mtk_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev); + +int mtk_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, bool enabled, int timeout); + +int mtk_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); + +int mtk_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa); + +int mtk_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev); + +int mtk_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + unsigned int duration, u64 *cookie); + +int mtk_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int +mtk_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +void mtk_cfg80211_mgmt_frame_register(IN struct wiphy *wiphy, + IN struct wireless_dev *wdev, + IN u16 frame_type, IN bool reg); + +int mtk_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_cfg80211_assoc(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_assoc_request *req); + +int +mtk_cfg80211_sched_scan_start(IN struct wiphy *wiphy, + IN struct net_device *ndev, IN struct cfg80211_sched_scan_request *request); + +int mtk_cfg80211_sched_scan_stop(IN struct wiphy *wiphy, IN struct net_device *ndev,u64 reqid); + +#if CONFIG_NL80211_TESTMODE +#if CFG_AUTO_CHANNEL_SEL_SUPPORT +WLAN_STATUS +wlanoidQueryACSChannelList(IN P_ADAPTER_T prAdapter, + IN PVOID pvQueryBuffer, IN UINT_32 u4QueryBufferLen, OUT PUINT_32 pu4QueryInfoLen); + +int +mtk_cfg80211_testmode_get_lte_channel(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); +#endif +int +mtk_cfg80211_testmode_get_sta_statistics(IN struct wiphy *wiphy, + IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_get_scan_done(IN struct wiphy *wiphy, IN void *data, IN int len, IN P_GLUE_INFO_T prGlueInfo); + +int mtk_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); + +int mtk_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#if CFG_SUPPORT_WAPI +int mtk_cfg80211_testmode_set_key_ext(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +int mtk_cfg80211_testmode_hs20_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#if CFG_ENABLE_WIFI_DIRECT && CFG_ENABLE_WIFI_DIRECT_CFG_80211 +int mtk_p2p_cfg80211_testmode_sw_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" +#endif +int mtk_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); +int mtk_cfg80211_resume(struct wiphy *wiphy); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_CFG80211_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h new file mode 100644 index 0000000000000..1406905095e64 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_kal.h @@ -0,0 +1,1565 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_kal.h#1 +*/ + +/*! \file gl_kal.h + \brief Declaration of KAL functions - kal*() which is provided by GLUE Layer. + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/* +** Log: gl_kal.h + * + * 06 13 2012 yuche.tsai + * NULL + * Update maintrunk driver. + * Add support for driver compose assoc request frame. + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 03 02 2012 terry.wu + * NULL + * Snc CFG80211 modification for ICS migration from branch 2.2. + * + * 02 06 2012 wh.su + * [WCXRP00001177] [MT6620 Wi-Fi][Driver][2.2] Adding the query channel filter for AP mode + * adding the channel query filter for AP mode. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 11 24 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adjust the code for Non-DBG and no XLOG. + * + * 11 22 2011 cp.wu + * [WCXRP00001120] [MT6620 Wi-Fi][Driver] Modify roaming to AIS state transition from synchronous to asynchronous + * approach to avoid incomplete state termination + * 1. change RDD related compile option brace position. + * 2. when roaming is triggered, ask AIS to transit immediately only when AIS is in Normal TR state without join + * timeout timer ticking + * 3. otherwise, insert AIS_REQUEST into pending request queue + * + * 11 11 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * modify the xlog related code. + * + * 11 10 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Modify the QM xlog level and remove LOG_FUNC. + * + * 11 10 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Using the new XLOG define for dum Memory. + * + * 11 08 2011 eddie.chen + * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog) + * Add xlog function. + * + * 11 08 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters, eCurPsProf, for PS. + * + * 11 08 2011 cm.chang + * NULL + * Add RLM and CNM debug message for XLOG + * + * 11 07 2011 tsaiyuan.hsu + * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered + * add debug counters and periodically dump counters for debugging. + * + * 11 03 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * Add dumpMemory8 at XLOG support. + * + * 11 02 2011 wh.su + * [WCXRP00001078] [MT6620 Wi-Fi][Driver] Adding the mediatek log improment support : XLOG + * adding the code for XLOG. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated + * network type + * include link.h for linux's port. + * + * 04 12 2011 cp.wu + * [WCXRP00000635] [MT6620 Wi-Fi][Driver] Clear pending security frames when QM clear pending data frames for dedicated + * network type + * clear pending security frames for dedicated network type when BSS is being deactivated/disconnected + * + * 04 01 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * 1. simplify config.h due to aggregation options could be also applied for eHPI/SPI interface + * 2. use spin-lock instead of semaphore for protecting eHPI access because of possible access from ISR + * 3. request_irq() API has some changes between linux kernel 2.6.12 and 2.6.26 + * + * 03 16 2011 cp.wu + * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage + * after system running for a long period + * 1. pre-allocate physical continuous buffer while module is being loaded + * 2. use pre-allocated physical continuous buffer for TX/RX DMA transfer + * + * The windows part remained the same as before, but added similar APIs to hide the difference. + * + * 03 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Add BOW table. + * + * 03 07 2011 terry.wu + * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message + * Toggle non-standard debug messages to comments. + * + * 03 06 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Sync BOW Driver to latest person development branch version.. + * + * 03 02 2011 cp.wu + * [WCXRP00000503] [MT6620 Wi-Fi][Driver] Take RCPI brought by association response as initial RSSI right after + * connection is built. + * use RCPI brought by ASSOC-RESP after connection is built as initial RCPI to avoid using a uninitialized MAC-RX RCPI. + * + * 02 24 2011 cp.wu + * [WCXRP00000490] [MT6620 Wi-Fi][Driver][Win32] modify kalMsleep() implementation because NdisMSleep() won't sleep + * long enough for specified interval such as 500ms + * modify cnm_timer and hem_mbox APIs to be thread safe to ease invoking restrictions + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 04 2011 cp.wu + * [WCXRP00000338] [MT6620 Wi-Fi][Driver] Separate kalMemAlloc into kmalloc and vmalloc implementations to ease + * physically continuous memory demands + * separate kalMemAlloc() into virtually-continuous and physically-continuous type to ease slab system pressure + * + * 12 31 2010 cp.wu + * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system + * scheduling + * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being + * loaded + * + * 12 31 2010 jeffrey.chang + * [WCXRP00000332] [MT6620 Wi-Fi][Driver] add kal sleep function for delay which use blocking call + * modify the implementation of kalDelay to msleep + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 11 30 2010 yuche.tsai + * NULL + * Invitation & Provision Discovery Indication. + * + * 11 26 2010 cp.wu + * [WCXRP00000209] [MT6620 Wi-Fi][Driver] Modify NVRAM checking mechanism to warning only with necessary data field + * checking + * 1. NVRAM error is now treated as warning only, thus normal operation is still available but extra scan result used + * to indicate user is attached + * 2. DPD and TX-PWR are needed fields from now on, if these 2 fields are not available then warning message is shown + * + * 11 08 2010 cp.wu + * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period + * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * add a kal function for set cipher. + * + * 10 04 2010 wh.su + * [WCXRP00000081] [MT6620][Driver] Fix the compiling error at WinXP while enable P2P + * fixed compiling error while enable p2p. + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 21 2010 cp.wu + * [WCXRP00000053] [MT6620 Wi-Fi][Driver] Reset incomplete and might leads to BSOD when entering RF test with AIS + * associated + * Do a complete reset with STA-REC null checking for RF test re-entry + * + * 09 21 2010 kevin.huang + * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning + * Eliminate Linux Compile Warning + * + * 09 10 2010 wh.su + * NULL + * fixed the compiling error at win XP. + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct Driver Hook] change event indication API to be consistent with supplicant + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 08 02 2010 jeffrey.chang + * NULL + * modify kalSetEvent declaration + * + * 07 29 2010 cp.wu + * NULL + * simplify post-handling after TX_DONE interrupt is handled. + * + * 07 23 2010 cp.wu + * + * 1) re-enable AIS-FSM beacon timeout handling. + * 2) scan done API revised + * + * 07 23 2010 jeffrey.chang + * + * fix kal header file + * + * 07 22 2010 jeffrey.chang + * + * use different spin lock for security frame + * + * 07 22 2010 jeffrey.chang + * + * add new spinlock + * + * 07 19 2010 jeffrey.chang + * + * add kal api for scanning done + * + * 07 19 2010 jeffrey.chang + * + * modify cmd/data path for new design + * + * 07 19 2010 jeffrey.chang + * + * add new kal api + * + * 07 19 2010 jeffrey.chang + * + * Linux port modification + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 21 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * change MAC address updating logic. + * + * 06 18 2010 cm.chang + * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver + * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf + * + * 06 11 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * 1) migrate assoc.c. + * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness + * 3) add configuration options for CNM_MEM and RSN modules + * 4) add data path for management frames + * 5) eliminate rPacketInfo of MSDU_INFO_T + * + * 06 07 2010 cp.wu + * [WPD00003833][MT6620 and MT5931] Driver migration + * gl_kal merged + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic handling framework for wireless extension ioctls. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * fill network type field while doing frame identification. + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * modify kalMemAlloc method + * + * 04 28 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change prefix for data structure used to communicate with 802.11 PAL + * to avoid ambiguous naming with firmware interface + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 22 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * when acquiring driver-own, wait for up to 8 seconds. + * + * 04 22 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * + * 1) modify rx path code for supporting Wi-Fi direct + * 2) modify config.h since Linux dont need to consider retaining packet + * + * 04 21 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add for private ioctl support + * + * 04 20 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * don't need SPIN_LOCK_PWR_CTRL anymore, it will raise IRQL + * * and cause SdBusSubmitRequest running at DISPATCH_LEVEL as well. + * + * 04 14 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * information buffer for query oid/ioctl is now buffered in prCmdInfo + * * * * * * * * instead of glue-layer variable to improve multiple oid/ioctl capability + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple handler + * * * * * * * * * * * * * * * * * * * capability + * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other purpose + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) add spinlock + * * * 2) add KAPI for handling association info + * + * 04 09 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * adding firmware download KAPI + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * finish non-glue layer access to glue variables + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * accessing to firmware load/start address, and access to OID handling information + * * * * are now handled in glue layer + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * * are done in adapter layer. + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->eParamMediaStateIndicated from non-glue layer + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * add KAL API: kalFlushPendingTxPackets(), and take use of the API + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access to prGlueInfo->rWlanInfo.eLinkAttr.ucMediaStreamMode from non-glue layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) for some OID, never do timeout expiration + * * * * 2) add 2 kal API for later integration + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download KAPI + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\41 2009-09-28 20:19:23 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\40 2009-08-18 22:57:09 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\39 2009-06-23 23:19:15 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\38 2009-02-09 14:03:17 GMT mtk01090 +** Add KAL function kalDevSetPowerState(). It is not implemented yet. Only add an empty macro. +** +** \main\maintrunk.MT5921\37 2009-01-22 13:05:59 GMT mtk01088 +** new defeine to got 1x value at packet reserved field +** \main\maintrunk.MT5921\36 2008-12-08 16:15:02 GMT mtk01461 +** Add kalQueryValidBufferLength() macro +** \main\maintrunk.MT5921\35 2008-11-13 20:33:15 GMT mtk01104 +** Remove lint warning +** \main\maintrunk.MT5921\34 2008-10-22 11:05:52 GMT mtk01461 +** Remove unused macro +** \main\maintrunk.MT5921\33 2008-10-16 15:48:17 GMT mtk01461 +** Update driver to fix lint warning +** \main\maintrunk.MT5921\32 2008-09-02 11:50:51 GMT mtk01461 +** SPIN_LOCK_SDIO_DDK_TX_QUE +** \main\maintrunk.MT5921\31 2008-08-29 15:58:30 GMT mtk01088 +** remove non-used function for code refine +** \main\maintrunk.MT5921\30 2008-08-21 00:33:29 GMT mtk01461 +** Update for Driver Review +** \main\maintrunk.MT5921\29 2008-06-19 13:29:14 GMT mtk01425 +** 1. Add declaration of SPIN_LOCK_SDIO_DDK_TX_QUE and SPIN_LOCK_SDIO_DDK_RX_QUE +** \main\maintrunk.MT5921\28 2008-05-30 20:27:34 GMT mtk01461 +** Rename KAL function +** \main\maintrunk.MT5921\27 2008-05-30 14:42:05 GMT mtk01461 +** Remove WMM Assoc Flag in KAL +** \main\maintrunk.MT5921\26 2008-05-29 14:15:18 GMT mtk01084 +** remove un-used function +** \main\maintrunk.MT5921\25 2008-04-23 14:02:20 GMT mtk01084 +** modify KAL port access function prototype +** \main\maintrunk.MT5921\24 2008-04-17 23:06:41 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\23 2008-04-08 15:38:50 GMT mtk01084 +** add KAL function to setting pattern search function enable/ disable +** \main\maintrunk.MT5921\22 2008-03-26 15:34:48 GMT mtk01461 +** Add update MAC address func +** \main\maintrunk.MT5921\21 2008-03-18 15:56:15 GMT mtk01084 +** update ENUM_NIC_INITIAL_PARAM_E +** \main\maintrunk.MT5921\20 2008-03-18 11:49:28 GMT mtk01084 +** update function for initial value access +** \main\maintrunk.MT5921\19 2008-03-18 10:21:31 GMT mtk01088 +** use kal update associate request at linux +** \main\maintrunk.MT5921\18 2008-03-14 18:03:41 GMT mtk01084 +** refine register and port access function +** \main\maintrunk.MT5921\17 2008-03-11 14:51:02 GMT mtk01461 +** Add copy_to(from)_user macro +** \main\maintrunk.MT5921\16 2008-03-06 23:42:21 GMT mtk01385 +** 1. add Query Registry Mac address function. +** \main\maintrunk.MT5921\15 2008-02-26 09:48:04 GMT mtk01084 +** modify KAL set network address/ checksum offload part +** \main\maintrunk.MT5921\14 2008-01-09 17:54:58 GMT mtk01084 +** Modify the argument of kalQueryPacketInfo +** \main\maintrunk.MT5921\13 2007-11-29 02:05:20 GMT mtk01461 +** Fix Windows RX multiple packet retain problem +** \main\maintrunk.MT5921\12 2007-11-26 19:43:45 GMT mtk01461 +** Add OS_TIMESTAMP macro +** +** \main\maintrunk.MT5921\11 2007-11-09 16:36:15 GMT mtk01425 +** 1. Modify for CSUM offloading with Tx Fragment +** \main\maintrunk.MT5921\10 2007-11-07 18:38:37 GMT mtk01461 +** Add Tx Fragmentation Support +** \main\maintrunk.MT5921\9 2007-11-06 19:36:50 GMT mtk01088 +** add the WPS related code +** \main\maintrunk.MT5921\8 2007-11-02 01:03:57 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** Revision 1.4 2007/07/05 07:25:33 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:50 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:23 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +#ifndef _GL_KAL_H +#define _GL_KAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "config.h" +#include "gl_typedef.h" +#include "gl_os.h" +#include "link.h" +#include "nic/mac.h" +#include "nic/wlan_def.h" +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "gl_wext_priv.h" +#include + +#if CFG_ENABLE_BT_OVER_WIFI +#include "nic/bow.h" +#endif + +#if DBG +extern int allocatedMemSize; +#endif + +#if CFG_SUPPORT_MET_PROFILING +#include "linux/kallsyms.h" +#include +#endif + +extern BOOLEAN fgIsUnderSuspend; +extern UINT_32 TaskIsrCnt; +extern BOOLEAN fgIsResetting; +extern int wlanHardStartXmit(struct sk_buff *prSkb, struct net_device *prDev); +extern UINT_32 u4MemAllocCnt, u4MemFreeCnt; + + +extern struct delayed_work sched_workq; + +#if defined(MT6620) && CFG_MULTI_ECOVER_SUPPORT +extern ENUM_WMTHWVER_TYPE_T mtk_wcn_wmt_hwver_get(VOID); +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* #define USEC_PER_MSEC (1000) */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum _ENUM_SPIN_LOCK_CATEGORY_E { + SPIN_LOCK_FSM = 0, + + /* FIX ME */ + SPIN_LOCK_RX_QUE, + SPIN_LOCK_TX_QUE, + SPIN_LOCK_CMD_QUE, + SPIN_LOCK_TX_RESOURCE, + SPIN_LOCK_CMD_RESOURCE, + SPIN_LOCK_QM_TX_QUEUE, + SPIN_LOCK_CMD_PENDING, + SPIN_LOCK_CMD_SEQ_NUM, + SPIN_LOCK_TX_MSDU_INFO_LIST, + SPIN_LOCK_TXING_MGMT_LIST, + SPIN_LOCK_TX_SEQ_NUM, + SPIN_LOCK_TX_COUNT, + SPIN_LOCK_TXS_COUNT, + /* end */ + SPIN_LOCK_TX, + SPIN_LOCK_IO_REQ, + SPIN_LOCK_INT, + + SPIN_LOCK_MGT_BUF, + SPIN_LOCK_MSG_BUF, + SPIN_LOCK_STA_REC, + + SPIN_LOCK_MAILBOX, + SPIN_LOCK_TIMER, + + SPIN_LOCK_BOW_TABLE, + + SPIN_LOCK_EHPI_BUS, /* only for EHPI */ + SPIN_LOCK_NET_DEV, + SPIN_LOCK_NUM +} ENUM_SPIN_LOCK_CATEGORY_E; + +/* event for assoc information update */ +typedef struct _EVENT_ASSOC_INFO { + UINT_8 ucAssocReq; /* 1 for assoc req, 0 for assoc rsp */ + UINT_8 ucReassoc; /* 0 for assoc, 1 for reassoc */ + UINT_16 u2Length; + PUINT_8 pucIe; +} EVENT_ASSOC_INFO, *P_EVENT_ASSOC_INFO; + +typedef enum _ENUM_KAL_NETWORK_TYPE_INDEX_T { + KAL_NETWORK_TYPE_AIS_INDEX = 0, +#if CFG_ENABLE_WIFI_DIRECT + KAL_NETWORK_TYPE_P2P_INDEX, +#endif +#if CFG_ENABLE_BT_OVER_WIFI + KAL_NETWORK_TYPE_BOW_INDEX, +#endif + KAL_NETWORK_TYPE_INDEX_NUM +} ENUM_KAL_NETWORK_TYPE_INDEX_T; + +typedef enum _ENUM_KAL_MEM_ALLOCATION_TYPE_E { + PHY_MEM_TYPE, /* physically continuous */ + VIR_MEM_TYPE, /* virtually continuous */ + MEM_TYPE_NUM +} ENUM_KAL_MEM_ALLOCATION_TYPE; + +#if CONFIG_ANDROID /* Defined in Android kernel source */ +typedef struct wake_lock KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#else +typedef UINT_32 KAL_WAKE_LOCK_T, *P_KAL_WAKE_LOCK_T; +#endif + +#if CFG_SUPPORT_AGPS_ASSIST +typedef enum _ENUM_MTK_AGPS_ATTR { + MTK_ATTR_AGPS_INVALID, + MTK_ATTR_AGPS_CMD, + MTK_ATTR_AGPS_DATA, + MTK_ATTR_AGPS_IFINDEX, + MTK_ATTR_AGPS_IFNAME, + MTK_ATTR_AGPS_MAX +} ENUM_MTK_CCX_ATTR; + +typedef enum _ENUM_AGPS_EVENT { + AGPS_EVENT_WLAN_ON, + AGPS_EVENT_WLAN_OFF, + AGPS_EVENT_WLAN_AP_LIST, + WIFI_EVENT_CHIP_RESET, +} ENUM_CCX_EVENT; +BOOLEAN kalIndicateAgpsNotify(P_ADAPTER_T prAdapter, UINT_8 cmd, PUINT_8 data, UINT_16 dataLen); +#endif + +struct KAL_HALT_CTRL_T { + struct semaphore lock; + struct task_struct *owner; + BOOLEAN fgHalt; + BOOLEAN fgHeldByKalIoctl; + OS_SYSTIME u4HoldStart; +}; +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/*----------------------------------------------------------------------------*/ +/* Macros of bit operation */ +/*----------------------------------------------------------------------------*/ +#define KAL_SET_BIT(bitOffset, value) set_bit(bitOffset, &value) +#define KAL_CLR_BIT(bitOffset, value) clear_bit(bitOffset, &value) +#define KAL_TEST_AND_CLEAR_BIT(bitOffset, value) test_and_clear_bit(bitOffset, &value) +#define KAL_TEST_BIT(bitOffset, value) test_bit(bitOffset, &value) + +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#define KAL_SPIN_LOCK_DECLARATION() unsigned long __u4Flags + +#define KAL_ACQUIRE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalAcquireSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, &__u4Flags) + +#define KAL_RELEASE_SPIN_LOCK(_prAdapter, _rLockCategory) \ + kalReleaseSpinLock(((P_ADAPTER_T)_prAdapter)->prGlueInfo, _rLockCategory, __u4Flags) + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define KAL_GET_PKT_QUEUE_ENTRY(_p) GLUE_GET_PKT_QUEUE_ENTRY(_p) +#define KAL_GET_PKT_DESCRIPTOR(_prQueueEntry) GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) +#define KAL_GET_PKT_TID(_p) GLUE_GET_PKT_TID(_p) +#define KAL_GET_PKT_IS1X(_p) GLUE_GET_PKT_IS1X(_p) +#define KAL_GET_PKT_HEADER_LEN(_p) GLUE_GET_PKT_HEADER_LEN(_p) +#define KAL_GET_PKT_PAYLOAD_LEN(_p) GLUE_GET_PKT_PAYLOAD_LEN(_p) +#define KAL_GET_PKT_ARRIVAL_TIME(_p) GLUE_GET_PKT_ARRIVAL_TIME(_p) + +/*----------------------------------------------------------------------------*/ +/* Macros of wake_lock operations for using in Driver Layer */ +/*----------------------------------------------------------------------------*/ +#if CONFIG_ANDROID /* Defined in Android kernel source */ +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) \ + wake_lock_init(_prWakeLock, WAKE_LOCK_SUSPEND, _pcName) + +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) \ + wake_lock_destroy(_prWakeLock) + +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) \ + wake_lock(_prWakeLock) + +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) \ + wake_lock_timeout(_prWakeLock, _u4Timeout) + +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) \ + wake_unlock(_prWakeLock) + +#else +#define KAL_WAKE_LOCK_INIT(_prAdapter, _prWakeLock, _pcName) +#define KAL_WAKE_LOCK_DESTROY(_prAdapter, _prWakeLock) +#define KAL_WAKE_LOCK(_prAdapter, _prWakeLock) +#define KAL_WAKE_LOCK_TIMEOUT(_prAdapter, _prWakeLock, _u4Timeout) +#define KAL_WAKE_UNLOCK(_prAdapter, _prWakeLock) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Cache memory allocation +* +* \param[in] u4Size Required memory size. +* \param[in] eMemType Memory allocation type +* +* \return Pointer to allocated memory +* or NULL +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + if (pvAddr) { \ + allocatedMemSize += u4Size; \ + DBGLOG(INIT, INFO, "%p(%u) allocated (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + pvAddr; \ +}) +#else +#define kalMemAlloc(u4Size, eMemType) ({ \ + void *pvAddr; \ + if (eMemType == PHY_MEM_TYPE) { \ + pvAddr = kmalloc(u4Size, GFP_KERNEL); \ + } \ + else { \ + pvAddr = vmalloc(u4Size); \ + } \ + pvAddr; \ +}) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Free allocated cache memory +* +* \param[in] pvAddr Required memory size. +* \param[in] eMemType Memory allocation type +* \param[in] u4Size Allocated memory size. +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#if DBG +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (pvAddr) { \ + allocatedMemSize -= u4Size; \ + DBGLOG(INIT, INFO, "%p(%u) freed (%s:%s)\n", \ + pvAddr, (UINT_32)u4Size, __FILE__, __func__); \ + } \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#else +#define kalMemFree(pvAddr, eMemType, u4Size) \ +{ \ + if (eMemType == PHY_MEM_TYPE) { \ + kfree(pvAddr); \ + } \ + else { \ + vfree(pvAddr); \ + } \ +} +#endif + +#define kalUdelay(u4USec) udelay(u4USec) + +#define kalMdelay(u4MSec) mdelay(u4MSec) +#define kalMsleep(u4MSec) msleep(u4MSec) + +/* Copy memory from user space to kernel space */ +#define kalMemCopyFromUser(_pvTo, _pvFrom, _u4N) copy_from_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory from kernel space to user space */ +#define kalMemCopyToUser(_pvTo, _pvFrom, _u4N) copy_to_user(_pvTo, _pvFrom, _u4N) + +/* Copy memory block with specific size */ +#define kalMemCopy(pvDst, pvSrc, u4Size) memcpy(pvDst, pvSrc, u4Size) + +/* Set memory block with specific pattern */ +#define kalMemSet(pvAddr, ucPattern, u4Size) memset(pvAddr, ucPattern, u4Size) + +/* Compare two memory block with specific length. + * Return zero if they are the same. + */ +#define kalMemCmp(pvAddr1, pvAddr2, u4Size) memcmp(pvAddr1, pvAddr2, u4Size) + +/* Zero specific memory block */ +#define kalMemZero(pvAddr, u4Size) memset(pvAddr, 0, u4Size) + +/* string operation */ +#define kalStrCpy(dest, src) strcpy(dest, src) +#define kalStrnCpy(dest, src, n) strncpy(dest, src, n) +#define kalStrCmp(ct, cs) strcmp(ct, cs) +#define kalStrnCmp(ct, cs, n) strncmp(ct, cs, n) +#define kalStrChr(s, c) strchr(s, c) +#define kalStrrChr(s, c) strrchr(s, c) +#define kalStrnChr(s, n, c) strnchr(s, n, c) +#define kalStrLen(s) strlen(s) +#define kalStrnLen(s, b) strnlen(s, b) +//#define kalStrniCmp(s1, s2, n) strnicmp(s1, s2, n) +#define kalStrniCmp(s1, s2, n) strncasecmp(s1, s2, n) +#define strnicmp(s1, s2, n) strncasecmp(s1, s2, n) +/* #define kalStrtoul(cp, endp, base) simple_strtoul(cp, endp, base) +#define kalStrtol(cp, endp, base) simple_strtol(cp, endp, base) */ +#define kalkStrtou32(cp, base, resp) kstrtou32(cp, base, resp) +#define kalkStrtos32(cp, base, resp) kstrtos32(cp, base, resp) +#define kalSnprintf(buf, size, fmt, ...) snprintf(buf, size, fmt, __VA_ARGS__) +#define kalSprintf(buf, fmt, ...) sprintf(buf, fmt, __VA_ARGS__) +/* remove for AOSP */ +/* #define kalSScanf(buf, fmt, ...) sscanf(buf, fmt, __VA_ARGS__) */ +#define kalStrStr(ct, cs) strstr(ct, cs) +#define kalStrSep(s, ct) strsep(s, ct) +#define kalStrCat(dest, src) strcat(dest, src) + +/* defined for wince sdio driver only */ +#if defined(_HIF_SDIO) +#define kalDevSetPowerState(prGlueInfo, ePowerMode) glSetPowerState(prGlueInfo, ePowerMode) +#else +#define kalDevSetPowerState(prGlueInfo, ePowerMode) +#endif + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Notify OS with SendComplete event of the specific packet. Linux should +* free packets here. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] status Status Code for OS upper layer +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalSendComplete(prGlueInfo, pvPacket, status) \ + kalSendCompleteAndAwakeQueue(prGlueInfo, pvPacket) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to locate the starting address of incoming ethernet +* frame for skb. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryBufferPointer(prGlueInfo, pvPacket) \ + ((PUINT_8)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to query the length of valid buffer which is accessible during +* port read/write. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* +* \return starting address of ethernet frame buffer. +*/ +/*----------------------------------------------------------------------------*/ +#define kalQueryValidBufferLength(prGlueInfo, pvPacket) \ + ((UINT_32)((struct sk_buff *)pvPacket)->end - \ + (UINT_32)((struct sk_buff *)pvPacket)->data) + +/*----------------------------------------------------------------------------*/ +/*! +* \brief This function is used to copy the entire frame from skb to the destination +* address in the input parameter. +* +* \param[in] prGlueInfo Pointer of GLUE Data Structure +* \param[in] pvPacket Pointer of Packet Handle +* \param[in] pucDestBuffer Destination Address +* +* \return - +*/ +/*----------------------------------------------------------------------------*/ +#define kalCopyFrame(prGlueInfo, pvPacket, pucDestBuffer) \ + do {struct sk_buff *skb = (struct sk_buff *)pvPacket; \ + memcpy(pucDestBuffer, skb->data, skb->len); } while (0) + +#define kalGetTimeTick() jiffies_to_msecs(jiffies) + +#define kalPrint pr_debug + +#if !DBG +#define AIS_ERROR_LOGFUNC(_Fmt...) +#define AIS_WARN_LOGFUNC(_Fmt...) +#define AIS_INFO_LOGFUNC(_Fmt...) +#define AIS_STATE_LOGFUNC(_Fmt...) +#define AIS_EVENT_LOGFUNC(_Fmt...) +#define AIS_TRACE_LOGFUNC(_Fmt...) +#define AIS_LOUD_LOGFUNC(_Fmt...) +#define AIS_TEMP_LOGFUNC(_Fmt...) + +#define INTR_ERROR_LOGFUNC(_Fmt...) +#define INTR_WARN_LOGFUNC(_Fmt...) +#define INTR_INFO_LOGFUNC(_Fmt...) +#define INTR_STATE_LOGFUNC(_Fmt...) +#define INTR_EVENT_LOGFUNC(_Fmt...) +#define INTR_TRACE_LOGFUNC(_Fmt...) +#define INTR_LOUD_LOGFUNC(_Fmt...) +#define INTR_TEMP_LOGFUNC(_Fmt...) + +#define INIT_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define INIT_TRACE_LOGFUNC(_Fmt...) +#define INIT_LOUD_LOGFUNC(_Fmt...) +#define INIT_TEMP_LOGFUNC(_Fmt...) + +#define AAA_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_STATE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_EVENT_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define AAA_LOUD_LOGFUNC(_Fmt...) +#define AAA_TEMP_LOGFUNC(_Fmt...) + +#define ROAMING_ERROR_LOGFUNC(_Fmt...) +#define ROAMING_WARN_LOGFUNC(_Fmt...) +#define ROAMING_INFO_LOGFUNC(_Fmt...) +#define ROAMING_STATE_LOGFUNC(_Fmt...) +#define ROAMING_EVENT_LOGFUNC(_Fmt...) +#define ROAMING_TRACE_LOGFUNC(_Fmt...) +#define ROAMING_LOUD_LOGFUNC(_Fmt...) +#define ROAMING_TEMP_LOGFUNC(_Fmt...) + +#define REQ_ERROR_LOGFUNC(_Fmt...) +#define REQ_WARN_LOGFUNC(_Fmt...) +#define REQ_INFO_LOGFUNC(_Fmt...) +#define REQ_STATE_LOGFUNC(_Fmt...) +#define REQ_EVENT_LOGFUNC(_Fmt...) +#define REQ_TRACE_LOGFUNC(_Fmt...) +#define REQ_LOUD_LOGFUNC(_Fmt...) +#define REQ_TEMP_LOGFUNC(_Fmt...) + +#define TX_ERROR_LOGFUNC(_Fmt...) +#define TX_WARN_LOGFUNC(_Fmt...) +#define TX_INFO_LOGFUNC(_Fmt...) +#define TX_STATE_LOGFUNC(_Fmt...) +#define TX_EVENT_LOGFUNC(_Fmt...) +#define TX_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define TX_LOUD_LOGFUNC(_Fmt...) +#define TX_TEMP_LOGFUNC(_Fmt...) + +#define RX_ERROR_LOGFUNC(_Fmt...) +#define RX_WARN_LOGFUNC(_Fmt...) +#define RX_INFO_LOGFUNC(_Fmt...) +#define RX_STATE_LOGFUNC(_Fmt...) +#define RX_EVENT_LOGFUNC(_Fmt...) +#define RX_TRACE_LOGFUNC(_Fmt...) +#define RX_LOUD_LOGFUNC(_Fmt...) +#define RX_TEMP_LOGFUNC(_Fmt...) + +#define RFTEST_ERROR_LOGFUNC(_Fmt...) +#define RFTEST_WARN_LOGFUNC(_Fmt...) +#define RFTEST_INFO_LOGFUNC(_Fmt...) +#define RFTEST_STATE_LOGFUNC(_Fmt...) +#define RFTEST_EVENT_LOGFUNC(_Fmt...) +#define RFTEST_TRACE_LOGFUNC(_Fmt...) +#define RFTEST_LOUD_LOGFUNC(_Fmt...) +#define RFTEST_TEMP_LOGFUNC(_Fmt...) + +#define EMU_ERROR_LOGFUNC(_Fmt...) +#define EMU_WARN_LOGFUNC(_Fmt...) +#define EMU_INFO_LOGFUNC(_Fmt...) +#define EMU_STATE_LOGFUNC(_Fmt...) +#define EMU_EVENT_LOGFUNC(_Fmt...) +#define EMU_TRACE_LOGFUNC(_Fmt...) +#define EMU_LOUD_LOGFUNC(_Fmt...) +#define EMU_TEMP_LOGFUNC(_Fmt...) + +#define HEM_ERROR_LOGFUNC(_Fmt...) +#define HEM_WARN_LOGFUNC(_Fmt...) +#define HEM_INFO_LOGFUNC(_Fmt...) +#define HEM_STATE_LOGFUNC(_Fmt...) +#define HEM_EVENT_LOGFUNC(_Fmt...) +#define HEM_TRACE_LOGFUNC(_Fmt...) +#define HEM_LOUD_LOGFUNC(_Fmt...) +#define HEM_TEMP_LOGFUNC(_Fmt...) + +#define RLM_ERROR_LOGFUNC(_Fmt...) +#define RLM_WARN_LOGFUNC(_Fmt...) +#define RLM_INFO_LOGFUNC(_Fmt...) +#define RLM_STATE_LOGFUNC(_Fmt...) +#define RLM_EVENT_LOGFUNC(_Fmt...) +#define RLM_TRACE_LOGFUNC(_Fmt...) +#define RLM_LOUD_LOGFUNC(_Fmt...) +#define RLM_TEMP_LOGFUNC(_Fmt...) + +#define MEM_ERROR_LOGFUNC(_Fmt...) +#define MEM_WARN_LOGFUNC(_Fmt...) +#define MEM_INFO_LOGFUNC(_Fmt...) +#define MEM_STATE_LOGFUNC(_Fmt...) +#define MEM_EVENT_LOGFUNC(_Fmt...) +#define MEM_TRACE_LOGFUNC(_Fmt...) +#define MEM_LOUD_LOGFUNC(_Fmt...) +#define MEM_TEMP_LOGFUNC(_Fmt...) + +#define CNM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define CNM_STATE_LOGFUNC(_Fmt...) +#define CNM_EVENT_LOGFUNC(_Fmt...) +#define CNM_TRACE_LOGFUNC(_Fmt...) +#define CNM_LOUD_LOGFUNC(_Fmt...) +#define CNM_TEMP_LOGFUNC(_Fmt...) + +#define RSN_ERROR_LOGFUNC(_Fmt...) +#define RSN_WARN_LOGFUNC(_Fmt...) +#define RSN_INFO_LOGFUNC(_Fmt...) +#define RSN_STATE_LOGFUNC(_Fmt...) +#define RSN_EVENT_LOGFUNC(_Fmt...) +#define RSN_TRACE_LOGFUNC(_Fmt...) +#define RSN_LOUD_LOGFUNC(_Fmt...) +#define RSN_TEMP_LOGFUNC(_Fmt...) + +#define BSS_ERROR_LOGFUNC(_Fmt...) +#define BSS_WARN_LOGFUNC(_Fmt...) +#define BSS_INFO_LOGFUNC(_Fmt...) +#define BSS_STATE_LOGFUNC(_Fmt...) +#define BSS_EVENT_LOGFUNC(_Fmt...) +#define BSS_TRACE_LOGFUNC(_Fmt...) +#define BSS_LOUD_LOGFUNC(_Fmt...) +#define BSS_TEMP_LOGFUNC(_Fmt...) + +#define SCN_ERROR_LOGFUNC(_Fmt...) +#define SCN_WARN_LOGFUNC(_Fmt...) +#define SCN_INFO_LOGFUNC(_Fmt...) +#define SCN_STATE_LOGFUNC(_Fmt...) +#define SCN_EVENT_LOGFUNC(_Fmt...) +#define SCN_TRACE_LOGFUNC(_Fmt...) +#define SCN_LOUD_LOGFUNC(_Fmt...) +#define SCN_TEMP_LOGFUNC(_Fmt...) + +#define SAA_ERROR_LOGFUNC(_Fmt...) +#define SAA_WARN_LOGFUNC(_Fmt...) +#define SAA_INFO_LOGFUNC(_Fmt...) +#define SAA_STATE_LOGFUNC(_Fmt...) +#define SAA_EVENT_LOGFUNC(_Fmt...) +#define SAA_TRACE_LOGFUNC(_Fmt...) +#define SAA_LOUD_LOGFUNC(_Fmt...) +#define SAA_TEMP_LOGFUNC(_Fmt...) + +#define P2P_ERROR_LOGFUNC(_Fmt...) +#define P2P_WARN_LOGFUNC(_Fmt...) +#define P2P_INFO_LOGFUNC(_Fmt...) +#define P2P_STATE_LOGFUNC(_Fmt...) +#define P2P_EVENT_LOGFUNC(_Fmt...) +#define P2P_TRACE_LOGFUNC(_Fmt...) +#define P2P_LOUD_LOGFUNC(_Fmt...) +#define P2P_TEMP_LOGFUNC(_Fmt...) + +#define QM_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_STATE_LOGFUNC(_Fmt...) +#define QM_EVENT_LOGFUNC(_Fmt...) +#define QM_TRACE_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define QM_LOUD_LOGFUNC(_Fmt...) +#define QM_TEMP_LOGFUNC(_Fmt...) + +#define SEC_ERROR_LOGFUNC(_Fmt...) +#define SEC_WARN_LOGFUNC(_Fmt...) +#define SEC_INFO_LOGFUNC(_Fmt...) +#define SEC_STATE_LOGFUNC(_Fmt...) +#define SEC_EVENT_LOGFUNC(_Fmt...) +#define SEC_TRACE_LOGFUNC(_Fmt...) +#define SEC_LOUD_LOGFUNC(_Fmt...) +#define SEC_TEMP_LOGFUNC(_Fmt...) + +#define BOW_ERROR_LOGFUNC(_Fmt...) +#define BOW_WARN_LOGFUNC(_Fmt...) +#define BOW_INFO_LOGFUNC(_Fmt...) +#define BOW_STATE_LOGFUNC(_Fmt...) +#define BOW_EVENT_LOGFUNC(_Fmt...) +#define BOW_TRACE_LOGFUNC(_Fmt...) +#define BOW_LOUD_LOGFUNC(_Fmt...) +#define BOW_TEMP_LOGFUNC(_Fmt...) + +#define HAL_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define HAL_WARN_LOGFUNC(_Fmt...) +#define HAL_INFO_LOGFUNC(_Fmt...) +#define HAL_STATE_LOGFUNC(_Fmt...) +#define HAL_EVENT_LOGFUNC(_Fmt...) +#define HAL_TRACE_LOGFUNC(_Fmt...) +#define HAL_LOUD_LOGFUNC(_Fmt...) +#define HAL_TEMP_LOGFUNC(_Fmt...) + +#define WAPI_ERROR_LOGFUNC(_Fmt...) +#define WAPI_WARN_LOGFUNC(_Fmt...) +#define WAPI_INFO_LOGFUNC(_Fmt...) +#define WAPI_STATE_LOGFUNC(_Fmt...) +#define WAPI_EVENT_LOGFUNC(_Fmt...) +#define WAPI_TRACE_LOGFUNC(_Fmt...) +#define WAPI_LOUD_LOGFUNC(_Fmt...) +#define WAPI_TEMP_LOGFUNC(_Fmt...) + +#define TDLS_ERROR_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define TDLS_WARN_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define TDLS_INFO_LOGFUNC(_Fmt...) kalPrint(_Fmt) +#define TDLS_STATE_LOGFUNC(_Fmt...) +#define TDLS_EVENT_LOGFUNC(_Fmt...) +#define TDLS_TRACE_LOGFUNC(_Fmt...) +#define TDLS_LOUD_LOGFUNC(_Fmt...) +#define TDLS_TEMP_LOGFUNC(_Fmt...) + +#define SW1_ERROR_LOGFUNC(_Fmt...) +#define SW1_WARN_LOGFUNC(_Fmt...) +#define SW1_INFO_LOGFUNC(_Fmt...) +#define SW1_STATE_LOGFUNC(_Fmt...) +#define SW1_EVENT_LOGFUNC(_Fmt...) +#define SW1_TRACE_LOGFUNC(_Fmt...) +#define SW1_LOUD_LOGFUNC(_Fmt...) +#define SW1_TEMP_LOGFUNC(_Fmt...) + +#define SW2_ERROR_LOGFUNC(_Fmt...) +#define SW2_WARN_LOGFUNC(_Fmt...) +#define SW2_INFO_LOGFUNC(_Fmt...) +#define SW2_STATE_LOGFUNC(_Fmt...) +#define SW2_EVENT_LOGFUNC(_Fmt...) +#define SW2_TRACE_LOGFUNC(_Fmt...) +#define SW2_LOUD_LOGFUNC(_Fmt...) +#define SW2_TEMP_LOGFUNC(_Fmt...) + +#define SW3_ERROR_LOGFUNC(_Fmt...) +#define SW3_WARN_LOGFUNC(_Fmt...) +#define SW3_INFO_LOGFUNC(_Fmt...) +#define SW3_STATE_LOGFUNC(_Fmt...) +#define SW3_EVENT_LOGFUNC(_Fmt...) +#define SW3_TRACE_LOGFUNC(_Fmt...) +#define SW3_LOUD_LOGFUNC(_Fmt...) +#define SW3_TEMP_LOGFUNC(_Fmt...) + +#define SW4_ERROR_LOGFUNC(_Fmt...) +#define SW4_WARN_LOGFUNC(_Fmt...) +#define SW4_INFO_LOGFUNC(_Fmt...) +#define SW4_STATE_LOGFUNC(_Fmt...) +#define SW4_EVENT_LOGFUNC(_Fmt...) +#define SW4_TRACE_LOGFUNC(_Fmt...) +#define SW4_LOUD_LOGFUNC(_Fmt...) +#define SW4_TEMP_LOGFUNC(_Fmt...) +#endif + +#define kalBreakPoint() \ +do { \ + BUG(); \ + panic("Oops"); \ +} while (0) + +#if CFG_ENABLE_AEE_MSG +#define kalSendAeeException aee_kernel_exception +#define kalSendAeeWarning aee_kernel_warning +#define kalSendAeeReminding aee_kernel_reminding +#else +#define kalSendAeeException(_module, _desc, ...) +#define kalSendAeeWarning(_module, _desc, ...) +#define kalSendAeeReminding(_module, _desc, ...) +#endif + +#define PRINTF_ARG(...) __VA_ARGS__ +#define SPRINTF(buf, arg) {buf += sprintf((char *)(buf), PRINTF_ARG arg); } + +#define USEC_TO_SYSTIME(_usec) ((_usec) / USEC_PER_MSEC) +#define MSEC_TO_SYSTIME(_msec) (_msec) + +#define MSEC_TO_JIFFIES(_msec) msecs_to_jiffies(_msec) + +#define KAL_HALT_LOCK_TIMEOUT_NORMAL_CASE 3000 /* 3s */ +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Routines in gl_kal.c */ +/*----------------------------------------------------------------------------*/ +VOID +kalAcquireSpinLock(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, OUT unsigned long *pu4Flags); + +VOID kalReleaseSpinLock(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_SPIN_LOCK_CATEGORY_E rLockCategory, IN UINT_32 u4Flags); + +VOID kalUpdateMACAddress(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucMacAddr); + +VOID kalPacketFree(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +PVOID kalPacketAlloc(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Size, OUT PUINT_8 *ppucData); + +VOID kalOsTimerInitialize(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prTimerHandler); + +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN OS_SYSTIME rInterval); + +WLAN_STATUS +kalProcessRxPacket(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN PUINT_8 pucPacketStart, IN UINT_32 u4PacketLen, + /* IN PBOOLEAN pfgIsRetain, */ + IN BOOLEAN fgIsRetain, IN ENUM_CSUM_RESULT_T aeCSUM[] +); + +WLAN_STATUS kalRxIndicatePkts(IN P_GLUE_INFO_T prGlueInfo, IN PVOID apvPkts[], IN UINT_8 ucPktNum); + +VOID +kalIndicateStatusAndComplete(IN P_GLUE_INFO_T prGlueInfo, IN WLAN_STATUS eStatus, IN PVOID pvBuf, IN UINT_32 u4BufLen); + +VOID +kalUpdateReAssocReqInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +VOID kalUpdateReAssocRspInfo(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen); + +#if CFG_TX_FRAGMENT +BOOLEAN +kalQueryTxPacketHeader(IN P_GLUE_INFO_T prGlueInfo, + IN PVOID pvPacket, OUT PUINT_16 pu2EtherTypeLen, OUT PUINT_8 pucEthDestAddr); +#endif /* CFG_TX_FRAGMENT */ + +VOID kalSendCompleteAndAwakeQueue(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket); + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +VOID kalQueryTxChksumOffloadParam(IN PVOID pvPacket, OUT PUINT_8 pucFlag); + +VOID kalUpdateRxCSUMOffloadParam(IN PVOID pvPacket, IN ENUM_CSUM_RESULT_T eCSUM[] +); +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +BOOLEAN kalRetrieveNetworkAddress(IN P_GLUE_INFO_T prGlueInfo, IN OUT PARAM_MAC_ADDRESS *prMacAddr); + +VOID +kalReadyOnChannel(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum, IN UINT_32 u4DurationMs); + +VOID +kalRemainOnChannelExpired(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_8 ucChannelNum); + +VOID +kalIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +/*----------------------------------------------------------------------------*/ +/* Routines in interface - ehpi/sdio.c */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalDevRegRead(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, OUT PUINT_32 pu4Value); + +BOOLEAN kalDevRegWrite(P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Register, IN UINT_32 u4Value); + +BOOLEAN +kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, OUT PUINT_8 pucBuf, IN UINT_32 u2ValidOutBufSize); + +BOOLEAN +kalDevPortWrite(P_GLUE_INFO_T prGlueInfo, + IN UINT_16 u2Port, IN UINT_32 u2Len, IN PUINT_8 pucBuf, IN UINT_32 u2ValidInBufSize); + +BOOLEAN kalDevWriteWithSdioCmd52(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Addr, IN UINT_8 ucData); + +void kalDevLoopbkAuto(IN GLUE_INFO_T *GlueInfo); + +#if CFG_SUPPORT_EXT_CONFIG +UINT_32 kalReadExtCfg(IN P_GLUE_INFO_T prGlueInfo); +#endif + +BOOLEAN +kalQoSFrameClassifierAndPacketInfo(IN P_GLUE_INFO_T prGlueInfo, + IN P_NATIVE_PACKET prPacket, + OUT PUINT_8 pucPriorityParam, + OUT PUINT_32 pu4PacketLen, + OUT PUINT_8 pucEthDestAddr, + OUT PBOOLEAN pfgIs1X, + OUT PBOOLEAN pfgIsPAL, OUT PUINT_8 pucNetworkType, + OUT PVOID prGenUse); + +VOID +kalOidComplete(IN P_GLUE_INFO_T prGlueInfo, + IN BOOLEAN fgSetQuery, IN UINT_32 u4SetQueryInfoLen, IN WLAN_STATUS rOidStatus); + +WLAN_STATUS +kalIoctl(IN P_GLUE_INFO_T prGlueInfo, + IN PFN_OID_HANDLER_FUNC pfnOidHandler, + IN PVOID pvInfoBuf, + IN UINT_32 u4InfoBufLen, + IN BOOLEAN fgRead, IN BOOLEAN fgWaitResp, IN BOOLEAN fgCmd, IN BOOLEAN fgIsP2pOid, OUT PUINT_32 pu4QryInfoLen); + +VOID kalHandleAssocInfo(IN P_GLUE_INFO_T prGlueInfo, IN P_EVENT_ASSOC_INFO prAssocInfo); + +#if CFG_ENABLE_FW_DOWNLOAD + +PVOID kalFirmwareImageMapping(IN P_GLUE_INFO_T prGlueInfo, OUT PPVOID ppvMapFileBuf, OUT PUINT_32 pu4FileLength); + +VOID kalFirmwareImageUnmapping(IN P_GLUE_INFO_T prGlueInfo, IN PVOID prFwHandle, IN PVOID pvMapFileBuf); +#endif + +/*----------------------------------------------------------------------------*/ +/* Card Removal Check */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsCardRemoved(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* TX */ +/*----------------------------------------------------------------------------*/ +VOID kalFlushPendingTxPackets(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Media State Indication */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalGetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSetMediaStateIndicated(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicate); + +/*----------------------------------------------------------------------------*/ +/* OID handling */ +/*----------------------------------------------------------------------------*/ +VOID kalOidCmdClearance(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalOidClearance(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalEnqueueCommand(IN P_GLUE_INFO_T prGlueInfo, IN P_QUE_ENTRY_T prQueueEntry); + +#if CFG_ENABLE_BT_OVER_WIFI +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi handling */ +/*----------------------------------------------------------------------------*/ +VOID kalIndicateBOWEvent(IN P_GLUE_INFO_T prGlueInfo, IN P_AMPC_EVENT prEvent); + +ENUM_BOW_DEVICE_STATE kalGetBowState(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); + +BOOLEAN kalSetBowState(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_BOW_DEVICE_STATE eBowState, PARAM_MAC_ADDRESS rPeerAddr); + +ENUM_BOW_DEVICE_STATE kalGetBowGlobalState(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetBowFreqInKHz(IN P_GLUE_INFO_T prGlueInfo); + +UINT_8 kalGetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr); + +VOID kalSetBowRole(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucRole, IN PARAM_MAC_ADDRESS rPeerAddr); + +UINT_8 kalGetBowAvailablePhysicalLinkCount(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_BOW_SEPARATE_DATA_PATH +/*----------------------------------------------------------------------------*/ +/* Bluetooth over Wi-Fi Net Device Init/Uninit */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitBowDevice(IN P_GLUE_INFO_T prGlueInfo, IN const char *prDevName); + +BOOLEAN kalUninitBowDevice(IN P_GLUE_INFO_T prGlueInfo); +#endif /* CFG_BOW_SEPARATE_DATA_PATH */ +#endif /* CFG_ENABLE_BT_OVER_WIFI */ + +/*----------------------------------------------------------------------------*/ +/* Firmware Download Handling */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetFwStartAddress(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetFwLoadAddress(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* Security Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID kalClearSecurityFrames(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearSecurityFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +VOID kalSecurityFrameSendComplete(IN P_GLUE_INFO_T prGlueInfo, IN PVOID pvPacket, IN WLAN_STATUS rStatus); + +/*----------------------------------------------------------------------------*/ +/* Management Frame Clearance */ +/*----------------------------------------------------------------------------*/ +VOID kalClearMgmtFrames(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalClearMgmtFramesByNetType(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx); + +UINT_32 kalGetTxPendingFrameCount(IN P_GLUE_INFO_T prGlueInfo); + +UINT_32 kalGetTxPendingCmdCount(IN P_GLUE_INFO_T prGlueInfo); + +BOOLEAN kalSetTimer(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Interval); + +BOOLEAN kalCancelTimer(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalScanDone(IN P_GLUE_INFO_T prGlueInfo, IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN WLAN_STATUS status); + +UINT_32 kalRandomNumber(VOID); + +VOID kalTimeoutHandler(struct timer_list *t); + +VOID kalSetEvent(P_GLUE_INFO_T pr); + +/*----------------------------------------------------------------------------*/ +/* NVRAM/Registry Service */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalIsConfigurationExist(IN P_GLUE_INFO_T prGlueInfo); + +P_REG_INFO_T kalGetConfiguration(IN P_GLUE_INFO_T prGlueInfo); + +VOID +kalGetConfigurationVersion(IN P_GLUE_INFO_T prGlueInfo, + OUT PUINT_16 pu2Part1CfgOwnVersion, + OUT PUINT_16 pu2Part1CfgPeerVersion, + OUT PUINT_16 pu2Part2CfgOwnVersion, OUT PUINT_16 pu2Part2CfgPeerVersion); + +BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data); + +BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, IN UINT_16 u2Data); + +/*----------------------------------------------------------------------------*/ +/* WSC Connection */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalWSCGetActiveState(IN P_GLUE_INFO_T prGlueInfo); + +/*----------------------------------------------------------------------------*/ +/* RSSI Updating */ +/*----------------------------------------------------------------------------*/ +VOID +kalUpdateRSSI(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_KAL_NETWORK_TYPE_INDEX_T eNetTypeIdx, IN INT_8 cRssi, IN INT_8 cLinkQuality); + +/*----------------------------------------------------------------------------*/ +/* I/O Buffer Pre-allocation */ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalInitIOBuffer(VOID); + +VOID kalUninitIOBuffer(VOID); + +PVOID kalAllocateIOBuffer(IN UINT_32 u4AllocSize); + +VOID kalReleaseIOBuffer(IN PVOID pvAddr, IN UINT_32 u4Size); + +VOID +kalGetChannelList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList); + +BOOLEAN kalIsAPmode(IN P_GLUE_INFO_T prGlueInfo); + +ULONG kalIOPhyAddrGet(IN ULONG VirtAddr); + +VOID kalDmaBufGet(OUT VOID **VirtAddr, OUT VOID **PhyAddr); + +#if CFG_SUPPORT_802_11W +/*----------------------------------------------------------------------------*/ +/* 802.11W */ +/*----------------------------------------------------------------------------*/ +UINT_32 kalGetMfpSetting(IN P_GLUE_INFO_T prGlueInfo); +#endif + +UINT_32 kalWriteToFile(const PUINT_8 pucPath, BOOLEAN fgDoAppend, PUINT_8 pucData, UINT_32 u4Size); + +/*----------------------------------------------------------------------------*/ +/* NL80211 */ +/*----------------------------------------------------------------------------*/ +VOID +kalIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, IN UINT_32 u4BufLen, IN UINT_8 ucChannelNum, IN INT_32 i4SignalStrength); + +/*----------------------------------------------------------------------------*/ +/* PNO Support */ +/*----------------------------------------------------------------------------*/ +VOID kalSchedScanResults(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalSchedScanStopped(IN P_GLUE_INFO_T prGlueInfo); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +int tx_thread(void *data); + +VOID kalHifAhbKalWakeLockTimeout(IN P_GLUE_INFO_T prGlueInfo); +VOID kalMetProfilingStart(IN P_GLUE_INFO_T prGlueInfo, IN struct sk_buff *prSkb); +VOID kalMetProfilingFinish(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo); +int kalMetInitProcfs(IN P_GLUE_INFO_T prGlueInfo); +int kalMetRemoveProcfs(void); + +UINT_64 kalGetBootTime(void); + +INT_32 kalReadToFile(const PUINT_8 pucPath, PUINT_8 pucData, UINT_32 u4Size, PUINT_32 pu4ReadSize); +#if CFG_SUPPORT_WAKEUP_REASON_DEBUG +BOOLEAN kalIsWakeupByWlan(P_ADAPTER_T prAdapter); +#endif +INT_32 kalHaltLock(UINT_32 waitMs); +INT_32 kalHaltTryLock(VOID); +VOID kalHaltUnlock(VOID); +VOID kalSetHalted(BOOLEAN fgHalt); +BOOLEAN kalIsHalted(VOID); + +INT32 kalPerMonInit(IN P_GLUE_INFO_T prGlueInfo); +INT32 kalPerMonDisable(IN P_GLUE_INFO_T prGlueInfo); +INT32 kalPerMonEnable(IN P_GLUE_INFO_T prGlueInfo); +INT32 kalPerMonStart(IN P_GLUE_INFO_T prGlueInfo); +INT32 kalPerMonStop(IN P_GLUE_INFO_T prGlueInfo); +INT32 kalPerMonDestroy(IN P_GLUE_INFO_T prGlueInfo); +VOID kalPerMonHandler(IN P_ADAPTER_T prAdapter, ULONG ulParam); +INT32 kalBoostCpu(UINT_32 core_num); + +#endif /* _GL_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h new file mode 100644 index 0000000000000..a4321e7f9a119 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_os.h @@ -0,0 +1,1270 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_os.h#2 +*/ + +/*! \file gl_os.h + \brief List the external reference to OS for GLUE Layer. + + In this file we define the data structure - GLUE_INFO_T to store those objects + we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the + external reference (header file, extern func() ..) to OS for GLUE Layer should + also list down here. +*/ + +/* +** Log: gl_os.h +** +** 08 20 2012 yuche.tsai +** NULL +** Fix possible KE issue. +** +** 08 20 2012 yuche.tsai +** [ALPS00339327] [Rose][6575JB][BSP Package][Free Test][KE][WIFI]There is no response when you tap the turn off/on +** button,wait a minutes, the device will reboot automatically and "KE" will pop up. +** Fix possible KE when netlink operate mgmt frame register. + * + * 04 12 2012 terry.wu + * NULL + * Add AEE message support + * 1) Show AEE warning(red screen) if SDIO access error occurs + + * + * 03 02 2012 terry.wu + * NULL + * Enable CFG80211 Support. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 12 13 2011 cm.chang + * [WCXRP00001136] [All Wi-Fi][Driver] Add wake lock for pending timer + * Add wake lock if timer timeout value is smaller than 5 seconds + * + * 11 18 2011 yuche.tsai + * NULL + * CONFIG P2P support RSSI query, default turned off. + * + * 11 16 2011 yuche.tsai + * NULL + * Avoid using work thread. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 29 2011 terry.wu + * NULL + * Show DRV_NAME by chip id. + * + * 04 18 2011 terry.wu + * [WCXRP00000660] [MT6620 Wi-Fi][Driver] Remove flag CFG_WIFI_DIRECT_MOVED + * Remove flag CFG_WIFI_DIRECT_MOVED. + * + * 03 29 2011 cp.wu + * [WCXRP00000598] [MT6620 Wi-Fi][Driver] Implementation of interface for communicating with user space process for + * RESET_START and RESET_END events + * implement kernel-to-userspace communication via generic netlink socket for whole-chip resetting mechanism + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * support concurrent network + * + * 03 03 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * modify net device relative functions to support multiple H/W queues + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 02 21 2011 cp.wu + * [WCXRP00000482] [MT6620 Wi-Fi][Driver] Simplify logic for checking NVRAM existence in driver domain + * simplify logic for checking NVRAM existence only once. + * + * 02 16 2011 jeffrey.chang + * NULL + * Add query ipv4 and ipv6 address during early suspend and late resume + * + * 02 10 2011 chinghwa.yu + * [WCXRP00000065] Update BoW design and settings + * Fix kernel API change issue. + * Before ALPS 2.2 (2.2 included), kfifo_alloc() is + * struct kfifo *kfifo_alloc(unsigned int size, gfp_t gfp_mask, spinlock_t *lock); + * After ALPS 2.3, kfifo_alloc() is changed to + * int kfifo_alloc(struct kfifo *fifo, unsigned int size, gfp_t gfp_mask); + * + * 02 09 2011 wh.su + * [WCXRP00000433] [MT6620 Wi-Fi][Driver] Remove WAPI structure define for avoid P2P module with structure miss-align + * pointer issue + * always pre-allio WAPI related structure for align p2p module. + * + * 02 09 2011 terry.wu + * [WCXRP00000383] [MT6620 Wi-Fi][Driver] Separate WiFi and P2P driver into two modules + * Halt p2p module init and exit until TxThread finished p2p register and unregister. + * + * 02 01 2011 cm.chang + * [WCXRP00000415] [MT6620 Wi-Fi][Driver] Check if any memory leakage happens when uninitializing in DGB mode + * . + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 12 2011 cp.wu + * [WCXRP00000357] [MT6620 Wi-Fi][Driver][Bluetooth over Wi-Fi] add another net device interface for BT AMP + * implementation of separate BT_OVER_WIFI data path. + * + * 01 12 2011 cp.wu + * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation + * needs such information + * fill mac header length information for 802.1x frames. + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. Connection establish + * successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. + * + * 01 10 2011 cp.wu + * [WCXRP00000349] [MT6620 Wi-Fi][Driver] make kalIoctl() of linux port as a thread safe API to avoid potential issues + * due to multiple access + * use mutex to protect kalIoctl() for thread safe. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * ioctl implementations for P2P Service Discovery + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 28 2010 wh.su + * NULL + * [WCXRP00000069][MT6620 Wi-Fi][Driver] Fix some code for phase 1 P2P Demo. + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 09 13 2010 cp.wu + * NULL + * add waitq for poll() and read(). + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 09 06 2010 wh.su + * NULL + * let the p2p can set the privacy bit at beacon and rsn ie at assoc req at key handshake state. + * + * 09 03 2010 kevin.huang + * NULL + * Refine #include sequence and solve recursive/nested #include issue + * + * 09 01 2010 wh.su + * NULL + * adding the wapi support for integration test. + * + * 08 31 2010 kevin.huang + * NULL + * Use LINK LIST operation to process SCAN result + * + * 08 23 2010 cp.wu + * NULL + * revise constant definitions to be matched with implementation (original cmd-event definition is deprecated) + * + * 08 16 2010 cp.wu + * NULL + * P2P packets are now marked when being queued into driver, and identified later without checking MAC address + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 11 2010 cp.wu + * NULL + * 1) do not use in-stack variable for beacon updating. (for MAUI porting) + * 2) extending scanning result to 64 instead of 48 + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 08 02 2010 jeffrey.chang + * NULL + * 1) modify tx service thread to avoid busy looping + * 2) add spin lock declartion for linux build + * + * 07 23 2010 jeffrey.chang + * + * add new KAL api + * + * 07 22 2010 jeffrey.chang + * + * modify tx thread and remove some spinlock + * + * 07 19 2010 jeffrey.chang + * + * add security frame pending count + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * + * 05 10 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement basic wi-fi direct framework + * + * 05 07 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * prevent supplicant accessing driver during resume + * + * 05 07 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add basic framework for implementating P2P driver hook. + * + * 05 05 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * change variable names for multiple physical link to match with coding convention + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * identify BT Over Wi-Fi Security frame and mark it as 802.1X frame + * + * 04 27 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add multiple physical link support + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * 1) fix firmware download bug + * 2) remove query statistics for acelerating firmware download + * + * 04 27 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * follow Linux's firmware framework, and remove unused kal API + * + * 04 23 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * surpress compiler warning + * + * 04 19 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * supporting power management + * + * 04 14 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * pvInformationBuffer and u4InformationBufferLength are no longer in glue + * + * 04 13 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add framework for BT-over-Wi-Fi support. + * * * * * * * * * * * * * * * * * * * * 1) prPendingCmdInfo is replaced by queue for multiple + * * * * * * * * * * * * * * * * * * * * handler capability + * * * * * * * * * * * * * * * * * * * * 2) command sequence number is now increased atomically + * * * * * * * * * * * * * * * * * * * * 3) private data could be hold and taken use for other + * * * * * * * * * * * * * * * * * * * * purpose + * + * 04 07 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * rWlanInfo should be placed at adapter rather than glue due to most operations + * * * * * * * * * * are done in adapter layer. + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * Tag the packet for QoS on Tx path + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * (1)deliver the kalOidComplete status to upper layer + * * (2) fix spin lock + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * add timeout check in the kalOidComplete + * + * 04 06 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * improve none-glue code portability + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * code refine: fgTestMode should be at adapter rather than glue due to the device/fw is also involved + * + * 04 06 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * eliminate direct access for prGlueInfo->fgIsCardRemoved in non-glue layer + * + * 03 30 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * emulate NDIS Pending OID facility + * + * 03 26 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * [WPD00003826] Initial import for Linux port + * adding firmware download related data type + * + * 03 25 2010 cp.wu + * [WPD00001943]Create WiFi test driver framework on WinXP + * 1) correct OID_802_11_CONFIGURATION with frequency setting behavior. + * * * * the frequency is used for adhoc connection only + * * * * 2) update with SD1 v0.9 CMD/EVENT documentation + * + * 03 25 2010 cp.wu + * [WPD00003823][MT6620 Wi-Fi] Add Bluetooth-over-Wi-Fi support + * add Bluetooth-over-Wifi frame header check + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\30 2009-10-20 17:38:31 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, +** and then stop hw. +** \main\maintrunk.MT5921\29 2009-10-08 10:33:33 GMT mtk01090 +** Avoid accessing private data of net_device directly. Replace with netdev_priv(). Add more checking for input +** parameters and pointers. +** \main\maintrunk.MT5921\28 2009-09-28 20:19:26 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\27 2009-08-18 22:57:12 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\26 2009-07-06 21:42:25 GMT mtk01088 +** fixed the compiling error at linux +** \main\maintrunk.MT5921\25 2009-07-06 20:51:46 GMT mtk01088 +** adding the wapi 1x ether type define +** \main\maintrunk.MT5921\24 2009-06-23 23:19:18 GMT mtk01090 +** Add build option BUILD_USE_EEPROM and compile option CFG_SUPPORT_EXT_CONFIG for NVRAM support +** \main\maintrunk.MT5921\23 2009-02-07 15:05:06 GMT mtk01088 +** add the privacy flag to ingo driver the supplicant selected ap's security +** \main\maintrunk.MT5921\22 2009-02-05 15:34:09 GMT mtk01088 +** fixed the compiling error for using bits marco for only one parameter +** \main\maintrunk.MT5921\21 2009-01-22 13:02:13 GMT mtk01088 +** data frame is or not 802.1x value share with tid, using the same reserved byte, provide the function to set and get +** \main\maintrunk.MT5921\20 2008-10-24 12:04:16 GMT mtk01088 +** move the config.h from precomp.h to here for lint check +** \main\maintrunk.MT5921\19 2008-09-22 23:19:02 GMT mtk01461 +** Update driver for code review +** \main\maintrunk.MT5921\18 2008-09-05 17:25:13 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\17 2008-08-01 13:32:47 GMT mtk01084 +** Prevent redundent driver assertion in driver logic when BUS is detached +** \main\maintrunk.MT5921\16 2008-05-30 14:41:43 GMT mtk01461 +** Remove WMM Assoc Flag in KAL +** \main\maintrunk.MT5921\15 2008-05-29 14:16:25 GMT mtk01084 +** remoev un-used variable +** \main\maintrunk.MT5921\14 2008-05-03 15:17:14 GMT mtk01461 +** Add Media Status variable in Glue Layer +** \main\maintrunk.MT5921\13 2008-04-24 11:58:41 GMT mtk01461 +** change threshold to 256 +** \main\maintrunk.MT5921\12 2008-03-11 14:51:05 GMT mtk01461 +** Remove redundant GL_CONN_INFO_T +** \main\maintrunk.MT5921\11 2008-01-07 15:07:41 GMT mtk01461 +** Adjust the netif stop threshold to 150 +** \main\maintrunk.MT5921\10 2007-11-26 19:43:46 GMT mtk01461 +** Add OS_TIMESTAMP macro +** +** \main\maintrunk.MT5921\9 2007-11-07 18:38:38 GMT mtk01461 +** Move definition +** \main\maintrunk.MT5921\8 2007-11-02 01:04:00 GMT mtk01461 +** Unify TX Path for Normal and IBSS Power Save + IBSS neighbor learning +** Revision 1.5 2007/07/12 11:04:28 MTK01084 +** update macro to delay for ms order +** +** Revision 1.4 2007/07/05 07:25:34 MTK01461 +** Add Linux initial code, modify doc, add 11BB, RF init code +** +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +#ifndef _GL_OS_H +#define _GL_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +/*------------------------------------------------------------------------------ + * Flags for LINUX(OS) dependent + *------------------------------------------------------------------------------ + */ +#define CFG_MAX_WLAN_DEVICES 1 /* number of wlan card will coexist */ + +#define CFG_MAX_TXQ_NUM 4 /* number of tx queue for support multi-queue h/w */ + +#define CFG_USE_SPIN_LOCK_BOTTOM_HALF 0 /* 1: Enable use of SPIN LOCK Bottom Half for LINUX + 0: Disable - use SPIN LOCK IRQ SAVE instead */ + +#define CFG_TX_PADDING_SMALL_ETH_PACKET 0 /* 1: Enable - Drop ethernet packet if it < 14 bytes. + And pad ethernet packet with dummy 0 if it < 60 bytes. + 0: Disable */ + +#define CFG_TX_STOP_NETIF_QUEUE_THRESHOLD 256 /* packets */ + +#define CFG_TX_STOP_NETIF_PER_QUEUE_THRESHOLD 256 /* packets */ +#define CFG_TX_START_NETIF_PER_QUEUE_THRESHOLD 128 /* packets */ + +#define ETH_P_1X 0x888E +#define IPTOS_PREC_OFFSET 5 +#define USER_PRIORITY_DEFAULT 0 + +#define ETH_WPI_1X 0x88B4 + +#define ETH_HLEN 14 +#define ETH_TYPE_LEN_OFFSET 12 +#define ETH_P_IP 0x0800 +#define ETH_P_1X 0x888E +#define ETH_P_PRE_1X 0x88C7 +#define ETH_P_ARP 0x0806 + +#define ARP_PRO_REQ 1 +#define ARP_PRO_RSP 2 + +#define IPVERSION 4 +#define IP_HEADER_LEN 20 + +#define IP_PRO_ICMP 0x01 +#define IP_PRO_UDP 0x11 +#define IP_PRO_TCP 0x06 + +#define UDP_PORT_DHCPS 0x43 +#define UDP_PORT_DHCPC 0x44 +#define UDP_PORT_DNS 0x35 + +#define IPVH_VERSION_OFFSET 4 /* For Little-Endian */ +#define IPVH_VERSION_MASK 0xF0 +#define IPTOS_PREC_OFFSET 5 +#define IPTOS_PREC_MASK 0xE0 + +#define SOURCE_PORT_LEN 2 +/* NOTE(Kevin): Without IP Option Length */ +#define LOOK_AHEAD_LEN (ETH_HLEN + IP_HEADER_LEN + SOURCE_PORT_LEN) + +/* 802.2 LLC/SNAP */ +#define ETH_LLC_OFFSET (ETH_HLEN) +#define ETH_LLC_LEN 3 +#define ETH_LLC_DSAP_SNAP 0xAA +#define ETH_LLC_SSAP_SNAP 0xAA +#define ETH_LLC_CONTROL_UNNUMBERED_INFORMATION 0x03 + +/* Bluetooth SNAP */ +#define ETH_SNAP_OFFSET (ETH_HLEN + ETH_LLC_LEN) +#define ETH_SNAP_LEN 5 +#define ETH_SNAP_BT_SIG_OUI_0 0x00 +#define ETH_SNAP_BT_SIG_OUI_1 0x19 +#define ETH_SNAP_BT_SIG_OUI_2 0x58 + +#define BOW_PROTOCOL_ID_SECURITY_FRAME 0x0003 + +#if defined(MT6620) +#define CHIP_NAME "MT6620" +#elif defined(MT6628) +#define CHIP_NAME "MT6582" +#endif + +#define DRV_NAME "["CHIP_NAME"]: " + +#define CONFIG_ANDROID 1 +/* Define if target platform is Android. + * It should already be defined in Android kernel source + */ + +/* for CFG80211 IE buffering mechanism */ +#define CFG_CFG80211_IE_BUF_LEN (512) + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include /* constant of kernel version */ + +#include /* bitops.h */ + +#include /* struct timer_list */ +#include /* jiffies */ +#include /* udelay and mdelay macro */ + +#if CONFIG_ANDROID +#include +#endif + +#include /* IRQT_FALLING */ + +#include /* struct net_device, struct net_device_stats */ +#include /* for eth_type_trans() function */ +#include /* struct iw_statistics */ +#include +#include /* struct in_device */ + +#include /* struct iphdr */ + +#include /* for memcpy()/memset() function */ +#include /* for offsetof() macro */ + +#include /* The proc filesystem constants/structures */ + +#include /* for rtnl_lock() and rtnl_unlock() */ +#include /* kthread_should_stop(), kthread_run() */ +#include /* for copy_from_user() */ +#include /* for firmware download */ +#include + +#include /* for kfifo interface */ +#include /* for cdev interface */ + +#include /* for firmware download */ + +#if defined(_HIF_SDIO) +#include +#include +#endif + +#include + +#include +#include + +#include /* readw and writew */ + +#if WIRELESS_EXT > 12 +#include +#endif + +#include "version.h" +#include "config.h" + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include + +#if CFG_SUPPORT_HOTSPOT_2_0 +#include +#endif + +#include "gl_typedef.h" +#include "typedef.h" +#include "queue.h" +#include "gl_kal.h" +#include "hif.h" +#if CFG_CHIP_RESET_SUPPORT +#include "gl_rst.h" +#endif + +#if (CFG_SUPPORT_TDLS == 1) +#include "tdls_extr.h" +#endif +#include "debug.h" + +#include "wlan_lib.h" +#include "wlan_oid.h" + +#if CFG_ENABLE_AEE_MSG +#include +#endif + +extern BOOLEAN fgIsBusAccessFailed; + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GLUE_FLAG_HALT BIT(0) +#define GLUE_FLAG_INT BIT(1) +#define GLUE_FLAG_OID BIT(2) +#define GLUE_FLAG_TIMEOUT BIT(3) +#define GLUE_FLAG_TXREQ BIT(4) +#define GLUE_FLAG_SUB_MOD_INIT BIT(5) +#define GLUE_FLAG_SUB_MOD_EXIT BIT(6) +#define GLUE_FLAG_SUB_MOD_MULTICAST BIT(7) +#define GLUE_FLAG_FRAME_FILTER BIT(8) +#define GLUE_FLAG_FRAME_FILTER_AIS BIT(9) +#define GLUE_FLAG_HIF_LOOPBK_AUTO BIT(10) +#define GLUE_FLAG_HALT_BIT (0) +#define GLUE_FLAG_INT_BIT (1) +#define GLUE_FLAG_OID_BIT (2) +#define GLUE_FLAG_TIMEOUT_BIT (3) +#define GLUE_FLAG_TXREQ_BIT (4) +#define GLUE_FLAG_SUB_MOD_INIT_BIT (5) +#define GLUE_FLAG_SUB_MOD_EXIT_BIT (6) +#define GLUE_FLAG_SUB_MOD_MULTICAST_BIT (7) +#define GLUE_FLAG_FRAME_FILTER_BIT (8) +#define GLUE_FLAG_FRAME_FILTER_AIS_BIT (9) +#define GLUE_FLAG_HIF_LOOPBK_AUTO_BIT (10) + +#define GLUE_BOW_KFIFO_DEPTH (1024) +/* #define GLUE_BOW_DEVICE_NAME "MT6620 802.11 AMP" */ +#define GLUE_BOW_DEVICE_NAME "ampc0" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _GL_WPA_INFO_T { + UINT_32 u4WpaVersion; + UINT_32 u4KeyMgmt; + UINT_32 u4CipherGroup; + UINT_32 u4CipherPairwise; + UINT_32 u4AuthAlg; + BOOLEAN fgPrivacyInvoke; +#if CFG_SUPPORT_802_11W + UINT_32 u4Mfp; +#endif +} GL_WPA_INFO_T, *P_GL_WPA_INFO_T; + +typedef enum _ENUM_RSSI_TRIGGER_TYPE { + ENUM_RSSI_TRIGGER_NONE, + ENUM_RSSI_TRIGGER_GREATER, + ENUM_RSSI_TRIGGER_LESS, + ENUM_RSSI_TRIGGER_TRIGGERED, + ENUM_RSSI_TRIGGER_NUM +} ENUM_RSSI_TRIGGER_TYPE; + +#if CFG_ENABLE_WIFI_DIRECT +typedef enum _ENUM_SUB_MODULE_IDX_T { + P2P_MODULE = 0, + SUB_MODULE_NUM +} ENUM_SUB_MODULE_IDX_T; + +typedef enum _ENUM_NET_REG_STATE_T { + ENUM_NET_REG_STATE_UNREGISTERED, + ENUM_NET_REG_STATE_REGISTERING, + ENUM_NET_REG_STATE_REGISTERED, + ENUM_NET_REG_STATE_UNREGISTERING, + ENUM_NET_REG_STATE_NUM +} ENUM_NET_REG_STATE_T; + +#endif + +typedef struct _GL_IO_REQ_T { + QUE_ENTRY_T rQueEntry; + /* wait_queue_head_t cmdwait_q; */ + BOOLEAN fgRead; + BOOLEAN fgWaitResp; +#if CFG_ENABLE_WIFI_DIRECT + BOOLEAN fgIsP2pOid; +#endif + P_ADAPTER_T prAdapter; + PFN_OID_HANDLER_FUNC pfnOidHandler; + PVOID pvInfoBuf; + UINT_32 u4InfoBufLen; + PUINT_32 pu4QryInfoLen; + WLAN_STATUS rStatus; + UINT_32 u4Flag; +} GL_IO_REQ_T, *P_GL_IO_REQ_T; + +#if CFG_ENABLE_BT_OVER_WIFI +typedef struct _GL_BOW_INFO { + BOOLEAN fgIsRegistered; + dev_t u4DeviceNumber; /* dynamic device number */ +/* struct kfifo *prKfifo; */ /* for buffering indicated events */ + struct kfifo rKfifo; /* for buffering indicated events */ + spinlock_t rSpinLock; /* spin lock for kfifo */ + struct cdev cdev; + UINT_32 u4FreqInKHz; /* frequency */ + + UINT_8 aucRole[CFG_BOW_PHYSICAL_LINK_NUM]; /* 0: Responder, 1: Initiator */ + ENUM_BOW_DEVICE_STATE aeState[CFG_BOW_PHYSICAL_LINK_NUM]; + PARAM_MAC_ADDRESS arPeerAddr[CFG_BOW_PHYSICAL_LINK_NUM]; + + wait_queue_head_t outq; + +#if CFG_BOW_SEPARATE_DATA_PATH + /* Device handle */ + struct net_device *prDevHandler; + BOOLEAN fgIsNetRegistered; +#endif + +} GL_BOW_INFO, *P_GL_BOW_INFO; +#endif + +#if (CFG_SUPPORT_TDLS == 1) +typedef struct _TDLS_INFO_LINK_T { + /* start time when link is built, end time when link is broken */ + unsigned long jiffies_start, jiffies_end; + + /* the peer MAC */ + UINT8 aucPeerMac[6]; + + /* broken reason */ + UINT8 ucReasonCode; + + /* TRUE: torn down is triggerred by us */ + UINT8 fgIsFromUs; + + /* duplicate count; same reason */ + UINT8 ucDupCount; + + /* HT capability */ +#define TDLS_INFO_LINK_HT_CAP_SUP 0x01 + UINT8 ucHtCap; +#define TDLS_INFO_LINK_HT_BA_SETUP 0x01 +#define TDLS_INFO_LINK_HT_BA_SETUP_OK 0x02 +#define TDLS_INFO_LINK_HT_BA_SETUP_DECLINE 0x04 +#define TDLS_INFO_LINK_HT_BA_PEER 0x10 +#define TDLS_INFO_LINK_HT_BA_RSP_OK 0x20 +#define TDLS_INFO_LINK_HT_BA_RSP_DECLINE 0x40 + UINT8 ucHtBa[8]; /* TID0 ~ TID7 */ +} TDLS_INFO_LINK_T; + +typedef struct _TDLS_INFO_T { + /* link history */ +#define TDLS_LINK_HISTORY_MAX 30 + TDLS_INFO_LINK_T rLinkHistory[TDLS_LINK_HISTORY_MAX]; + UINT32 u4LinkIdx; + + /* TRUE: support 20/40 bandwidth in TDLS link */ + BOOLEAN fgIs2040Sup; + + /* total TDLS link count */ + INT8 cLinkCnt; +} TDLS_INFO_T; +#endif /* CFG_SUPPORT_TDLS */ + +/* +* type definition of pointer to p2p structure +*/ +typedef struct _GL_P2P_INFO_T GL_P2P_INFO_T, *P_GL_P2P_INFO_T; + +struct _GLUE_INFO_T { + /* Device handle */ + struct net_device *prDevHandler; + + /* Device Index(index of arWlanDevInfo[]) */ + INT_32 i4DevIdx; + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* Wireless statistics struct net_device */ + struct iw_statistics rIwStats; + + /* spinlock to sync power save mechanism */ + spinlock_t rSpinLock[SPIN_LOCK_NUM]; + + /* semaphore for ioctl */ + struct semaphore ioctl_sem; + + UINT_64 u8Cookie; + + ULONG ulFlag; /* GLUE_FLAG_XXX */ + UINT_32 u4PendFlag; + /* UINT_32 u4TimeoutFlag; */ + UINT_32 u4OidCompleteFlag; + UINT_32 u4ReadyFlag; /* check if card is ready */ + + UINT_32 u4OsMgmtFrameFilter; + + /* Number of pending frames, also used for debuging if any frame is + * missing during the process of unloading Driver. + * + * NOTE(Kevin): In Linux, we also use this variable as the threshold + * for manipulating the netif_stop(wake)_queue() func. + */ + INT_32 ai4TxPendingFrameNumPerQueue[4][CFG_MAX_TXQ_NUM]; + INT_32 i4TxPendingFrameNum; + INT_32 i4TxPendingSecurityFrameNum; + + /* current IO request for kalIoctl */ + GL_IO_REQ_T OidEntry; + + /* registry info */ + REG_INFO_T rRegInfo; + + /* firmware */ + struct firmware *prFw; + + /* Host interface related information */ + /* defined in related hif header file */ + GL_HIF_INFO_T rHifInfo; + + /*! \brief wext wpa related information */ + GL_WPA_INFO_T rWpaInfo; + + /* Pointer to ADAPTER_T - main data structure of internal protocol stack */ + P_ADAPTER_T prAdapter; + +#ifdef WLAN_INCLUDE_PROC + struct proc_dir_entry *pProcRoot; +#endif /* WLAN_INCLUDE_PROC */ + + /* Indicated media state */ + ENUM_PARAM_MEDIA_STATE_T eParamMediaStateIndicated; + + /* Device power state D0~D3 */ + PARAM_DEVICE_POWER_STATE ePowerState; + + struct completion rScanComp; /* indicate scan complete */ + struct completion rHaltComp; /* indicate main thread halt complete */ + struct completion rPendComp; /* indicate main thread halt complete */ +#if CFG_ENABLE_WIFI_DIRECT + struct completion rSubModComp; /*indicate sub module init or exit complete */ +#endif + WLAN_STATUS rPendStatus; + + QUE_T rTxQueue; + + /* OID related */ + QUE_T rCmdQueue; + /* PVOID pvInformationBuffer; */ + /* UINT_32 u4InformationBufferLength; */ + /* PVOID pvOidEntry; */ + /* PUINT_8 pucIOReqBuff; */ + /* QUE_T rIOReqQueue; */ + /* QUE_T rFreeIOReqQueue; */ + + wait_queue_head_t waitq; + struct task_struct *main_thread; + + struct timer_list tickfn; + +#if CFG_SUPPORT_EXT_CONFIG + UINT_16 au2ExtCfg[256]; /* NVRAM data buffer */ + UINT_32 u4ExtCfgLength; /* 0 means data is NOT valid */ +#endif + +#if 1 /* CFG_SUPPORT_WAPI */ + /* Should be large than the PARAM_WAPI_ASSOC_INFO_T */ + UINT_8 aucWapiAssocInfoIEs[42]; + UINT_16 u2WapiAssocInfoIESz; +#endif + +#if CFG_ENABLE_BT_OVER_WIFI + GL_BOW_INFO rBowInfo; +#endif + +#if CFG_ENABLE_WIFI_DIRECT + P_GL_P2P_INFO_T prP2PInfo; +#if CFG_SUPPORT_P2P_RSSI_QUERY + /* Wireless statistics struct net_device */ + struct iw_statistics rP2pIwStats; +#endif +#endif + BOOLEAN fgWpsActive; + UINT_8 aucWSCIE[500]; /*for probe req */ + UINT_16 u2WSCIELen; + UINT_8 aucWSCAssocInfoIE[200]; /*for Assoc req */ + UINT_16 u2WSCAssocInfoIELen; + +#if CFG_SUPPORT_HOTSPOT_2_0 + UINT_8 aucHS20AssocInfoIE[200]; /*for Assoc req */ + UINT_16 u2HS20AssocInfoIELen; + UINT_8 ucHotspotConfig; + BOOLEAN fgConnectHS20AP; +#endif + + /* NVRAM availability */ + BOOLEAN fgNvramAvailable; + + BOOLEAN fgMcrAccessAllowed; + + /* MAC Address Overridden by IOCTL */ + BOOLEAN fgIsMacAddrOverride; + PARAM_MAC_ADDRESS rMacAddrOverride; + + SET_TXPWR_CTRL_T rTxPwr; + + /* for cfg80211 scan done indication */ + struct cfg80211_scan_request *prScanRequest; + + /* for cfg80211 scheduled scan */ + struct cfg80211_sched_scan_request *prSchedScanRequest; + + /* to indicate registered or not */ + BOOLEAN fgIsRegistered; + + /* for cfg80211 connected indication */ + UINT_32 u4RspIeLength; + UINT_8 aucRspIe[CFG_CFG80211_IE_BUF_LEN]; + + UINT_32 u4ReqIeLength; + UINT_8 aucReqIe[CFG_CFG80211_IE_BUF_LEN]; + + KAL_WAKE_LOCK_T rAhbIsrWakeLock; + +#if CFG_SUPPORT_HOTSPOT_2_0 + BOOLEAN fgIsDad; + UINT_8 aucDADipv4[4]; + BOOLEAN fgIs6Dad; + UINT_8 aucDADipv6[16]; +#endif +#if (CFG_SUPPORT_MET_PROFILING == 1) + UINT_8 u8MetProfEnable; + INT_16 u16MetUdpPort; +#endif + BOOLEAN fgPoorlinkValid; + UINT_64 u8Statistic[2]; + UINT_64 u8TotalFailCnt; + UINT_32 u4LinkspeedThreshold; + INT_32 i4RssiThreshold; + INT_32 i4RssiCache; + UINT_32 u4LinkSpeedCache; + +#if (CFG_SUPPORT_TDLS == 1) + TDLS_INFO_T rTdlsLink; + + UINT8 aucTdlsHtPeerMac[6]; + IE_HT_CAP_T rTdlsHtCap; /* temp to queue HT capability element */ + + /* + [0~7]: jiffies + [8~13]: Peer MAC + [14]: Reason Code + [15]: From us or peer + [16]: Duplicate Count + */ +/* UINT8 aucTdlsDisconHistory[TDLS_DISCON_HISTORY_MAX][20]; */ +/* UINT32 u4TdlsDisconIdx; */ +#endif /* CFG_SUPPORT_TDLS */ + UINT_32 IsrCnt; + UINT_32 IsrPassCnt; + UINT_32 TaskIsrCnt; + + UINT_32 IsrPreCnt; + UINT_32 IsrPrePassCnt; + UINT_32 TaskPreIsrCnt; + + UINT_32 IsrAbnormalCnt; + UINT_32 IsrSoftWareCnt; + UINT_32 IsrTxCnt; + UINT_32 IsrRxCnt; + UINT_64 u8SkbToDriver; + UINT_64 u8SkbFreed; +}; + +typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs); + +typedef void (*PFN_LINUX_TIMER_FUNC) (unsigned long); + +/* generic sub module init/exit handler +* now, we only have one sub module, p2p +*/ +#if CFG_ENABLE_WIFI_DIRECT +typedef BOOLEAN(*SUB_MODULE_INIT) (P_GLUE_INFO_T prGlueInfo); +typedef BOOLEAN(*SUB_MODULE_EXIT) (P_GLUE_INFO_T prGlueInfo); + +typedef struct _SUB_MODULE_HANDLER { + SUB_MODULE_INIT subModInit; + SUB_MODULE_EXIT subModExit; + BOOLEAN fgIsInited; +} SUB_MODULE_HANDLER, *P_SUB_MODULE_HANDLER; + +#endif + + +#ifdef CONFIG_NL80211_TESTMODE +enum TestModeCmdType { + /* old test mode command id, compatible with exist testmode command */ + TESTMODE_CMD_ID_SW_CMD = 1, + TESTMODE_CMD_ID_WAPI = 2, + TESTMODE_CMD_ID_HS20 = 3, + TESTMODE_CMD_ID_POORLINK = 4, + TESTMODE_CMD_ID_STATISTICS = 0x10, + TESTMODE_CMD_ID_LINK_DETECT = 0x20, + /* old test mode command id, compatible with exist testmode command */ + + /* all new added test mode command should great than TESTMODE_CMD_ID_NEW_BEGIN */ + TESTMODE_CMD_ID_NEW_BEGIN = 100, + TESTMODE_CMD_ID_SUSPEND = 101, +}; +#if CFG_SUPPORT_HOTSPOT_2_0 +enum Hs20CmdType { + HS20_CMD_ID_SET_BSSID_POOL = 0, + NUM_OF_HS20_CMD_ID +}; +#endif + +typedef struct _NL80211_DRIVER_TEST_MODE_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_MODE_PARAMS, *P_NL80211_DRIVER_TEST_MODE_PARAMS; + +/*SW CMD */ +typedef struct _NL80211_DRIVER_SW_CMD_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 set; + UINT_32 adr; + UINT_32 data; +} NL80211_DRIVER_SW_CMD_PARAMS, *P_NL80211_DRIVER_SW_CMD_PARAMS; + +typedef struct _NL80211_DRIVER_SUSPEND_PARAMS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 suspend; +} NL80211_DRIVER_SUSPEND_PARAMS, *P_NL80211_DRIVER_SUSPEND_PARAMS; +struct iw_encode_exts { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 addr[MAC_ADDR_LEN]; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[32]; +}; + +/*SET KEY EXT */ +typedef struct _NL80211_DRIVER_SET_KEY_EXTS { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + UINT_8 key_index; + UINT_8 key_len; + struct iw_encode_exts ext; +} NL80211_DRIVER_SET_KEY_EXTS, *P_NL80211_DRIVER_SET_KEY_EXTS; + +#if CFG_SUPPORT_HOTSPOT_2_0 + +struct param_hs20_set_bssid_pool { + u8 fgBssidPoolIsEnable; + u8 ucNumBssidPool; + u8 arBssidPool[8][ETH_ALEN]; +}; + +struct wpa_driver_hs20_data_s { + NL80211_DRIVER_TEST_MODE_PARAMS hdr; + enum Hs20CmdType CmdType; + struct param_hs20_set_bssid_pool hs20_set_bssid_pool; +}; + +#endif /* CFG_SUPPORT_HOTSPOT_2_0 */ + +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Macros of SPIN LOCK operations for using in Glue Layer */ +/*----------------------------------------------------------------------------*/ +#if CFG_USE_SPIN_LOCK_BOTTOM_HALF +#define GLUE_SPIN_LOCK_DECLARATION() +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_bh(&(prGlueInfo->rSpinLock[rLockCategory])); \ + } +#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ + spin_lock_bh(prLock) +#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ + spin_unlock_bh(prLock) + +#else /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ +#define GLUE_SPIN_LOCK_DECLARATION() unsigned long __u4Flags = 0 +#define GLUE_ACQUIRE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_lock_irqsave(&(prGlueInfo)->rSpinLock[rLockCategory], __u4Flags); \ + } +#define GLUE_RELEASE_SPIN_LOCK(prGlueInfo, rLockCategory) \ + { \ + if (rLockCategory < SPIN_LOCK_NUM) \ + spin_unlock_irqrestore(&(prGlueInfo->rSpinLock[rLockCategory]), __u4Flags); \ + } +#define GLUE_ACQUIRE_THE_SPIN_LOCK(prLock) \ + spin_lock_irqsave(prLock, __u4Flags) +#define GLUE_RELEASE_THE_SPIN_LOCK(prLock) \ + spin_unlock_irqrestore(prLock, __u4Flags) +#endif /* !CFG_USE_SPIN_LOCK_BOTTOM_HALF */ + +/*----------------------------------------------------------------------------*/ +/* Macros for accessing Reserved Fields of native packet */ +/*----------------------------------------------------------------------------*/ +#define GLUE_CB_OFFSET 4 /* For 64-bit platform, avoiding that the cb + isoverwrited by "(prQueueEntry)->prNext = + (P_QUE_ENTRY_T)NULL;" in QUEUE_INSERT_TAIL */ +#define GLUE_GET_PKT_QUEUE_ENTRY(_p) \ + (&(((struct sk_buff *)(_p))->cb[0])) + +#define GLUE_GET_PKT_DESCRIPTOR(_prQueueEntry) \ + ((P_NATIVE_PACKET) ((ULONG)_prQueueEntry - offsetof(struct sk_buff, cb[0]))) + +#define GLUE_SET_PKT_FLAG_802_11(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(7)) + +#define GLUE_SET_PKT_FLAG_1X(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(6)) + +#define GLUE_SET_PKT_FLAG_PAL(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(5)) + +#define GLUE_SET_PKT_FLAG_P2P(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= BIT(4)) + +#define GLUE_SET_PKT_TID(_p, _tid) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4])) |= (((UINT_8)((_tid) & (BITS(0, 3)))))) + +#define GLUE_SET_PKT_FRAME_LEN(_p, _u2PayloadLen) \ + (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6])) = (UINT_16)(_u2PayloadLen)) + +#define GLUE_GET_PKT_FRAME_LEN(_p) \ + (*((PUINT_16)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+6]))) + +#define GLUE_GET_PKT_IS_802_11(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(7))) + +#define GLUE_GET_PKT_IS_1X(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(6))) + +#define GLUE_GET_PKT_TID(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BITS(0, 3))) + +#define GLUE_GET_PKT_IS_PAL(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(5))) + +#define GLUE_GET_PKT_IS_P2P(_p) \ + ((*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+4]))) & (BIT(4))) + +#define GLUE_SET_PKT_HEADER_LEN(_p, _ucMacHeaderLen) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5])) = (UINT_8)(_ucMacHeaderLen)) + +#define GLUE_GET_PKT_HEADER_LEN(_p) \ + (*((PUINT_8)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+5]))) + +#define GLUE_SET_PKT_ARRIVAL_TIME(_p, _rSysTime) \ + (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8])) = (OS_SYSTIME)(_rSysTime)) + +#define GLUE_GET_PKT_ARRIVAL_TIME(_p) \ + (*((POS_SYSTIME)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+8]))) + +#define GLUE_SET_PKT_XTIME(_p, _rSysTime) \ + (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16])) = (UINT_64)(_rSysTime)) + +#define GLUE_GET_PKT_XTIME(_p) \ + (*((UINT_64 *)&(((struct sk_buff *)(_p))->cb[GLUE_CB_OFFSET+16]))) + +/* Check validity of prDev, private data, and pointers */ +#define GLUE_CHK_DEV(prDev) \ + ((prDev && *((P_GLUE_INFO_T *) netdev_priv(prDev))) ? TRUE : FALSE) + +#define GLUE_CHK_PR2(prDev, pr2) \ + ((GLUE_CHK_DEV(prDev) && pr2) ? TRUE : FALSE) + +#define GLUE_CHK_PR3(prDev, pr2, pr3) \ + ((GLUE_CHK_PR2(prDev, pr2) && pr3) ? TRUE : FALSE) + +#define GLUE_CHK_PR4(prDev, pr2, pr3, pr4) \ + ((GLUE_CHK_PR3(prDev, pr2, pr3) && pr4) ? TRUE : FALSE) + +#define GLUE_SET_EVENT(pr) \ + kalSetEvent(pr) + +#define GLUE_INC_REF_CNT(_refCount) atomic_inc((atomic_t *)&(_refCount)) +#define GLUE_DEC_REF_CNT(_refCount) atomic_dec((atomic_t *)&(_refCount)) + +#define DbgPrint(...) +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +#ifdef WLAN_INCLUDE_PROC +INT_32 procRemoveProcfs(VOID); + +INT_32 procCreateFsEntry(P_GLUE_INFO_T prGlueInfo); +INT_32 procInitFs(VOID); +INT_32 procUninitProcFs(VOID); + +#endif /* WLAN_INCLUDE_PROC */ + +#if CFG_ENABLE_BT_OVER_WIFI +BOOLEAN glRegisterAmpc(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glUnregisterAmpc(P_GLUE_INFO_T prGlueInfo); +#endif + +#if CFG_ENABLE_WIFI_DIRECT + +VOID wlanSubModRunInit(P_GLUE_INFO_T prGlueInfo); + +VOID wlanSubModRunExit(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN wlanSubModInit(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN wlanSubModExit(P_GLUE_INFO_T prGlueInfo); + +VOID +wlanSubModRegisterInitExit(SUB_MODULE_INIT rSubModInit, SUB_MODULE_EXIT rSubModExit, ENUM_SUB_MODULE_IDX_T eSubModIdx); + +BOOLEAN wlanExportGlueInfo(P_GLUE_INFO_T *prGlueInfoExpAddr); + +BOOLEAN wlanIsLaunched(VOID); + +VOID wlanUpdateChannelTable(P_GLUE_INFO_T prGlueInfo); + +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_OS_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h new file mode 100644 index 0000000000000..a27294e335003 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_ioctl.h @@ -0,0 +1,743 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_ioctl.h#9 +*/ + +/*! \file gl_p2p_ioctl.h + \brief This file is for custom ioctls for Wi-Fi Direct only +*/ + +/* +** Log: gl_p2p_ioctl.h +** +** 07 26 2012 yuche.tsai +** [ALPS00324337] [ALPS.JB][Hot-Spot] Driver update for Hot-Spot +** Update driver code of ALPS.JB for hot-spot. +** +** 07 19 2012 yuche.tsai +** NULL +** Code update for JB. + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 06 07 2011 yuche.tsai + * [WCXRP00000763] [Volunteer Patch][MT6620][Driver] RX Service Discovery Frame under AP mode Issue + * Fix RX SD request under AP mode issue. + * + * 03 25 2011 wh.su + * NULL + * Fix P2P IOCTL of multicast address bug, add low power driver stop control. + * + * 11 22 2011 yuche.tsai + * NULL + * Update RSSI link quality of P2P Network query method. (Bug fix) + * + * 11 19 2011 yuche.tsai + * NULL + * Add RSSI support for P2P network. + * + * 11 11 2011 yuche.tsai + * NULL + * Fix work thread cancel issue. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service + * discovery version check. + * Add support for driver version query & p2p supplicant verseion set. + * For new service discovery mechanism sync. + * + * 10 25 2011 cm.chang + * [WCXRP00001058] [All Wi-Fi][Driver] Fix sta_rec's phyTypeSet and OBSS scan in AP mode + * . + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 16 2011 chinglan.wang + * NULL + * Add the group id information in the invitation indication. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 05 04 2011 chinglan.wang + * [WCXRP00000698] [MT6620 Wi-Fi][P2P][Driver] Add p2p invitation command for the p2p driver + * . + * + * 03 29 2011 wh.su + * [WCXRP00000095] [MT6620 Wi-Fi] [FW] Refine the P2P GO send broadcast protected code + * add the set power and get power function sample. + * + * 03 22 2011 george.huang + * [WCXRP00000504] [MT6620 Wi-Fi][FW] Support Sigma CAPI for power saving related command + * link with supplicant commands + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 03 01 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * fixed the ioctl sumcmd to meet the p2p_supplicant setting. + * + * 02 23 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int define for p2p parameter. + * + * 02 22 2011 wh.su + * [WCXRP00000488] [MT6620 Wi-Fi][Driver] Support the SIGMA set p2p parameter to driver + * adding the ioctl set int from supplicant, and can used to set the p2p parameters + * + * 02 17 2011 wh.su + * [WCXRP00000448] [MT6620 Wi-Fi][Driver] Fixed WSC IE not send out at probe request + * adjust the set wsc ie structure. + * + * 01 05 2011 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * ioctl implementations for P2P Service Discovery + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * + * 12 15 2010 cp.wu + * NULL + * invoke nicEnableInterrupt() before leaving from wlanAdapterStart() + * + * 12 07 2010 cp.wu + * [WCXRP00000237] [MT6620 Wi-Fi][Wi-Fi Direct][Driver] Add interface for supporting service discovery + * define a pair of i/o control for multiplexing layer + * + * 11 04 2010 wh.su + * [WCXRP00000164] [MT6620 Wi-Fi][Driver] Support the p2p random SSID + * adding the p2p random ssid support. + * + * 10 20 2010 wh.su + * [WCXRP00000124] [MT6620 Wi-Fi] [Driver] Support the dissolve P2P Group + * Add the code to support disconnect p2p group + * + * 09 21 2010 kevin.huang + * [WCXRP00000054] [MT6620 Wi-Fi][Driver] Restructure driver for second Interface + * Isolate P2P related function for Hardware Software Bundle + * + * 09 10 2010 george.huang + * NULL + * update iwpriv LP related + * + * 09 07 2010 wh.su + * NULL + * adding the code for beacon/probe req/ probe rsp wsc ie at p2p. + * + * 08 25 2010 cp.wu + * NULL + * add netdev_ops(NDO) for linux kernel 2.6.31 or greater + * + * 08 20 2010 yuche.tsai + * NULL + * Refine a function parameter name. + * + * 08 19 2010 cp.wu + * NULL + * add set mac address interface for further possibilities of wpa_supplicant overriding interface address. + * + * 08 16 2010 george.huang + * NULL + * add wext handlers to link P2P set PS profile/ network address function (TBD) + * + * 08 16 2010 cp.wu + * NULL + * revised implementation of Wi-Fi Direct io controls. + * + * 08 12 2010 cp.wu + * NULL + * follow-up with ioctl interface update for Wi-Fi Direct application + * + * 08 06 2010 cp.wu + * NULL + * driver hook modifications corresponding to ioctl interface change. + * + * 08 03 2010 cp.wu + * NULL + * [Wi-Fi Direct] add framework for driver hooks + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 06 01 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl to configure scan mode for p2p connection + * + * 05 31 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add cfg80211 interface, which is to replace WE, for further extension + * + * 05 17 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement get scan result. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * implement wireless extension ioctls in iw_handler form. + * + * 05 14 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl framework for Wi-Fi Direct by reusing wireless extension ioctls as well + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * p2p ioctls revised. + * + * 05 11 2010 cp.wu + * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support + * add ioctl for controlling p2p scan phase parameters + * +*/ + +#ifndef _GL_P2P_IOCTL_H +#define _GL_P2P_IOCTL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Device private ioctl calls */ +/* #define SIOCDEVPRIVATE 0x89F0*/ +#define IOC_GET_PRIVATE_IOCTL_CMD (SIOCDEVPRIVATE+1) + +/* (WirelessExtension) Private I/O Controls */ +#define IOC_P2P_CFG_DEVICE (SIOCIWFIRSTPRIV+0) +#define IOC_P2P_PROVISION_COMPLETE (SIOCIWFIRSTPRIV+2) +#define IOC_P2P_START_STOP_DISCOVERY (SIOCIWFIRSTPRIV+4) +#define IOC_P2P_DISCOVERY_RESULTS (SIOCIWFIRSTPRIV+5) +#define IOC_P2P_WSC_BEACON_PROBE_RSP_IE (SIOCIWFIRSTPRIV+6) +#define IOC_P2P_GO_WSC_IE IOC_P2P_WSC_BEACON_PROBE_RSP_IE +#define IOC_P2P_CONNECT_DISCONNECT (SIOCIWFIRSTPRIV+8) +#define IOC_P2P_PASSWORD_READY (SIOCIWFIRSTPRIV+10) +/* #define IOC_P2P_SET_PWR_MGMT_PARAM (SIOCIWFIRSTPRIV+12) */ +#define IOC_P2P_SET_INT (SIOCIWFIRSTPRIV+12) +#define IOC_P2P_GET_STRUCT (SIOCIWFIRSTPRIV+13) +#define IOC_P2P_SET_STRUCT (SIOCIWFIRSTPRIV+14) +#define IOC_P2P_GET_REQ_DEVICE_INFO (SIOCIWFIRSTPRIV+15) + +#define PRIV_CMD_INT_P2P_SET 0 + +/* IOC_P2P_PROVISION_COMPLETE (iw_point . flags) */ +#define P2P_PROVISIONING_SUCCESS 0 +#define P2P_PROVISIONING_FAIL 1 + +/* IOC_P2P_START_STOP_DISCOVERY (iw_point . flags) */ +#define P2P_STOP_DISCOVERY 0 +#define P2P_START_DISCOVERY 1 + +/* IOC_P2P_CONNECT_DISCONNECT (iw_point . flags) */ +#define P2P_CONNECT 0 +#define P2P_DISCONNECT 1 + +/* IOC_P2P_START_STOP_DISCOVERY (scan_type) */ +#define P2P_SCAN_FULL_AND_FIND 0 +#define P2P_SCAN_FULL 1 +#define P2P_SCAN_SEARCH_AND_LISTEN 2 +#define P2P_LISTEN 3 + +/* IOC_P2P_GET_STRUCT/IOC_P2P_SET_STRUCT */ +#define P2P_SEND_SD_RESPONSE 0 +#define P2P_GET_SD_REQUEST 1 +#define P2P_SEND_SD_REQUEST 2 +#define P2P_GET_SD_RESPONSE 3 +#define P2P_TERMINATE_SD_PHASE 4 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/*----------------------------------------------------------------------------*/ +/* Wireless Extension: Private I/O Control */ +/*----------------------------------------------------------------------------*/ +typedef struct iw_p2p_cfg_device_type { + void __user *ssid; + UINT_8 ssid_len; + UINT_8 pri_device_type[8]; + UINT_8 snd_device_type[8]; + void __user *device_name; + UINT_8 device_name_len; + UINT_8 intend; + UINT_8 persistence; + UINT_8 sec_mode; + UINT_8 ch; + UINT_8 ch_width; /* 0: 20 Mhz 1:20/40 Mhz auto */ + UINT_8 max_scb; +} IW_P2P_CFG_DEVICE_TYPE, *P_IW_P2P_CFG_DEVICE_TYPE; + +typedef struct iw_p2p_hostapd_param { + UINT_8 cmd; + UINT_8 rsv[3]; + UINT_8 sta_addr[6]; + void __user *data; + UINT_16 len; +} IW_P2P_HOSTAPD_PARAM, *P_IW_P2P_HOSTAPD_PARAM; + +typedef struct iw_p2p_req_device_type { + UINT_8 scan_type; /* 0: Full scan + Find + * 1: Full scan + * 2: Scan (Search +Listen) + * 3: Listen + * other : reserved + */ + UINT_8 pri_device_type[8]; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_REQ_DEVICE_TYPE, *P_IW_P2P_REQ_DEVICE_TYPE; + +typedef struct iw_p2p_connect_device { + UINT_8 sta_addr[6]; + UINT_8 p2pRole; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 authPeer; /* 1: auth peer invitation request */ + UINT_8 intend_config_method; /* Request Peer Device used config method */ +} IW_P2P_CONNECT_DEVICE, *P_IW_P2P_CONNECT_DEVICE; + +typedef struct iw_p2p_password_ready { + UINT_8 active_config_method; + void __user *probe_req_ie; + UINT_16 probe_req_len; + void __user *probe_rsp_ie; + UINT_16 probe_rsp_len; +} IW_P2P_PASSWORD_READY, *P_IW_P2P_PASSWORD_READY; + +typedef struct iw_p2p_device_req { + UINT_8 name[33]; + UINT_32 name_len; + UINT_8 device_addr[6]; + UINT_8 device_type; + INT_32 config_method; + INT_32 active_config_method; +} IW_P2P_DEVICE_REQ, *P_IW_P2P_DEVICE_REQ; + +typedef struct iw_p2p_transport_struct { + UINT_32 u4CmdId; + UINT_32 inBufferLength; + UINT_32 outBufferLength; + UINT_8 aucBuffer[16]; +} IW_P2P_TRANSPORT_STRUCT, *P_IW_P2P_TRANSPORT_STRUCT; + +/* For Invitation */ +typedef struct iw_p2p_ioctl_invitation_struct { + UINT_8 aucDeviceID[6]; + UINT_8 aucGroupID[6]; /* BSSID */ + UINT_8 aucSsid[32]; + UINT_32 u4SsidLen; + UINT_8 ucReinvoke; +} IW_P2P_IOCTL_INVITATION_STRUCT, *P_IW_P2P_IOCTL_INVITATION_STRUCT; + +typedef struct iw_p2p_ioctl_abort_invitation { + UINT_8 dev_addr[6]; +} IW_P2P_IOCTL_ABORT_INVITATION, *P_IW_P2P_IOCTL_ABORT_INVITATION; + +typedef struct iw_p2p_ioctl_invitation_indicate { + UINT_8 dev_addr[6]; + UINT_8 group_bssid[6]; + INT_32 config_method; /* peer device supported config method */ + UINT_8 dev_name[32]; /* for reinvoke */ + UINT_32 name_len; + UINT_8 operating_channel; /* for re-invoke, target operating channel */ + UINT_8 invitation_type; /* invitation or re-invoke */ +} IW_P2P_IOCTL_INVITATION_INDICATE, *P_IW_P2P_IOCTL_INVITATION_INDICATE; + +typedef struct iw_p2p_ioctl_invitation_status { + UINT_32 status_code; +} IW_P2P_IOCTL_INVITATION_STATUS, *P_IW_P2P_IOCTL_INVITATION_STATUS; + +/* For Formation */ +typedef struct iw_p2p_ioctl_start_formation { + UINT_8 dev_addr[6]; /* bssid */ + UINT_8 role; /* 0: P2P Device, 1:GC, 2: GO */ + UINT_8 needProvision; /* 0: Don't needed provision, 1: doing the wsc provision first */ + UINT_8 auth; /* 1: auth peer invitation request */ + UINT_8 config_method; /* Request Peer Device used config method */ +} IW_P2P_IOCTL_START_FORMATION, *P_IW_P2P_IOCTL_START_FORMATION; + +/* SET_STRUCT / GET_STRUCT */ +typedef enum _ENUM_P2P_CMD_ID_T { + P2P_CMD_ID_SEND_SD_RESPONSE = 0, /* 0x00 (Set) */ + P2P_CMD_ID_GET_SD_REQUEST, /* 0x01 (Get) */ + P2P_CMD_ID_SEND_SD_REQUEST, /* 0x02 (Set) */ + P2P_CMD_ID_GET_SD_RESPONSE, /* 0x03 (Get) */ + P2P_CMD_ID_TERMINATE_SD_PHASE, /* 0x04 (Set) */ +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + P2P_CMD_ID_SEC_CHECK, /* 0x05(Set) */ +#endif + P2P_CMD_ID_INVITATION, /* 0x06 (Set) */ + P2P_CMD_ID_INVITATION_INDICATE, /* 0x07 (Get) */ + P2P_CMD_ID_INVITATION_STATUS, /* 0x08 (Get) */ + P2P_CMD_ID_INVITATION_ABORT, /* 0x09 (Set) */ + P2P_CMD_ID_START_FORMATION, /* 0x0A (Set) */ + P2P_CMD_ID_P2P_VERSION, /* 0x0B (Set/Get) */ + P2P_CMD_ID_GET_CH_LIST = 12, /* 0x0C (Get) */ + P2P_CMD_ID_GET_OP_CH = 14 /* 0x0E (Get) */ +} ENUM_P2P_CMD_ID_T, *P_ENUM_P2P_CMD_ID_T; + +/* Service Discovery */ +typedef struct iw_p2p_cmd_send_sd_response { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_SEND_SD_RESPONSE, *P_IW_P2P_CMD_SEND_SD_RESPONSE; + +typedef struct iw_p2p_cmd_get_sd_request { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_GET_SD_REQUEST, *P_IW_P2P_CMD_GET_SD_REQUEST; + +typedef struct iw_p2p_cmd_send_service_discovery_request { + PARAM_MAC_ADDRESS rReceiverAddr; + UINT_8 fgNeedTxDoneIndication; + UINT_8 ucSeqNum; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_SEND_SD_REQUEST, *P_IW_P2P_CMD_SEND_SD_REQUEST; + +typedef struct iw_p2p_cmd_get_sd_response { + PARAM_MAC_ADDRESS rTransmitterAddr; + UINT_16 u2PacketLength; + UINT_8 aucPacketContent[0]; /*native 802.11 */ +} IW_P2P_CMD_GET_SD_RESPONSE, *P_IW_P2P_CMD_GET_SD_RESPONSE; + +typedef struct iw_p2p_cmd_terminate_sd_phase { + PARAM_MAC_ADDRESS rPeerAddr; +} IW_P2P_CMD_TERMINATE_SD_PHASE, *P_IW_P2P_CMD_TERMINATE_SD_PHASE; + +typedef struct iw_p2p_version { + UINT_32 u4Version; +} IW_P2P_VERSION, *P_IW_P2P_VERSION; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +extern struct ieee80211_supported_band mtk_band_2ghz; +extern struct ieee80211_supported_band mtk_band_5ghz; +extern UINT_32 mtk_cipher_suites[5]; +#endif + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +int mtk_p2p_cfg80211_change_iface(struct wiphy *wiphy, + struct net_device *ndev, + enum nl80211_iftype type,/* u32 *flags,*/ struct vif_params *params); + +int mtk_p2p_cfg80211_add_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, bool pairwise, const u8 *mac_addr, struct key_params *params); + +int mtk_p2p_cfg80211_get_key(struct wiphy *wiphy, + struct net_device *ndev, + u8 key_index, + bool pairwise, + const u8 *mac_addr, void *cookie, void (*callback) (void *cookie, struct key_params *) +); + +int mtk_p2p_cfg80211_del_key(struct wiphy *wiphy, + struct net_device *ndev, u8 key_index, bool pairwise, const u8 *mac_addr); + +int +mtk_p2p_cfg80211_set_default_key(struct wiphy *wiphy, + struct net_device *netdev, u8 key_index, bool unicast, bool multicast); + +int mtk_p2p_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, + const u8 *mac, struct station_info *sinfo); + +int mtk_p2p_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed); + +int mtk_p2p_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_connect_params *sme); + +int mtk_p2p_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, u16 reason_code); + +int mtk_p2p_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params); + +int mtk_p2p_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev); + +int mtk_p2p_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, int timeout); + +int mtk_p2p_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev, struct bss_parameters *params); + +int mtk_p2p_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, unsigned int duration, u64 *cookie); + +int mtk_p2p_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request); + +int mtk_p2p_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie); + +int mtk_p2p_cfg80211_set_txpower(struct wiphy *wiphy, + struct wireless_dev *wdev, enum nl80211_tx_power_setting type, int mbm); + +int mtk_p2p_cfg80211_get_txpower(struct wiphy *wiphy, struct wireless_dev *wdev, int *dbm); + +int mtk_p2p_cfg80211_deauth(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_deauth_request *req); + +int mtk_p2p_cfg80211_disassoc(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_disassoc_request *req); + +int mtk_p2p_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ap_settings *settings); + +int mtk_p2p_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *info); + +int mtk_p2p_cfg80211_mgmt_tx(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct cfg80211_mgmt_tx_params *params, + u64 *cookie); + +int mtk_p2p_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev); + +int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params); +//int mtk_p2p_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, const u8 *mac); + +int mtk_p2p_cfg80211_set_channel(struct wiphy *wiphy, struct cfg80211_chan_def *chandef); + +void mtk_p2p_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct wireless_dev *wdev, u16 frame_type, bool reg); + +int +mtk_p2p_cfg80211_set_bitrate_mask(IN struct wiphy *wiphy, + IN struct net_device *dev, + IN const u8 *peer, IN const struct cfg80211_bitrate_mask *mask); + +#ifdef CONFIG_NL80211_TESTMODE +int mtk_p2p_cfg80211_testmode_cmd(IN struct wiphy *wiphy, IN struct wireless_dev *wdev, IN void *data, IN int len); +int mtk_p2p_cfg80211_testmode_p2p_sigma_pre_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +int mtk_p2p_cfg80211_testmode_p2p_sigma_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); + +#if CFG_SUPPORT_WFD +int mtk_p2p_cfg80211_testmode_wfd_update_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#endif + +int mtk_p2p_cfg80211_testmode_hotspot_block_cmd(IN struct wiphy *wiphy, IN void *data, IN int len); +#else +#error "Please ENABLE kernel config (CONFIG_NL80211_TESTMODE) to support Wi-Fi Direct" +#endif + +#endif + +/* I/O control handlers */ + +int +mtk_p2p_wext_get_priv(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_reconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_auth(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_key(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_mlme_handler(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_powermode(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls takes use of iw_handler */ +int +mtk_p2p_wext_set_local_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_provision_complete(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_start_stop_discovery(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_discovery_results(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_wsc_ie(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_connect_disconnect(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_password_ready(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_request_dev_info(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_indicate(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_invitation_status(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_pm_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_ps_profile(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_network_address(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_int(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* Private Wireless I/O Controls for IOC_SET_STRUCT/IOC_GET_STRUCT */ +int +mtk_p2p_wext_set_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_struct(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +/* IOC_SET_STRUCT/IOC_GET_STRUCT: Service Discovery */ +int +mtk_p2p_wext_get_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_request(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_send_service_discovery_response(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_terminate_service_discovery_phase(IN struct net_device *prDev, + IN struct iw_request_info *info, + IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +#if CFG_SUPPORT_ANTI_PIRACY +int +mtk_p2p_wext_set_sec_check_request(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_sec_check_response(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); +#endif + +int +mtk_p2p_wext_set_noa_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_oppps_param(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_set_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +int +mtk_p2p_wext_get_p2p_version(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +void mtk_p2p_wext_set_Multicastlist(IN P_GLUE_INFO_T prGlueInfo); + +#if CFG_SUPPORT_P2P_RSSI_QUERY +int +mtk_p2p_wext_get_rssi(IN struct net_device *prDev, + IN struct iw_request_info *info, IN OUT union iwreq_data *wrqu, IN OUT char *extra); + +struct iw_statistics *mtk_p2p_wext_get_wireless_stats(struct net_device *prDev); + +#endif + +int +mtk_p2p_wext_set_txpow(IN struct net_device *prDev, + IN struct iw_request_info *prIwrInfo, IN OUT union iwreq_data *prTxPow, IN char *pcExtra); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_P2P_IOCTL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h new file mode 100644 index 0000000000000..bf9d8871ef48a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_kal.h @@ -0,0 +1,243 @@ +/* +** Id: //Department/DaVinci/TRUNK/WiFi_P2P_Driver/os/linux/include/gl_p2p_kal.h#2 +*/ + +/*! \file gl_p2p_kal.h + \brief Declaration of KAL functions for Wi-Fi Direct support + - kal*() which is provided by GLUE Layer. + + Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +/* +** Log: gl_p2p_kal.h +** +** 08 30 2012 chinglan.wang +** [ALPS00349664] [6577JB][WIFI] Phone can not connect to AP secured with AES via WPS in 802.11n Only +** . + * + * 07 17 2012 yuche.tsai + * NULL + * Compile no error before trial run. + * + * 10 18 2011 yuche.tsai + * [WCXRP00001045] [WiFi Direct][Driver] Check 2.1 branch. + * New 2.1 branch + + * + * 08 15 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Add group BSSID in invitation request indication. + * The BSSID is used for APP to decide the configure method. + * + * 08 09 2011 yuche.tsai + * [WCXRP00000919] [Volunteer Patch][WiFi Direct][Driver] Invitation New Feature. + * Invitation Feature add on. + * + * 03 19 2011 terry.wu + * [WCXRP00000577] [MT6620 Wi-Fi][Driver][FW] Create V2.0 branch for firmware and driver + * create V2.0 p2p driver release based on label "MT6620_WIFI_P2P_DRIVER_V2_0_2100_0319_2011" from main trunk. + * + * 03 07 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * rename the define to anti_pviracy. + * + * 03 05 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * add the code to get the check rsponse and indicate to app. + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add Security check related code. + * + * 12 22 2010 cp.wu + * [WCXRP00000283] [MT6620 Wi-Fi][Driver][Wi-Fi Direct] Implementation of interface for supporting Wi-Fi Direct Service + * Discovery + * 1. header file restructure for more clear module isolation + * 2. add function interface definition for implementing Service Discovery callbacks + * +*/ + +#ifndef _GL_P2P_KAL_H +#define _GL_P2P_KAL_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "config.h" +#include "gl_typedef.h" +#include "gl_os.h" +#include "wlan_lib.h" +#include "wlan_oid.h" +#include "wlan_p2p.h" +#include "gl_kal.h" +#include "gl_wext_priv.h" +#include "nic/p2p.h" + +#if DBG +extern int allocatedMemSize; +#endif + +extern BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); + +#if CFG_SUPPORT_WPS +extern BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT unsigned char **ppucDesiredIE); +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +BOOLEAN kalP2pFuncGetChannelType(IN ENUM_CHNL_EXT_T rChnlSco, OUT enum nl80211_channel_type *channel_type); +struct ieee80211_channel *kalP2pFuncGetChannelEntry(IN P_GL_P2P_INFO_T prP2pInfo, IN P_RF_CHANNEL_INFO_T prChannelInfo); + +/* Service Discovery */ +VOID kalP2PIndicateSDRequest(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum); + +void kalP2PIndicateSDResponse(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucSeqNum); + +VOID kalP2PIndicateTXDone(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucSeqNum, IN UINT_8 ucStatus); + +/*----------------------------------------------------------------------------*/ +/* Wi-Fi Direct handling */ +/*----------------------------------------------------------------------------*/ +ENUM_PARAM_MEDIA_STATE_T kalP2PGetState(IN P_GLUE_INFO_T prGlueInfo); + +VOID +kalP2PSetState(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_PARAM_MEDIA_STATE_T eState, IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucRole); + +VOID +kalP2PUpdateAssocInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBody, IN UINT_32 u4FrameBodyLen, IN BOOLEAN fgReassocRequest); + +UINT_32 kalP2PGetFreqInKHz(IN P_GLUE_INFO_T prGlueInfo); + +UINT_8 kalP2PGetRole(IN P_GLUE_INFO_T prGlueInfo); + +VOID +kalP2PSetRole(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_8 ucResult, IN PUINT_8 pucSSID, IN UINT_8 ucSSIDLen, IN UINT_8 ucRole); + +VOID kalP2PSetCipher(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Cipher); + +BOOLEAN kalP2PGetCipher(IN P_GLUE_INFO_T prGlueInfo); + +BOOLEAN kalP2PGetTkipCipher(IN P_GLUE_INFO_T prGlueInfo); + +BOOLEAN kalP2PGetCcmpCipher(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalP2PSetWscMode(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucWscMode); + +UINT_8 kalP2PGetWscMode(IN P_GLUE_INFO_T prGlueInfo); + +UINT_16 kalP2PCalWSC_IELen(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType); + +VOID kalP2PGenWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer); + +VOID kalP2PUpdateWSC_IE(IN P_GLUE_INFO_T prGlueInfo, IN UINT_8 ucType, IN PUINT_8 pucBuffer, IN UINT_16 u2BufferLength); + +BOOLEAN kalP2PIndicateFound(IN P_GLUE_INFO_T prGlueInfo); + +VOID kalP2PIndicateConnReq(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucDevName, IN INT_32 u4NameLength, + IN PARAM_MAC_ADDRESS rPeerAddr, IN UINT_8 ucDevType, /* 0: P2P Device / 1: GC / 2: GO */ + IN INT_32 i4ConfigMethod, IN INT_32 i4ActiveConfigMethod); + +VOID kalP2PInvitationStatus(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4InvStatus); + +VOID +kalP2PInvitationIndication(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_DEVICE_DESC_T prP2pDevDesc, + IN PUINT_8 pucSsid, + IN UINT_8 ucSsidLen, + IN UINT_8 ucOperatingChnl, IN UINT_8 ucInvitationType, IN PUINT_8 pucGroupBssid); + +struct net_device *kalP2PGetDevHdlr(P_GLUE_INFO_T prGlueInfo); + +VOID +kalGetChnlList(IN P_GLUE_INFO_T prGlueInfo, + IN ENUM_BAND_T eSpecificBand, + IN UINT_8 ucMaxChannelNum, IN PUINT_8 pucNumOfChannel, IN P_RF_CHANNEL_INFO_T paucChannelList); + +#if CFG_SUPPORT_ANTI_PIRACY +VOID kalP2PIndicateSecCheckRsp(IN P_GLUE_INFO_T prGlueInfo, IN PUINT_8 pucRsp, IN UINT_16 u2RspLen); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID +kalP2PIndicateChannelReady(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8SeqNum, + IN UINT_32 u4ChannelNum, + IN ENUM_BAND_T eBand, IN ENUM_CHNL_EXT_T eSco, IN UINT_32 u4Duration); + +VOID kalP2PIndicateScanDone(IN P_GLUE_INFO_T prGlueInfo, IN BOOLEAN fgIsAbort); + +VOID +kalP2PIndicateBssInfo(IN P_GLUE_INFO_T prGlueInfo, + IN PUINT_8 pucFrameBuf, + IN UINT_32 u4BufLen, IN P_RF_CHANNEL_INFO_T prChannelInfo, IN INT_32 i4SignalStrength); + +VOID kalP2PIndicateRxMgmtFrame(IN P_GLUE_INFO_T prGlueInfo, IN P_SW_RFB_T prSwRfb); + +VOID +kalP2PIndicateMgmtTxStatus(IN P_GLUE_INFO_T prGlueInfo, + IN UINT_64 u8Cookie, IN BOOLEAN fgIsAck, IN PUINT_8 pucFrameBuf, IN UINT_32 u4FrameLen); + +VOID kalP2PIndicateChannelExpired(IN P_GLUE_INFO_T prGlueInfo, IN P_P2P_CHNL_REQ_INFO_T prChnlReqInfo); + +VOID +kalP2PGCIndicateConnectionStatus(IN P_GLUE_INFO_T prGlueInfo, + IN P_P2P_CONNECTION_REQ_INFO_T prP2pConnInfo, + IN PUINT_8 pucRxIEBuf, IN UINT_16 u2RxIELen, IN UINT_16 u2StatusReason, + IN WLAN_STATUS eStatus); + +VOID kalP2PGOStationUpdate(IN P_GLUE_INFO_T prGlueInfo, IN P_STA_RECORD_T prCliStaRec, IN BOOLEAN fgIsNew); + +INT_32 kalP2PSetBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid, IN BOOLEAN fgIsblock); + +BOOLEAN kalP2PCmpBlackList(IN P_GLUE_INFO_T prGlueInfo, IN PARAM_MAC_ADDRESS rbssid); + +VOID kalP2PSetMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4MaxClient); + +BOOLEAN kalP2PMaxClients(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4NumClient); + +#endif /* _GL_P2P_KAL_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h new file mode 100644 index 0000000000000..e5026e7e6eec5 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_p2p_os.h @@ -0,0 +1,242 @@ +/* +** Id: +//Department/DaVinci/TRUNK/MT6620_5931_WiFi_Driver/os/linux/include/gl_p2p_os.h#28 +*/ + +/*! \file gl_p2p_os.h + \brief List the external reference to OS for p2p GLUE Layer. + + In this file we define the data structure - GLUE_INFO_T to store those objects + we acquired from OS - e.g. TIMER, SPINLOCK, NET DEVICE ... . And all the + external reference (header file, extern func() ..) to OS for GLUE Layer should + also list down here. +*/ + +#ifndef _GL_P2P_OS_H +#define _GL_P2P_OS_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 +#include +#endif + +#include "wlan_oid.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +struct _GL_P2P_INFO_T { + + /* Device handle */ + struct net_device *prDevHandler; + +#if CFG_ENABLE_WIFI_DIRECT_CFG_80211 + /* cfg80211 */ + struct wireless_dev *prWdev; + + struct cfg80211_scan_request *prScanRequest; + + UINT_64 u8Cookie; + + /* Generation for station list update. */ + INT_32 i4Generation; + + UINT_32 u4OsMgmtFrameFilter; + +#endif + + /* Device statistics */ + struct net_device_stats rNetDevStats; + + /* glue layer variables */ + UINT_32 u4FreqInKHz; /* frequency */ + UINT_8 ucRole; /* 0: P2P Device, 1: Group Client, 2: Group Owner */ + UINT_8 ucIntent; /* range: 0-15 */ + UINT_8 ucScanMode; /* 0: Search & Listen, 1: Scan without probe response */ + + ENUM_PARAM_MEDIA_STATE_T eState; + UINT_32 u4PacketFilter; + PARAM_MAC_ADDRESS aucMCAddrList[MAX_NUM_GROUP_ADDR]; + + /* connection-requested peer information */ + UINT_8 aucConnReqDevName[32]; + INT_32 u4ConnReqNameLength; + PARAM_MAC_ADDRESS rConnReqPeerAddr; + PARAM_MAC_ADDRESS rConnReqGroupAddr; /* For invitation group. */ + UINT_8 ucConnReqDevType; + INT_32 i4ConnReqConfigMethod; + INT_32 i4ConnReqActiveConfigMethod; + + UINT_32 u4CipherPairwise; + UINT_8 ucWSCRunning; + + UINT_8 aucWSCIE[3][400]; /* 0 for beacon, 1 for probe req, 2 for probe response */ + UINT_16 u2WSCIELen[3]; + +#if CFG_SUPPORT_WFD + UINT_8 aucVenderIE[1024]; /* Save the other IE for prove resp */ + UINT_16 u2VenderIELen; +#endif + + UINT_8 ucOperatingChnl; + UINT_8 ucInvitationType; + + UINT_32 u4InvStatus; + + /* For SET_STRUCT/GET_STRUCT */ + UINT_8 aucOidBuf[4096]; + +#if 1 /* CFG_SUPPORT_ANTI_PIRACY */ + UINT_8 aucSecCheck[256]; + UINT_8 aucSecCheckRsp[256]; +#endif + + /* Hotspot Client Management */ + PARAM_MAC_ADDRESS aucblackMACList[8]; + UINT_8 ucMaxClients; + +#if CFG_SUPPORT_HOTSPOT_OPTIMIZATION + UINT_32 u4PsLevel; +#endif +}; + +#ifdef CONFIG_NL80211_TESTMODE +typedef struct _NL80211_DRIVER_TEST_PRE_PARAMS { + UINT_16 idx_mode; + UINT_16 idx; + UINT_32 value; +} NL80211_DRIVER_TEST_PRE_PARAMS, *P_NL80211_DRIVER_TEST_PRE_PARAMS; + +typedef struct _NL80211_DRIVER_TEST_PARAMS { + UINT_32 index; + UINT_32 buflen; +} NL80211_DRIVER_TEST_PARAMS, *P_NL80211_DRIVER_TEST_PARAMS; + +/* P2P Sigma*/ +typedef struct _NL80211_DRIVER_P2P_SIGMA_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 idx; + UINT_32 value; +} NL80211_DRIVER_P2P_SIGMA_PARAMS, *P_NL80211_DRIVER_P2P_SIGMA_PARAMS; + +/* Hotspot Client Management */ +typedef struct _NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_8 ucblocked; + UINT_8 aucBssid[MAC_ADDR_LEN]; +} NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS, *P_NL80211_DRIVER_HOTSPOT_BLOCK_PARAMS; + +#if CFG_SUPPORT_WFD +typedef struct _NL80211_DRIVER_WFD_PARAMS { + NL80211_DRIVER_TEST_PARAMS hdr; + UINT_32 WfdCmdType; + UINT_8 WfdEnable; + UINT_8 WfdCoupleSinkStatus; + UINT_8 WfdSessionAvailable; + UINT_8 WfdSigmaMode; + UINT_16 WfdDevInfo; + UINT_16 WfdControlPort; + UINT_16 WfdMaximumTp; + UINT_16 WfdExtendCap; + UINT_8 WfdCoupleSinkAddress[MAC_ADDR_LEN]; + UINT_8 WfdAssociatedBssid[MAC_ADDR_LEN]; + UINT_8 WfdVideoIp[4]; + UINT_8 WfdAudioIp[4]; + UINT_16 WfdVideoPort; + UINT_16 WfdAudioPort; + UINT_32 WfdFlag; + UINT_32 WfdPolicy; + UINT_32 WfdState; + UINT_8 WfdSessionInformationIE[24 * 8]; /* Include Subelement ID, length */ + UINT_16 WfdSessionInformationIELen; + UINT_8 aucReserved1[2]; + UINT_8 aucWfdPrimarySinkMac[MAC_ADDR_LEN]; + UINT_8 aucWfdSecondarySinkMac[MAC_ADDR_LEN]; + UINT_32 WfdAdvanceFlag; + /* Group 1 64 bytes */ + UINT_8 aucWfdLocalIp[4]; + UINT_16 WfdLifetimeAc2; /* Unit is 2 TU */ + UINT_16 WfdLifetimeAc3; /* Unit is 2 TU */ + UINT_16 WfdCounterThreshold; /* Unit is ms */ + UINT_8 aucReserved2[54]; + /* Group 3 64 bytes */ + UINT_8 aucReserved3[64]; + /* Group 3 64 bytes */ + UINT_8 aucReserved4[64]; +} NL80211_DRIVER_WFD_PARAMS, *P_NL80211_DRIVER_WFD_PARAMS; +#endif +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +BOOLEAN p2pLaunch(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2pRemove(P_GLUE_INFO_T prGlueInfo); + +VOID p2pSetMode(IN BOOLEAN fgIsAPMOde); + +BOOLEAN glRegisterP2P(P_GLUE_INFO_T prGlueInfo, const char *prDevName, BOOLEAN fgIsApMode); + +VOID p2pEalySuspendReg(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsEnable); + +BOOLEAN glUnregisterP2P(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2pNetRegister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); + +BOOLEAN p2pNetUnregister(P_GLUE_INFO_T prGlueInfo, BOOLEAN fgIsRtnlLockAcquired); + +BOOLEAN p2pStopImmediate(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN p2PFreeInfo(P_GLUE_INFO_T prGlueInfo); + +BOOLEAN glP2pCreateWirelessDevice(P_GLUE_INFO_T prGlueInfo); + +VOID glP2pDestroyWirelessDevice(VOID); + +VOID p2pSetMulticastListWorkQueueWrapper(P_GLUE_INFO_T prGlueInfo); + +#endif diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h new file mode 100644 index 0000000000000..f24ceee9e921a --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_rst.h @@ -0,0 +1,133 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_rst.h#1 +*/ + +/*! \file gl_rst.h + \brief Declaration of functions and finite state machine for + MT6620 Whole-Chip Reset Mechanism +*/ + +#ifndef _GL_RST_H +#define _GL_RST_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include "gl_typedef.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +#if 1 +typedef INT_32(*wmt_wlan_probe_cb) (VOID); +typedef INT_32(*wmt_wlan_remove_cb) (VOID); +typedef INT_32(*wmt_wlan_bus_cnt_get_cb) (VOID); +typedef INT_32(*wmt_wlan_bus_cnt_clr_cb) (VOID); + +typedef struct _MTK_WCN_WMT_WLAN_CB_INFO { + wmt_wlan_probe_cb wlan_probe_cb; + wmt_wlan_remove_cb wlan_remove_cb; + wmt_wlan_bus_cnt_get_cb wlan_bus_cnt_get_cb; + wmt_wlan_bus_cnt_clr_cb wlan_bus_cnt_clr_cb; +} MTK_WCN_WMT_WLAN_CB_INFO, *P_MTK_WCN_WMT_WLAN_CB_INFO; + +extern INT_32 mtk_wcn_wmt_wlan_reg(P_MTK_WCN_WMT_WLAN_CB_INFO pWmtWlanCbInfo); +extern INT_32 mtk_wcn_wmt_wlan_unreg(VOID); +#endif + +typedef enum _ENUM_RESET_STATUS_T { + RESET_FAIL, + RESET_SUCCESS +} ENUM_RESET_STATUS_T; + +typedef struct _RESET_STRUCT_T { + ENUM_RESET_STATUS_T rst_data; + struct work_struct rst_work; +} RESET_STRUCT_T; + +typedef enum _ENUM_WMTRSTMSG_TYPE_T { + WMTRSTMSG_RESET_START = 0x0, + WMTRSTMSG_RESET_END = 0x1, + WMTRSTMSG_RESET_END_FAIL = 0x2, + WMTRSTMSG_RESET_MAX, + WMTRSTMSG_RESET_INVALID = 0xff +} ENUM_WMTRSTMSG_TYPE_T, *P_ENUM_WMTRSTMSG_TYPE_T; + +typedef void (*PF_WMT_CB) (ENUM_WMTDRV_TYPE_T, /* Source driver type */ + ENUM_WMTDRV_TYPE_T, /* Destination driver type */ + ENUM_WMTMSG_TYPE_T, /* Message type */ + void *, /* READ-ONLY buffer. Buffer is allocated and freed by WMT_drv. Client + can't touch this buffer after this function return. */ + unsigned int /* Buffer size in unit of byte */ +); + +/******************************************************************************* +* E X T E R N A L F U N C T I O N S +******************************************************************************** +*/ +#define glDoChipReset() \ + do { \ + if (!kalStrnCmp(current->comm, "mtk_wmtd", 8)) { \ + g_IsNeedDoChipReset = 1; \ + DBGLOG(INIT, ERROR, "forbid core dump in mtk_wmtd %s line %d\n", __func__, __LINE__); \ + break; \ + } \ + DBGLOG(INIT, ERROR, "Do core dump and chip reset in %s line %d\n", __func__, __LINE__); \ + mtk_wcn_wmt_assert(WMTDRV_TYPE_WIFI, 0x40); \ + } while (0) + +#if CFG_CHIP_RESET_SUPPORT +extern int mtk_wcn_wmt_msgcb_reg(ENUM_WMTDRV_TYPE_T eType, PF_WMT_CB pCb); +extern int mtk_wcn_wmt_msgcb_unreg(ENUM_WMTDRV_TYPE_T eType); +extern int wifi_reset_start(void); +extern int wifi_reset_end(ENUM_RESET_STATUS_T); +#endif +extern MTK_WCN_BOOL mtk_wcn_wmt_assert(ENUM_WMTDRV_TYPE_T type, UINT32 reason); +extern BOOLEAN mtk_wcn_set_connsys_power_off_flag(BOOLEAN value); + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern UINT_32 g_IsNeedDoChipReset; +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +VOID glResetInit(VOID); + +VOID glResetUninit(VOID); + +VOID glSendResetRequest(VOID); + +BOOLEAN kalIsResetting(VOID); + +#endif /* _GL_RST_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h new file mode 100644 index 0000000000000..3cc57780f2010 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_sec.h @@ -0,0 +1,21 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_sec.h#1 +*/ + +/*! \file p2p_fsm.h + \brief Declaration of functions and finite state machine for P2P Module. + + Declaration of functions and finite state machine for P2P Module. +*/ + +#ifndef _GL_SEC_H +#define _GL_SEC_H + +extern void handle_sec_msg_1(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_2(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_3(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_4(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_5(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); +extern void handle_sec_msg_final(unsigned char *msg_in, int msg_in_len, unsigned char *msg_out, int *msg_out_len); + +#endif /* _GL_SEC_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h new file mode 100644 index 0000000000000..e9aa3e849eb2e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_typedef.h @@ -0,0 +1,298 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_typedef.h#1 +*/ + +/*! \file gl_typedef.h + \brief Definition of basic data type(os dependent). + + In this file we define the basic data type. +*/ + +/* +** Log: gl_typedef.h + * + * 06 22 2012 cp.wu + * [WCXRP00001257] [MT6620][MT5931][MT6628][Driver][Linux] Modify KAL_HZ to align ms accuracy + * modify KAL_HZ to (1000) for correct definition. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * portability improvement + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\6 2009-08-18 22:57:14 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\5 2008-09-22 23:19:30 GMT mtk01461 +** Update comment for code review +** \main\maintrunk.MT5921\4 2008-09-05 17:25:16 GMT mtk01461 +** Update Driver for Code Review +** \main\maintrunk.MT5921\3 2007-11-09 11:00:50 GMT mtk01425 +** 1. Use macro to unify network-to-host and host-to-network related functions +** Revision 1.3 2007/06/27 02:18:51 MTK01461 +** Update SCAN_FSM, Initial(Can Load Module), Proc(Can do Reg R/W), TX API +** +** Revision 1.2 2007/06/25 06:16:24 MTK01461 +** Update illustrations, gl_init.c, gl_kal.c, gl_kal.h, gl_os.h and RX API +** +*/ + +#ifndef _GL_TYPEDEF_H +#define _GL_TYPEDEF_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* Define HZ of timer tick for function kalGetTimeTick() */ +#define KAL_HZ (1000) + +/* Miscellaneous Equates */ +#ifndef FALSE +#define FALSE ((BOOLEAN) 0) +#define TRUE ((BOOLEAN) 1) +#endif /* FALSE */ + +#ifndef NULL +#if defined(__cplusplus) +#define NULL 0 +#else +#define NULL ((void *) 0) +#endif +#endif + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* Type definition for void */ +/*mach/mt_typedefs.h define _TYPEDEFS_H, to avoid compile error*/ +#ifndef _TYPEDEFS_H +typedef void VOID; +#endif +typedef void *PVOID, **PPVOID; + +/* Type definition for Boolean */ +typedef unsigned char BOOLEAN, *PBOOLEAN; + +/* Type definition for signed integers */ +typedef signed char CHAR, *PCHAR, **PPCHAR; +typedef signed char INT_8, *PINT_8, **PPINT_8; +typedef signed short INT_16, *PINT_16, **PPINT_16; +typedef signed int INT_32, *PINT_32, **PPINT_32; +typedef long LONG, *PLONG, **PPLONG; +typedef signed long long INT_64, *PINT_64, **PPINT_64; + +/* Type definition for unsigned integers */ +typedef unsigned char UCHAR, *PUCHAR, **PPUCHAR; +typedef unsigned char UINT_8, *PUINT_8, **PPUINT_8, *P_UINT_8; +typedef unsigned short UINT_16, *PUINT_16, **PPUINT_16; +typedef unsigned int UINT32, *PUINT32; +typedef unsigned int UINT_32, *PUINT_32, **PPUINT_32; +typedef unsigned long ULONG, *PULONG, **PPULONG; +typedef unsigned long long UINT_64, *PUINT_64, **PPUINT_64; + +typedef unsigned int OS_SYSTIME, *POS_SYSTIME, **PPOS_SYSTIME; + +#ifndef _TYPEDEFS_H +typedef signed char INT8, *PINT8; +typedef signed short INT16, *PINT16; +typedef signed int INT32, *PINT32; +typedef unsigned char UINT8, *PUINT8; +typedef unsigned short UINT16, *PUINT16; +typedef unsigned int UINT32, *PUINT32; +#endif + +/* Type definition of large integer (64bits) union to be comptaible with + * Windows definition, so we won't apply our own coding style to these data types. + * NOTE: LARGE_INTEGER must NOT be floating variable. + * : Check for big-endian compatibility. + */ +typedef union _LARGE_INTEGER { + struct { + UINT_32 LowPart; + INT_32 HighPart; + } u; + INT_64 QuadPart; +} LARGE_INTEGER, *PLARGE_INTEGER; + +typedef union _ULARGE_INTEGER { + struct { + UINT_32 LowPart; + UINT_32 HighPart; + } u; + UINT_64 QuadPart; +} ULARGE_INTEGER, *PULARGE_INTEGER; + +typedef INT_32(*probe_card) (PVOID pvData); +typedef VOID(*remove_card) (VOID); + +/* duplicated from wmt_exp.h for better driver isolation */ +typedef enum _ENUM_WMTDRV_TYPE_T { + WMTDRV_TYPE_BT = 0, + WMTDRV_TYPE_FM = 1, + WMTDRV_TYPE_GPS = 2, + WMTDRV_TYPE_WIFI = 3, + WMTDRV_TYPE_WMT = 4, + WMTDRV_TYPE_STP = 5, + WMTDRV_TYPE_SDIO1 = 6, + WMTDRV_TYPE_SDIO2 = 7, + WMTDRV_TYPE_LPBK = 8, + WMTDRV_TYPE_MAX +} ENUM_WMTDRV_TYPE_T, *P_ENUM_WMTDRV_TYPE_T; + +typedef enum _ENUM_WMTMSG_TYPE_T { + WMTMSG_TYPE_POWER_ON = 0, + WMTMSG_TYPE_POWER_OFF = 1, + WMTMSG_TYPE_RESET = 2, + WMTMSG_TYPE_STP_RDY = 3, + WMTMSG_TYPE_HW_FUNC_ON = 4, + WMTMSG_TYPE_MAX +} ENUM_WMTMSG_TYPE_T, *P_ENUM_WMTMSG_TYPE_T; + + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +#define IN /* volatile */ +#define OUT /* volatile */ + +#define __KAL_ATTRIB_PACKED__ __attribute__((__packed__)) +#define __KAL_ATTRIB_ALIGN_4__ __aligned(4) + +#ifndef BIT +#define BIT(n) ((UINT_32) 1U << (n)) +#endif /* BIT */ + +#ifndef BITS +/* bits range: for example BITS(16,23) = 0xFF0000 + * ==> (BIT(m)-1) = 0x0000FFFF ~(BIT(m)-1) => 0xFFFF0000 + * ==> (BIT(n+1)-1) = 0x00FFFFFF + */ +#define BITS(m, n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n))) +#endif /* BIT */ + +/* This macro returns the byte offset of a named field in a known structure + type. + _type - structure name, + _field - field name of the structure */ +#ifndef OFFSET_OF +#define OFFSET_OF(_type, _field) ((ULONG)&(((_type *)0)->_field)) +#endif /* OFFSET_OF */ + +/* This macro returns the base address of an instance of a structure + * given the type of the structure and the address of a field within the + * containing structure. + * _addrOfField - address of current field of the structure, + * _type - structure name, + * _field - field name of the structure + */ +#ifndef ENTRY_OF +#define ENTRY_OF(_addrOfField, _type, _field) \ + ((_type *)((PINT_8)(_addrOfField) - (PINT_8)OFFSET_OF(_type, _field))) +#endif /* ENTRY_OF */ + +/* This macro align the input value to the DW boundary. + * _value - value need to check + */ +#ifndef ALIGN_4 +#define ALIGN_4(_value) (((_value) + 3) & ~3u) +#endif /* ALIGN_4 */ + +/* This macro check the DW alignment of the input value. + * _value - value of address need to check + */ +#ifndef IS_ALIGN_4 +#define IS_ALIGN_4(_value) (((_value) & 0x3) ? FALSE : TRUE) +#endif /* IS_ALIGN_4 */ + +#ifndef IS_NOT_ALIGN_4 +#define IS_NOT_ALIGN_4(_value) (((_value) & 0x3) ? TRUE : FALSE) +#endif /* IS_NOT_ALIGN_4 */ + +/* This macro evaluate the input length in unit of Double Word(4 Bytes). + * _value - value in unit of Byte, output will round up to DW boundary. + */ +#ifndef BYTE_TO_DWORD +#define BYTE_TO_DWORD(_value) ((_value + 3) >> 2) +#endif /* BYTE_TO_DWORD */ + +/* This macro evaluate the input length in unit of Byte. + * _value - value in unit of DW, output is in unit of Byte. + */ +#ifndef DWORD_TO_BYTE +#define DWORD_TO_BYTE(_value) ((_value) << 2) +#endif /* DWORD_TO_BYTE */ + +#if 1 /* Little-Endian */ +#define CONST_NTOHS(_x) ntohs(_x) + +#define CONST_HTONS(_x) htons(_x) + +#define NTOHS(_x) ntohs(_x) + +#define HTONS(_x) htons(_x) + +#define NTOHL(_x) ntohl(_x) + +#define HTONL(_x) htonl(_x) + +#else /* Big-Endian */ + +#define CONST_NTOHS(_x) + +#define CONST_HTONS(_x) + +#define NTOHS(_x) + +#define HTONS(_x) + +#endif + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_TYPEDEF_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h new file mode 100644 index 0000000000000..d8d5b0fb67402 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_vendor.h @@ -0,0 +1,619 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_vendor.h#1 +*/ + +/*! \file gl_vendor.h + \brief This file is for Portable Driver linux gl_vendor support. +*/ + +/* +** Log: gl_vendor.h +** +** 10 14 2014 +** add vendor declaration +** + * +*/ + +#ifndef _GL_VENDOR_H +#define _GL_VENDOR_H + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include +#include +#include + +#include "gl_os.h" + +#include "wlan_lib.h" +#include "gl_wext.h" + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define GOOGLE_OUI 0x001A11 + +typedef enum { + /* Don't use 0 as a valid subcommand */ + ANDROID_NL80211_SUBCMD_UNSPECIFIED, + + /* Define all vendor startup commands between 0x0 and 0x0FFF */ + ANDROID_NL80211_SUBCMD_WIFI_RANGE_START = 0x0001, + ANDROID_NL80211_SUBCMD_WIFI_RANGE_END = 0x0FFF, + + /* Define all GScan related commands between 0x1000 and 0x10FF */ + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START = 0x1000, + ANDROID_NL80211_SUBCMD_GSCAN_RANGE_END = 0x10FF, + + /* Define all RTT related commands between 0x1100 and 0x11FF */ + ANDROID_NL80211_SUBCMD_RTT_RANGE_START = 0x1100, + ANDROID_NL80211_SUBCMD_RTT_RANGE_END = 0x11FF, + + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START = 0x1200, + ANDROID_NL80211_SUBCMD_LSTATS_RANGE_END = 0x12FF, + + /* Define all Logger related commands between 0x1400 and 0x14FF */ + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_START = 0x1400, + ANDROID_NL80211_SUBCMD_DEBUG_RANGE_END = 0x14FF, + + /* Define all wifi offload related commands between 0x1600 and 0x16FF */ + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_START = 0x1600, + ANDROID_NL80211_SUBCMD_WIFI_OFFLOAD_RANGE_END = 0x16FF, + + /* This is reserved for future usage */ + +} ANDROID_VENDOR_SUB_COMMAND; + +typedef enum { + WIFI_SUBCMD_GET_CHANNEL_LIST = ANDROID_NL80211_SUBCMD_WIFI_RANGE_START, + + WIFI_SUBCMD_GET_FEATURE_SET, /* 0x0001 */ + WIFI_SUBCMD_GET_FEATURE_SET_MATRIX, /* 0x0002 */ + WIFI_SUBCMD_SET_PNO_RANDOM_MAC_OUI, /* 0x0003 */ + WIFI_SUBCMD_NODFS_SET, /* 0x0004 */ + WIFI_SUBCMD_SET_COUNTRY_CODE, /* 0x0005 */ + /* Add more sub commands here */ + +} WIFI_SUB_COMMAND; + +typedef enum { + GSCAN_SUBCMD_GET_CAPABILITIES = ANDROID_NL80211_SUBCMD_GSCAN_RANGE_START, + + GSCAN_SUBCMD_SET_CONFIG, /* 0x1001 */ + GSCAN_SUBCMD_SET_SCAN_CONFIG, /* 0x1002 */ + GSCAN_SUBCMD_ENABLE_GSCAN, /* 0x1003 */ + GSCAN_SUBCMD_GET_SCAN_RESULTS, /* 0x1004 */ + GSCAN_SUBCMD_SCAN_RESULTS, /* 0x1005 */ + + GSCAN_SUBCMD_SET_HOTLIST, /* 0x1006 */ + + GSCAN_SUBCMD_SET_SIGNIFICANT_CHANGE_CONFIG, /* 0x1007 */ + GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS, /* 0x1008 */ + /* Add more sub commands here */ + +} GSCAN_SUB_COMMAND; + +typedef enum { + RTT_SUBCMD_SET_CONFIG = ANDROID_NL80211_SUBCMD_RTT_RANGE_START, + RTT_SUBCMD_CANCEL_CONFIG, + RTT_SUBCMD_GETCAPABILITY, +} RTT_SUB_COMMAND; + +typedef enum { + LSTATS_SUBCMD_GET_INFO = ANDROID_NL80211_SUBCMD_LSTATS_RANGE_START, +} LSTATS_SUB_COMMAND; + +typedef enum { + GSCAN_EVENT_SIGNIFICANT_CHANGE_RESULTS, + GSCAN_EVENT_HOTLIST_RESULTS_FOUND, + GSCAN_EVENT_SCAN_RESULTS_AVAILABLE, + GSCAN_EVENT_FULL_SCAN_RESULTS, + RTT_EVENT_COMPLETE, + GSCAN_EVENT_COMPLETE_SCAN, + GSCAN_EVENT_HOTLIST_RESULTS_LOST +} WIFI_VENDOR_EVENT; + +typedef enum { + WIFI_ATTRIBUTE_BAND, + WIFI_ATTRIBUTE_NUM_CHANNELS, + WIFI_ATTRIBUTE_CHANNEL_LIST, + + WIFI_ATTRIBUTE_NUM_FEATURE_SET, + WIFI_ATTRIBUTE_FEATURE_SET, + WIFI_ATTRIBUTE_PNO_RANDOM_MAC_OUI, + WIFI_ATTRIBUTE_NODFS_VALUE, + WIFI_ATTRIBUTE_COUNTRY_CODE + +} WIFI_ATTRIBUTE; + +typedef enum { + GSCAN_ATTRIBUTE_CAPABILITIES = 1, + + GSCAN_ATTRIBUTE_NUM_BUCKETS = 10, + GSCAN_ATTRIBUTE_BASE_PERIOD, + GSCAN_ATTRIBUTE_BUCKETS_BAND, + GSCAN_ATTRIBUTE_BUCKET_ID, + GSCAN_ATTRIBUTE_BUCKET_PERIOD, + GSCAN_ATTRIBUTE_BUCKET_NUM_CHANNELS, + GSCAN_ATTRIBUTE_BUCKET_CHANNELS, + GSCAN_ATTRIBUTE_NUM_AP_PER_SCAN, + GSCAN_ATTRIBUTE_REPORT_THRESHOLD, + GSCAN_ATTRIBUTE_NUM_SCANS_TO_CACHE, + + GSCAN_ATTRIBUTE_ENABLE_FEATURE = 20, + GSCAN_ATTRIBUTE_SCAN_RESULTS_COMPLETE, /* indicates no more results */ + GSCAN_ATTRIBUTE_FLUSH_FEATURE, /* Flush all the configs */ + GSCAN_ENABLE_FULL_SCAN_RESULTS, + GSCAN_ATTRIBUTE_REPORT_EVENTS, + + GSCAN_ATTRIBUTE_NUM_OF_RESULTS = 30, + GSCAN_ATTRIBUTE_FLUSH_RESULTS, + GSCAN_ATTRIBUTE_SCAN_RESULTS, /* flat array of wifi_scan_result */ + GSCAN_ATTRIBUTE_SCAN_ID, /* indicates scan number */ + GSCAN_ATTRIBUTE_SCAN_FLAGS, /* indicates if scan was aborted */ + GSCAN_ATTRIBUTE_AP_FLAGS, /* flags on significant change event */ + + GSCAN_ATTRIBUTE_SSID = 40, + GSCAN_ATTRIBUTE_BSSID, + GSCAN_ATTRIBUTE_CHANNEL, + GSCAN_ATTRIBUTE_RSSI, + GSCAN_ATTRIBUTE_TIMESTAMP, + GSCAN_ATTRIBUTE_RTT, + GSCAN_ATTRIBUTE_RTTSD, + + GSCAN_ATTRIBUTE_HOTLIST_BSSIDS = 50, + GSCAN_ATTRIBUTE_RSSI_LOW, + GSCAN_ATTRIBUTE_RSSI_HIGH, + GSCAN_ATTRIBUTE_HOTLIST_ELEM, + GSCAN_ATTRIBUTE_HOTLIST_FLUSH, + + GSCAN_ATTRIBUTE_RSSI_SAMPLE_SIZE = 60, + GSCAN_ATTRIBUTE_LOST_AP_SAMPLE_SIZE, + GSCAN_ATTRIBUTE_MIN_BREACHING, + GSCAN_ATTRIBUTE_NUM_AP, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_BSSIDS, + GSCAN_ATTRIBUTE_SIGNIFICANT_CHANGE_FLUSH + +} GSCAN_ATTRIBUTE; + +typedef enum { + RTT_ATTRIBUTE_CAPABILITIES = 1, + + RTT_ATTRIBUTE_TARGET_CNT = 10, + RTT_ATTRIBUTE_TARGET_INFO, + RTT_ATTRIBUTE_TARGET_MAC, + RTT_ATTRIBUTE_TARGET_TYPE, + RTT_ATTRIBUTE_TARGET_PEER, + RTT_ATTRIBUTE_TARGET_CHAN, + RTT_ATTRIBUTE_TARGET_PERIOD, + RTT_ATTRIBUTE_TARGET_NUM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_FTM_BURST, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTM, + RTT_ATTRIBUTE_TARGET_NUM_RETRY_FTMR, + RTT_ATTRIBUTE_TARGET_LCI, + RTT_ATTRIBUTE_TARGET_LCR, + RTT_ATTRIBUTE_TARGET_BURST_DURATION, + RTT_ATTRIBUTE_TARGET_PREAMBLE, + RTT_ATTRIBUTE_TARGET_BW, + RTT_ATTRIBUTE_RESULTS_COMPLETE = 30, + RTT_ATTRIBUTE_RESULTS_PER_TARGET, + RTT_ATTRIBUTE_RESULT_CNT, + RTT_ATTRIBUTE_RESULT +} RTT_ATTRIBUTE; + +typedef enum { + LSTATS_ATTRIBUTE_STATS = 2, +} LSTATS_ATTRIBUTE; + +typedef enum { + WIFI_BAND_UNSPECIFIED, + WIFI_BAND_BG = 1, /* 2.4 GHz */ + WIFI_BAND_A = 2, /* 5 GHz without DFS */ + WIFI_BAND_A_DFS = 4, /* 5 GHz DFS only */ + WIFI_BAND_A_WITH_DFS = 6, /* 5 GHz with DFS */ + WIFI_BAND_ABG = 3, /* 2.4 GHz + 5 GHz; no DFS */ + WIFI_BAND_ABG_WITH_DFS = 7, /* 2.4 GHz + 5 GHz with DFS */ +} WIFI_BAND; + +typedef enum { + WIFI_SCAN_BUFFER_FULL, + WIFI_SCAN_COMPLETE, +} WIFI_SCAN_EVENT; + +#define GSCAN_MAX_REPORT_THRESHOLD 1024000 +#define GSCAN_MAX_CHANNELS 8 +#define GSCAN_MAX_BUCKETS 8 +#define MAX_HOTLIST_APS 16 +#define MAX_SIGNIFICANT_CHANGE_APS 16 +#define PSCAN_MAX_SCAN_CACHE_SIZE 16 +#define PSCAN_MAX_AP_CACHE_PER_SCAN 16 +#define PSCAN_VERSION 1 + +#define MAX_BUFFERED_GSCN_RESULTS 5 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef UINT_64 wifi_timestamp; /* In microseconds (us) */ +typedef UINT_64 wifi_timespan; /* In nanoseconds (ns) */ + +typedef UINT_8 mac_addr[6]; +typedef UINT_32 wifi_channel; /* Indicates channel frequency in MHz */ +typedef INT_32 wifi_rssi; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +typedef struct _PARAM_WIFI_GSCAN_GET_RESULT_PARAMS { + UINT_32 get_num; + UINT_8 flush; +} PARAM_WIFI_GSCAN_GET_RESULT_PARAMS, *P_PARAM_WIFI_GSCAN_GET_RESULT_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS { + UINT_8 ucPscanAct; + UINT_8 aucReserved[3]; +} PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_ACTION_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T { + UINT_32 max_scan_cache_size; /* total space allocated for scan (in bytes) */ + UINT_32 max_scan_buckets; /* maximum number of channel buckets */ + UINT_32 max_ap_cache_per_scan; /* maximum number of APs that can be stored per scan */ + UINT_32 max_rssi_sample_size; /* number of RSSI samples used for averaging RSSI */ + UINT_32 max_scan_reporting_threshold; /* max possible report_threshold as described */ + /* in wifi_scan_cmd_params */ + UINT_32 max_hotlist_aps; /* maximum number of entries for hotlist APs */ + UINT_32 max_significant_wifi_change_aps; /* maximum number of entries for */ + /* significant wifi change APs */ + UINT_32 max_bssid_history_entries; /* number of BSSID/RSSI entries that device can hold */ +} PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T, *P_PARAM_WIFI_GSCAN_CAPABILITIES_STRUCT_T; + +typedef struct _PARAM_WIFI_GSCAN_CHANNEL_SPEC { + UINT_32 channel; /* frequency */ + UINT_32 dwellTimeMs; /* dwell time hint */ + UINT_32 passive; /* 0 => active, 1 => passive scan; ignored for DFS */ + /* Add channel class */ +} PARAM_WIFI_GSCAN_CHANNEL_SPEC, *P_PARAM_WIFI_GSCAN_CHANNEL_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_BUCKET_SPEC { + UINT_32 bucket; /* bucket index, 0 based */ + WIFI_BAND band; /* when UNSPECIFIED, use channel list */ + UINT_32 period; /* desired period, in millisecond; if this is too */ + /* low, the firmware should choose to generate results as */ + /* fast as it can instead of failing the command */ + /* report_events semantics - + * 0 => report only when scan history is % full + * 1 => same as 0 + report a scan completion event after scanning this bucket + * 2 => same as 1 + forward scan results (beacons/probe responses + IEs) in real time to HAL + * 3 => same as 2 + forward scan results (beacons/probe responses + IEs) in real time to + supplicant as well (optional) . */ + UINT_8 report_events; + + UINT_32 num_channels; + PARAM_WIFI_GSCAN_CHANNEL_SPEC channels[GSCAN_MAX_CHANNELS]; /* channels to scan; + these may include DFS channels */ +} PARAM_WIFI_GSCAN_BUCKET_SPEC, *P_PARAM_WIFI_GSCAN_BUCKET_SPEC; + +typedef struct _PARAM_WIFI_GSCAN_CMD_PARAMS { + UINT_32 base_period; /* base timer period in ms */ + UINT_32 max_ap_per_scan; /* number of APs to store in each scan in the */ + /* BSSID/RSSI history buffer (keep the highest RSSI APs) */ + UINT_32 report_threshold; /* in %, when scan buffer is this much full, wake up AP */ + UINT_32 num_scans; + UINT_32 num_buckets; + PARAM_WIFI_GSCAN_BUCKET_SPEC buckets[GSCAN_MAX_BUCKETS]; +} PARAM_WIFI_GSCAN_CMD_PARAMS, *P_PARAM_WIFI_GSCAN_CMD_PARAMS; + +typedef struct _PARAM_WIFI_GSCAN_RESULT { + wifi_timestamp ts; /* time since boot (in microsecond) when the result was */ + /* retrieved */ + UINT_8 ssid[32 + 1]; /* null terminated */ + mac_addr bssid; + wifi_channel channel; /* channel frequency in MHz */ + wifi_rssi rssi; /* in db */ + wifi_timespan rtt; /* in nanoseconds */ + wifi_timespan rtt_sd; /* standard deviation in rtt */ + UINT_16 beacon_period; /* period advertised in the beacon */ + UINT_16 capability; /* capabilities advertised in the beacon */ + UINT_32 ie_length; /* size of the ie_data blob */ + UINT_8 ie_data[1]; /* blob of all the information elements found in the */ + /* beacon; this data should be a packed list of */ + /* wifi_information_element objects, one after the other. */ + /* other fields */ +} PARAM_WIFI_GSCAN_RESULT, *P_PARAM_WIFI_GSCAN_RESULT; + +/* Significant wifi change*/ +/*typedef struct _PARAM_WIFI_CHANGE_RESULT{ + mac_addr bssid; // BSSID + wifi_channel channel; // channel frequency in MHz + UINT_32 num_rssi; // number of rssi samples + wifi_rssi rssi[8]; // RSSI history in db +} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT;*/ + +typedef struct _PARAM_WIFI_CHANGE_RESULT { + UINT_16 flags; + UINT_16 channel; + mac_addr bssid; /* BSSID */ + INT_8 rssi[8]; /* RSSI history in db */ +} PARAM_WIFI_CHANGE_RESULT, *P_PARAM_WIFI_CHANGE_RESULT; + +typedef struct _PARAM_AP_THRESHOLD { + mac_addr bssid; /* AP BSSID */ + wifi_rssi low; /* low threshold */ + wifi_rssi high; /* high threshold */ + wifi_channel channel; /* channel hint */ +} PARAM_AP_THRESHOLD, *P_PARAM_AP_THRESHOLD; + +typedef struct _PARAM_WIFI_BSSID_HOTLIST { + UINT_32 lost_ap_sample_size; + UINT_32 num_ap; /* number of hotlist APs */ + PARAM_AP_THRESHOLD ap[MAX_HOTLIST_APS]; /* hotlist APs */ +} PARAM_WIFI_BSSID_HOTLIST, *P_PARAM_WIFI_BSSID_HOTLIST; + +typedef struct _PARAM_WIFI_SIGNIFICANT_CHANGE { + UINT_16 rssi_sample_size; /* number of samples for averaging RSSI */ + UINT_16 lost_ap_sample_size; /* number of samples to confirm AP loss */ + UINT_16 min_breaching; /* number of APs breaching threshold */ + UINT_16 num_ap; /* max 64 */ + PARAM_AP_THRESHOLD ap[MAX_SIGNIFICANT_CHANGE_APS]; +} PARAM_WIFI_SIGNIFICANT_CHANGE, *P_PARAM_WIFI_SIGNIFICANT_CHANGE; + +/* RTT Capabilities */ +typedef struct _PARAM_WIFI_RTT_CAPABILITIES { + UINT_8 rtt_one_sided_supported; /* if 1-sided rtt data collection is supported */ + UINT_8 rtt_ftm_supported; /* if ftm rtt data collection is supported */ + UINT_8 lci_support; /* if initiator supports LCI request. Applies to 2-sided RTT */ + UINT_8 lcr_support; /* if initiator supports LCR request. Applies to 2-sided RTT */ + UINT_8 preamble_support; /* bit mask indicates what preamble is supported by initiator */ + UINT_8 bw_support; /* bit mask indicates what BW is supported by initiator */ +} PARAM_WIFI_RTT_CAPABILITIES, *P_PARAM_WIFI_RTT_CAPABILITIES; + +/* channel operating width */ +typedef enum { + WIFI_CHAN_WIDTH_20 = 0, + WIFI_CHAN_WIDTH_40 = 1, + WIFI_CHAN_WIDTH_80 = 2, + WIFI_CHAN_WIDTH_160 = 3, + WIFI_CHAN_WIDTH_80P80 = 4, + WIFI_CHAN_WIDTH_5 = 5, + WIFI_CHAN_WIDTH_10 = 6, + WIFI_CHAN_WIDTH_INVALID = -1 +} WIFI_CHANNEL_WIDTH; + +/* channel information */ +typedef struct { + WIFI_CHANNEL_WIDTH width; /* channel width (20, 40, 80, 80+80, 160) */ + UINT_32 center_freq; /* primary 20 MHz channel */ + UINT_32 center_freq0; /* center frequency (MHz) first segment */ + UINT_32 center_freq1; /* center frequency (MHz) second segment */ +} WIFI_CHANNEL_INFO; + +/* channel statistics */ +typedef struct { + WIFI_CHANNEL_INFO channel; /* channel */ + UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ + UINT_32 cca_busy_time; /* msecs the CCA register is busy (32 bits number accruing over time) */ +} WIFI_CHANNEL_STAT; + +/* radio statistics */ +typedef struct { + UINT_32 radio; /* wifi radio (if multiple radio supported) */ + UINT_32 on_time; /* msecs the radio is awake (32 bits number accruing over time) */ + UINT_32 tx_time; /* msecs the radio is transmitting (32 bits number accruing over time) */ + UINT_32 rx_time; /* msecs the radio is in active receive (32 bits number accruing over time) */ + UINT_32 on_time_scan; /* msecs the radio is awake due to all scan (32 bits number accruing over time) */ + UINT_32 on_time_nbd; /* msecs the radio is awake due to NAN (32 bits number accruing over time) */ + UINT_32 on_time_gscan; /* msecs the radio is awake due to G?scan (32 bits number accruing over time) */ + UINT_32 on_time_roam_scan; /* msecs the radio is awake due to roam?scan + (32 bits number accruing over time) */ + UINT_32 on_time_pno_scan; /* msecs the radio is awake due to PNO scan + (32 bits number accruing over time) */ + UINT_32 on_time_hs20; /* msecs the radio is awake due to HS2.0 scans and GAS exchange + 32 bits number accruing over time) */ + UINT_32 num_channels; /* number of channels */ + WIFI_CHANNEL_STAT channels[]; /* channel statistics */ +} WIFI_RADIO_STAT; + +/* wifi rate */ +typedef struct { + UINT_32 preamble:3; /* 0: OFDM, 1:CCK, 2:HT 3:VHT 4..7 reserved */ + UINT_32 nss:2; /* 0:1x1, 1:2x2, 3:3x3, 4:4x4 */ + UINT_32 bw:3; /* 0:20MHz, 1:40Mhz, 2:80Mhz, 3:160Mhz */ + UINT_32 rateMcsIdx:8; /* OFDM/CCK rate code would be as per ieee std in the units of 0.5mbps */ + /* HT/VHT it would be mcs index */ + UINT_32 reserved:16; /* reserved */ + UINT_32 bitrate; /* units of 100 Kbps */ +} WIFI_RATE; + +/* per rate statistics */ +typedef struct { + WIFI_RATE rate; /* rate information */ + UINT_32 tx_mpdu; /* number of successfully transmitted data pkts (ACK rcvd) */ + UINT_32 rx_mpdu; /* number of received data pkts */ + UINT_32 mpdu_lost; /* number of data packet losses (no ACK) */ + UINT_32 retries; /* total number of data pkt retries */ + UINT_32 retries_short; /* number of short data pkt retries */ + UINT_32 retries_long; /* number of long data pkt retries */ +} WIFI_RATE_STAT; + +/*wifi_interface_link_layer_info*/ +typedef enum { + WIFI_DISCONNECTED = 0, + WIFI_AUTHENTICATING = 1, + WIFI_ASSOCIATING = 2, + WIFI_ASSOCIATED = 3, + WIFI_EAPOL_STARTED = 4, /* if done by firmware/driver */ + WIFI_EAPOL_COMPLETED = 5, /* if done by firmware/driver */ +} WIFI_CONNECTION_STATE; + +typedef enum { + WIFI_ROAMING_IDLE = 0, + WIFI_ROAMING_ACTIVE = 1, +} WIFI_ROAM_STATE; + +typedef enum { + WIFI_INTERFACE_STA = 0, + WIFI_INTERFACE_SOFTAP = 1, + WIFI_INTERFACE_IBSS = 2, + WIFI_INTERFACE_P2P_CLIENT = 3, + WIFI_INTERFACE_P2P_GO = 4, + WIFI_INTERFACE_NAN = 5, + WIFI_INTERFACE_MESH = 6, + WIFI_INTERFACE_UNKNOWN = -1 +} WIFI_INTERFACE_MODE; + +typedef struct { + WIFI_INTERFACE_MODE mode; /* interface mode */ + u8 mac_addr[6]; /* interface mac address (self) */ + WIFI_CONNECTION_STATE state; /* connection state (valid for STA, CLI only) */ + WIFI_ROAM_STATE roaming; /* roaming state */ + u32 capabilities; /* WIFI_CAPABILITY_XXX (self) */ + u8 ssid[33]; /* null terminated SSID */ + u8 bssid[6]; /* bssid */ + u8 ap_country_str[3]; /* country string advertised by AP */ + u8 country_str[3]; /* country string for this association */ +} WIFI_INTERFACE_LINK_LAYER_INFO; + +/* access categories */ +typedef enum { + WIFI_AC_VO = 0, + WIFI_AC_VI = 1, + WIFI_AC_BE = 2, + WIFI_AC_BK = 3, + WIFI_AC_MAX = 4, +} WIFI_TRAFFIC_AC; + +/* wifi peer type */ +typedef enum { + WIFI_PEER_STA, + WIFI_PEER_AP, + WIFI_PEER_P2P_GO, + WIFI_PEER_P2P_CLIENT, + WIFI_PEER_NAN, + WIFI_PEER_TDLS, + WIFI_PEER_INVALID, +} WIFI_PEER_TYPE; + +/* per peer statistics */ +typedef struct { + WIFI_PEER_TYPE type; /* peer type (AP, TDLS, GO etc.) */ + UINT_8 peer_mac_address[6]; /* mac address */ + UINT_32 capabilities; /* peer WIFI_CAPABILITY_XXX */ + UINT_32 num_rate; /* number of rates */ + WIFI_RATE_STAT rate_stats[]; /* per rate statistics, number of entries = num_rate */ +} WIFI_PEER_INFO; + +/* per access category statistics */ +typedef struct { + WIFI_TRAFFIC_AC ac; /* access category (VI, VO, BE, BK) */ + UINT_32 tx_mpdu; /* number of successfully transmitted unicast data pkts (ACK rcvd) */ + UINT_32 rx_mpdu; /* number of received unicast mpdus */ + UINT_32 tx_mcast; /* number of successfully transmitted multicast data packets */ + /* STA case: implies ACK received from AP for the unicast packet in which mcast pkt was sent */ + UINT_32 rx_mcast; /* number of received multicast data packets */ + UINT_32 rx_ampdu; /* number of received unicast a-mpdus */ + UINT_32 tx_ampdu; /* number of transmitted unicast a-mpdus */ + UINT_32 mpdu_lost; /* number of data pkt losses (no ACK) */ + UINT_32 retries; /* total number of data pkt retries */ + UINT_32 retries_short; /* number of short data pkt retries */ + UINT_32 retries_long; /* number of long data pkt retries */ + UINT_32 contention_time_min; /* data pkt min contention time (usecs) */ + UINT_32 contention_time_max; /* data pkt max contention time (usecs) */ + UINT_32 contention_time_avg; /* data pkt avg contention time (usecs) */ + UINT_32 contention_num_samples; /* num of data pkts used for contention statistics */ +} WIFI_WMM_AC_STAT; + +/* interface statistics */ +typedef struct { + /* wifi_interface_handle iface; // wifi interface */ + WIFI_INTERFACE_LINK_LAYER_INFO info; /* current state of the interface */ + UINT_32 beacon_rx; /* access point beacon received count from connected AP */ + UINT_32 mgmt_rx; /* access point mgmt frames received count from connected AP (including Beacon) */ + UINT_32 mgmt_action_rx; /* action frames received count */ + UINT_32 mgmt_action_tx; /* action frames transmit count */ + wifi_rssi rssi_mgmt; /* access Point Beacon and Management frames RSSI (averaged) */ + wifi_rssi rssi_data; /* access Point Data Frames RSSI (averaged) from connected AP */ + wifi_rssi rssi_ack; /* access Point ACK RSSI (averaged) from connected AP */ + WIFI_WMM_AC_STAT ac[WIFI_AC_MAX]; /* per ac data packet statistics */ + UINT_32 num_peers; /* number of peers */ + WIFI_PEER_INFO peer_info[]; /* per peer statistics */ +} WIFI_IFACE_STAT; + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +int mtk_cfg80211_vendor_get_channel_list(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_country_code(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_gscan_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_set_scan_config(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_set_significant_change(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_set_hotlist(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_scan(struct wiphy *wiphy, struct wireless_dev *wdev, const void *data, int data_len); + +int mtk_cfg80211_vendor_enable_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_get_rtt_capabilities(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_llstats_get_info(struct wiphy *wiphy, struct wireless_dev *wdev, + const void *data, int data_len); + +int mtk_cfg80211_vendor_event_complete_scan(struct wiphy *wiphy, struct wireless_dev *wdev, WIFI_SCAN_EVENT complete); + +int mtk_cfg80211_vendor_event_scan_results_available(struct wiphy *wiphy, struct wireless_dev *wdev, UINT_32 num); + +int mtk_cfg80211_vendor_event_full_scan_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_significant_change_results(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_CHANGE_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_found(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +int mtk_cfg80211_vendor_event_hotlist_ap_lost(struct wiphy *wiphy, struct wireless_dev *wdev, + P_PARAM_WIFI_GSCAN_RESULT pdata, UINT_32 data_len); + +#endif /* _GL_VENDOR_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h new file mode 100644 index 0000000000000..827ff92b1581f --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext.h @@ -0,0 +1,357 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext.h#1 +*/ + +/*! \file gl_wext.h + \brief This file is for Portable Driver linux wireless extension support. +*/ + +/* +** Log: gl_wext.h + * + * 10 12 2011 wh.su + * [WCXRP00001036] [MT6620 Wi-Fi][Driver][FW] Adding the 802.11w code for MFP + * adding the 802.11w related function and define . + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 09 20 2011 chinglan.wang + * [WCXRP00000989] [WiFi Direct] [Driver] Add a new io control API to start the formation for the sigma test. + * . + * + * 01 11 2011 chinglan.wang + * NULL + * Modify to reslove the CR :[ALPS00028994] Use WEP security to connect Marvell 11N AP. + * Connection establish successfully. + * Use the WPS function to connect AP, the privacy bit always is set to 1. . + * + * 09 27 2010 wh.su + * NULL + * [WCXRP00000067][MT6620 Wi-Fi][Driver] Support the android+ WAPI function. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\12 2009-10-20 17:38:33 GMT mtk01090 +** Refine driver unloading and clean up procedure. Block requests, stop main thread and clean up queued requests, +** and then stop hw. +** \main\maintrunk.MT5921\11 2009-09-28 20:19:28 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\10 2009-09-03 12:12:35 GMT mtk01088 +** adding the function declaration +** \main\maintrunk.MT5921\9 2009-08-18 22:57:17 GMT mtk01090 +** Add Linux SDIO (with mmc core) support. +** Add Linux 2.6.21, 2.6.25, 2.6.26. +** Fix compile warning in Linux. +** \main\maintrunk.MT5921\8 2008-08-29 16:59:07 GMT mtk01088 +** fixed compiling error +** \main\maintrunk.MT5921\7 2008-08-29 14:13:28 GMT mtk01088 +** adjust the header file for code refine +** \main\maintrunk.MT5921\6 2008-03-28 10:40:31 GMT mtk01461 +** Add set desired rate in Linux STD IOCTL +** \main\maintrunk.MT5921\5 2008-03-11 14:51:08 GMT mtk01461 +** Refine private IOCTL functions +** \main\maintrunk.MT5921\4 2008-02-12 23:45:45 GMT mtk01461 +** Add Set Frequency & Channel oid support for Linux +** \main\maintrunk.MT5921\3 2007-11-06 19:36:19 GMT mtk01088 +** add the WPS related code +*/ + +#ifndef _GL_WEXT_H +#define _GL_WEXT_H + +#ifdef WIRELESS_EXT +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define KILO 1000 +#define RATE_5_5M 11 /* 5.5M */ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef struct _PARAM_FIXED_IEs { + UINT_8 aucTimestamp[8]; + UINT_16 u2BeaconInterval; + UINT_16 u2Capabilities; +} PARAM_FIXED_IEs; + +typedef struct _PARAM_VARIABLE_IE_T { + UINT_8 ucElementID; + UINT_8 ucLength; + UINT_8 aucData[1]; +} PARAM_VARIABLE_IE_T, *P_PARAM_VARIABLE_IE_T; + +#if WIRELESS_EXT < 18 + +#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses struct iw_mlme */ +/* MLME requests (SIOCSIWMLME / struct iw_mlme) */ +#define IW_MLME_DEAUTH 0 +#define IW_MLME_DISASSOC 1 + +/*! \brief SIOCSIWMLME data */ +struct iw_mlme { + __u16 cmd; /*!< IW_MLME_* */ + __u16 reason_code; + struct sockaddr addr; +}; + +#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ +#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ +/* SIOCSIWAUTH/SIOCGIWAUTH struct iw_param flags */ +#define IW_AUTH_INDEX 0x0FFF +#define IW_AUTH_FLAGS 0xF000 +/* SIOCSIWAUTH/SIOCGIWAUTH parameters (0 .. 4095) + * (IW_AUTH_INDEX mask in struct iw_param flags; this is the index of the + * parameter that is being set/get to; value will be read/written to + * struct iw_param value field) */ +#define IW_AUTH_WPA_VERSION 0 +#define IW_AUTH_CIPHER_PAIRWISE 1 +#define IW_AUTH_CIPHER_GROUP 2 +#define IW_AUTH_KEY_MGMT 3 +#define IW_AUTH_TKIP_COUNTERMEASURES 4 +#define IW_AUTH_DROP_UNENCRYPTED 5 +#define IW_AUTH_80211_AUTH_ALG 6 +#define IW_AUTH_WPA_ENABLED 7 +#define IW_AUTH_RX_UNENCRYPTED_EAPOL 8 +#define IW_AUTH_ROAMING_CONTROL 9 +#define IW_AUTH_PRIVACY_INVOKED 10 +#if CFG_SUPPORT_802_11W +#define IW_AUTH_MFP 12 + +#define IW_AUTH_MFP_DISABLED 0 /* MFP disabled */ +#define IW_AUTH_MFP_OPTIONAL 1 /* MFP optional */ +#define IW_AUTH_MFP_REQUIRED 2 /* MFP required */ +#endif + +/* IW_AUTH_WPA_VERSION values (bit field) */ +#define IW_AUTH_WPA_VERSION_DISABLED 0x00000001 +#define IW_AUTH_WPA_VERSION_WPA 0x00000002 +#define IW_AUTH_WPA_VERSION_WPA2 0x00000004 + +/* IW_AUTH_PAIRWISE_CIPHER and IW_AUTH_GROUP_CIPHER values (bit field) */ +#define IW_AUTH_CIPHER_NONE 0x00000001 +#define IW_AUTH_CIPHER_WEP40 0x00000002 +#define IW_AUTH_CIPHER_TKIP 0x00000004 +#define IW_AUTH_CIPHER_CCMP 0x00000008 +#define IW_AUTH_CIPHER_WEP104 0x00000010 + +/* IW_AUTH_KEY_MGMT values (bit field) */ +#define IW_AUTH_KEY_MGMT_802_1X 1 +#define IW_AUTH_KEY_MGMT_PSK 2 +#define IW_AUTH_KEY_MGMT_WPA_NONE 4 + +/* IW_AUTH_80211_AUTH_ALG values (bit field) */ +#define IW_AUTH_ALG_OPEN_SYSTEM 0x00000001 +#define IW_AUTH_ALG_SHARED_KEY 0x00000002 +#define IW_AUTH_ALG_LEAP 0x00000004 + +/* IW_AUTH_ROAMING_CONTROL values */ +#define IW_AUTH_ROAMING_ENABLE 0 /* driver/firmware based roaming */ +#define IW_AUTH_ROAMING_DISABLE 1 /* user space program used for roaming + * control */ + +#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ +#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ +/* SIOCSIWENCODEEXT definitions */ +#define IW_ENCODE_SEQ_MAX_SIZE 8 +/* struct iw_encode_ext ->alg */ +#define IW_ENCODE_ALG_NONE 0 +#define IW_ENCODE_ALG_WEP 1 +#define IW_ENCODE_ALG_TKIP 2 +#define IW_ENCODE_ALG_CCMP 3 +#if CFG_SUPPORT_802_11W +#define IW_ENCODE_ALG_AES_CMAC 5 +#endif + +/* struct iw_encode_ext ->ext_flags */ +#define IW_ENCODE_EXT_TX_SEQ_VALID 0x00000001 +#define IW_ENCODE_EXT_RX_SEQ_VALID 0x00000002 +#define IW_ENCODE_EXT_GROUP_KEY 0x00000004 +#define IW_ENCODE_EXT_SET_TX_KEY 0x00000008 + +struct iw_encode_ext { + __u32 ext_flags; /*!< IW_ENCODE_EXT_* */ + __u8 tx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + __u8 rx_seq[IW_ENCODE_SEQ_MAX_SIZE]; /*!< LSB first */ + struct sockaddr addr; /*!< ff:ff:ff:ff:ff:ff for broadcast/multicast + * (group) keys or unicast address for + * individual keys */ + __u16 alg; /*!< IW_ENCODE_ALG_* */ + __u16 key_len; + __u8 key[0]; +}; + +#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ +#define IW_PMKSA_ADD 1 +#define IW_PMKSA_REMOVE 2 +#define IW_PMKSA_FLUSH 3 + +#define IW_PMKID_LEN 16 + +struct iw_pmksa { + __u32 cmd; /*!< IW_PMKSA_* */ + struct sockaddr bssid; + __u8 pmkid[IW_PMKID_LEN]; +}; + +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) */ + +#endif /* WIRELESS_EXT < 18 */ + +#if WIRELESS_EXT < 17 +/* Statistics flags (bitmask in updated) */ +#define IW_QUAL_QUAL_UPDATED 0x1 /* Value was updated since last read */ +#define IW_QUAL_LEVEL_UPDATED 0x2 +#define IW_QUAL_NOISE_UPDATED 0x4 +#define IW_QUAL_QUAL_INVALID 0x10 /* Driver doesn't provide value */ +#define IW_QUAL_LEVEL_INVALID 0x20 +#define IW_QUAL_NOISE_INVALID 0x40 +#endif + +enum { + IEEE80211_FILTER_TYPE_BEACON = 1 << 0, + IEEE80211_FILTER_TYPE_PROBE_REQ = 1 << 1, + IEEE80211_FILTER_TYPE_PROBE_RESP = 1 << 2, + IEEE80211_FILTER_TYPE_ASSOC_REQ = 1 << 3, + IEEE80211_FILTER_TYPE_ASSOC_RESP = 1 << 4, + IEEE80211_FILTER_TYPE_AUTH = 1 << 5, + IEEE80211_FILTER_TYPE_DEAUTH = 1 << 6, + IEEE80211_FILTER_TYPE_DISASSOC = 1 << 7, + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */ +}; + +#if CFG_SUPPORT_WAPI +#define IW_AUTH_WAPI_ENABLED 0x20 +#define IW_ENCODE_ALG_SMS4 0x20 +#endif + +#if CFG_SUPPORT_WAPI /* Android+ */ +#define IW_AUTH_KEY_MGMT_WAPI_PSK 3 +#define IW_AUTH_KEY_MGMT_WAPI_CERT 4 +#endif +#define IW_AUTH_KEY_MGMT_WPS 5 + +#if CFG_SUPPORT_802_11W +#define IW_AUTH_KEY_MGMT_802_1X_SHA256 7 +#define IW_AUTH_KEY_MGMT_PSK_SHA256 8 +#endif + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ +extern const struct iw_handler_def wext_handler_def; + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ +/* wireless extensions' ioctls */ +int wext_support_ioctl(IN struct net_device *prDev, IN struct ifreq *prIfReq, IN int i4Cmd); + +int +wext_set_rate(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN struct iw_param *prRate, IN char *pcExtra); + +void +wext_indicate_wext_event(IN P_GLUE_INFO_T prGlueInfo, + IN unsigned int u4Cmd, IN unsigned char *pucData, IN unsigned int u4DataLen); + +struct iw_statistics *wext_get_wireless_stats(struct net_device *prDev); + +BOOLEAN +wextSrchDesiredWPAIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); + +#if CFG_SUPPORT_WPS +BOOLEAN +wextSrchDesiredWPSIE(IN PUINT_8 pucIEStart, + IN INT_32 i4TotalIeLen, IN UINT_8 ucDesiredElemId, OUT PUINT_8 *ppucDesiredIE); +#endif + +#if CFG_SUPPORT_HOTSPOT_2_0 +BOOLEAN wextSrchDesiredHS20IE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredInterworkingIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredAdvProtocolIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); + +BOOLEAN wextSrchDesiredRoamingConsortiumIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); +#endif + +#if CFG_SUPPORT_WAPI +BOOLEAN wextSrchDesiredWAPIIE(IN PUINT_8 pucIEStart, IN INT_32 i4TotalIeLen, OUT PUINT_8 *ppucDesiredIE); +#endif + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* WIRELESS_EXT */ + +#endif /* _GL_WEXT_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h new file mode 100644 index 0000000000000..31933fc6a461e --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/include/gl_wext_priv.h @@ -0,0 +1,402 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/include/gl_wext_priv.h#3 +*/ + +/*! \file gl_wext_priv.h + \brief This file includes private ioctl support. +*/ + +/* +** Log: gl_wext_priv.h + * + * 01 16 2012 wh.su + * [WCXRP00001170] [MT6620 Wi-Fi][Driver] Adding the related code for set/get band ioctl + * Adding the template code for set / get band IOCTL (with ICS supplicant_6).. + * + * 01 05 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the related ioctl / wlan oid function to set the Tx power cfg. + * + * 01 02 2012 wh.su + * [WCXRP00001153] [MT6620 Wi-Fi][Driver] Adding the get_ch_list and set_tx_power proto type function + * Adding the proto type function for set_int set_tx_power and get int get_ch_list. + * + * 11 08 2011 yuche.tsai + * [WCXRP00001094] [Volunteer Patch][Driver] Driver version & supplicant version query & set support for service + * discovery version check. + * Add a CMD ID for P2P driver version query. + * + * 03 17 2011 chinglan.wang + * [WCXRP00000570] [MT6620 Wi-Fi][Driver] Add Wi-Fi Protected Setup v2.0 feature + * . + * + * 03 02 2011 wh.su + * [WCXRP00000506] [MT6620 Wi-Fi][Driver][FW] Add Security check related code + * Add security check code. + * + * 01 27 2011 cm.chang + * [WCXRP00000402] [MT6620 Wi-Fi][Driver] Enable MCR read/write by iwpriv by default + * . + * + * 01 20 2011 eddie.chen + * [WCXRP00000374] [MT6620 Wi-Fi][DRV] SW debug control + * Add Oid for sw control debug command + * + * 01 07 2011 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add a new compiling option to control if MCR read/write is permitted + * + * 12 31 2010 cm.chang + * [WCXRP00000336] [MT6620 Wi-Fi][Driver] Add test mode commands in normal phone operation + * Add some iwpriv commands to support test mode operation + * + * 11 08 2010 wh.su + * [WCXRP00000171] [MT6620 Wi-Fi][Driver] Add message check code same behavior as mt5921 + * add the message check code from mt5921. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 09 23 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * add skeleton for NVRAM integration + * + * 08 04 2010 cp.wu + * NULL + * revert changelist #15371, efuse read/write access will be done by RF test approach + * + * 08 04 2010 cp.wu + * NULL + * add OID definitions for EFUSE read/write access. + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base + * + * 03 31 2010 wh.su + * [WPD00003816][MT6620 Wi-Fi] Adding the security support + * modify the wapi related code for new driver's design. + * + * 03 24 2010 jeffrey.chang + * [WPD00003826]Initial import for Linux port + * initial import for Linux port +** \main\maintrunk.MT5921\16 2009-09-29 16:47:23 GMT mtk01090 +** Remove unused functions +** \main\maintrunk.MT5921\15 2009-09-28 20:19:31 GMT mtk01090 +** Add private ioctl to carry OID structures. Restructure public/private ioctl interfaces to Linux kernel. +** \main\maintrunk.MT5921\14 2009-05-07 22:26:06 GMT mtk01089 +** add private IO control for Linux BWCS +** \main\maintrunk.MT5921\13 2008-08-29 14:55:20 GMT mtk01088 +** adjust the code to meet coding style +** \main\maintrunk.MT5921\12 2008-07-16 15:23:45 GMT mtk01104 +** Support GPIO2 mode +** \main\maintrunk.MT5921\11 2008-07-14 13:55:58 GMT mtk01104 +** Support PRIV_CMD_BT_COEXIST +** \main\maintrunk.MT5921\10 2008-07-09 00:20:24 GMT mtk01461 +** Add priv oid to support WMM_PS_TEST +** \main\maintrunk.MT5921\9 2008-05-30 20:27:24 GMT mtk01461 +** Add POWER_MODE Private IOCTL cmd +** \main\maintrunk.MT5921\8 2008-04-17 23:06:44 GMT mtk01461 +** Add iwpriv support for AdHocMode setting +** \main\maintrunk.MT5921\7 2008-03-31 21:01:24 GMT mtk01461 +** Add priv IOCTL for VOIP settings +** \main\maintrunk.MT5921\6 2008-03-31 13:49:47 GMT mtk01461 +** add priv ioctl arg definition for turning on / off roaming +** \main\maintrunk.MT5921\5 2008-03-26 15:35:09 GMT mtk01461 +** Add CSUM offload priv ioctl for Linux +** \main\maintrunk.MT5921\4 2008-03-11 14:51:11 GMT mtk01461 +** Refine private IOCTL functions +** \main\maintrunk.MT5921\3 2007-11-06 19:36:25 GMT mtk01088 +** add the WPS related code +*/ + +#ifndef _GL_WEXT_PRIV_H +#define _GL_WEXT_PRIV_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ +/* If it is set to 1, iwpriv will support register read/write */ +#define CFG_SUPPORT_PRIV_MCR_RW 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +#if CFG_ENABLE_WIFI_DIRECT +extern int set_p2p_mode_handler(struct net_device *netdev, PARAM_CUSTOM_P2P_SET_STRUCT_T p2pmode); +#if 0 +extern BOOLEAN fgIsResetting; +extern BOOLEAN g_u4HaltFlag; +extern spinlock_t g_p2p_lock; +extern int g_u4P2PEnding; +extern int g_u4P2POnOffing; +#endif +#endif + + +#if (CFG_SUPPORT_TXR_ENC == 1) +extern VOID rlmCmd(P_GLUE_INFO_T prGlueInfo, UINT_8 *prInBuf, UINT_32 u4InBufLen); +#endif /* CFG_SUPPORT_TXR_ENC */ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +/* New wireless extensions API - SET/GET convention (even ioctl numbers are + * root only) + */ +#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0) +#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1) + +#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2) +#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3) +#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4) +#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5) +#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6) +#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7) +#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8) +#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9) +#define IOCTL_SET_STRUCT_FOR_EM (SIOCIWFIRSTPRIV + 11) +#define IOCTL_SET_INTS (SIOCIWFIRSTPRIV + 12) +#define IOCTL_GET_INTS (SIOCIWFIRSTPRIV + 13) +#define IOCTL_SET_STRING (SIOCIWFIRSTPRIV + 14) + +#define PRIV_CMD_REG_DOMAIN 0 +#define PRIV_CMD_BEACON_PERIOD 1 +#define PRIV_CMD_ADHOC_MODE 2 + +#if CFG_TCP_IP_CHKSUM_OFFLOAD +#define PRIV_CMD_CSUM_OFFLOAD 3 +#endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */ + +#define PRIV_CMD_ROAMING 4 +#define PRIV_CMD_VOIP_DELAY 5 +#define PRIV_CMD_POWER_MODE 6 + +#define PRIV_CMD_WMM_PS 7 +#define PRIV_CMD_BT_COEXIST 8 +#define PRIV_GPIO2_MODE 9 + +#define PRIV_CUSTOM_SET_PTA 10 +#define PRIV_CUSTOM_CONTINUOUS_POLL 11 +#define PRIV_CUSTOM_SINGLE_ANTENNA 12 +#define PRIV_CUSTOM_BWCS_CMD 13 +#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION 14 /* later */ +#define PRIV_CMD_OID 15 +#define PRIV_SEC_MSG_OID 16 + +#define PRIV_CMD_TEST_MODE 17 +#define PRIV_CMD_TEST_CMD 18 +#define PRIV_CMD_ACCESS_MCR 19 +#define PRIV_CMD_SW_CTRL 20 + +#if 1 /* ANTI_PRIVCY */ +#define PRIV_SEC_CHECK_OID 21 +#endif + +#define PRIV_CMD_WSC_PROBE_REQ 22 + +#define PRIV_CMD_P2P_VERSION 23 + +#define PRIV_CMD_GET_CH_LIST 24 + +#define PRIV_CMD_SET_TX_POWER 25 + +#define PRIV_CMD_BAND_CONFIG 26 + +#define PRIV_CMD_DUMP_MEM 27 + +#define PRIV_CMD_P2P_MODE 28 + +#define PRIV_CMD_GET_BUILD_DATE_CODE 29 + +#define PRIV_CMD_GET_DEBUG_CODE 30 + +#define PRIV_CMD_OTHER 31 + +#define PRIV_CMD_WFD_DEBUG_CODE 32 + +#define PRIV_CMD_MET_PROFILING 33 + +/* other string command ID */ +#define PRIV_CMD_OTHER_TDLS 0x00 +#define PRIV_CMD_OTHER_TAR 0x01 /* TX auto rate */ + +/* 802.3 Objects (Ethernet) */ +#define OID_802_3_CURRENT_ADDRESS 0x01010102 + +/* IEEE 802.11 OIDs */ +#define OID_802_11_SUPPORTED_RATES 0x0D01020E +#define OID_802_11_CONFIGURATION 0x0D010211 + +/* PnP and PM OIDs, NDIS default OIDS */ +#define OID_PNP_SET_POWER 0xFD010101 + +#define OID_CUSTOM_OID_INTERFACE_VERSION 0xFFA0C000 + +/* MT5921 specific OIDs */ +#define OID_CUSTOM_BT_COEXIST_CTRL 0xFFA0C580 +#define OID_CUSTOM_POWER_MANAGEMENT_PROFILE 0xFFA0C581 +#define OID_CUSTOM_PATTERN_CONFIG 0xFFA0C582 +#define OID_CUSTOM_BG_SSID_SEARCH_CONFIG 0xFFA0C583 +#define OID_CUSTOM_VOIP_SETUP 0xFFA0C584 +#define OID_CUSTOM_ADD_TS 0xFFA0C585 +#define OID_CUSTOM_DEL_TS 0xFFA0C586 +#define OID_CUSTOM_SLT 0xFFA0C587 +#define OID_CUSTOM_ROAMING_EN 0xFFA0C588 +#define OID_CUSTOM_WMM_PS_TEST 0xFFA0C589 +#define OID_CUSTOM_COUNTRY_STRING 0xFFA0C58A +#define OID_CUSTOM_MULTI_DOMAIN_CAPABILITY 0xFFA0C58B +#define OID_CUSTOM_GPIO2_MODE 0xFFA0C58C +#define OID_CUSTOM_CONTINUOUS_POLL 0xFFA0C58D +#define OID_CUSTOM_DISABLE_BEACON_DETECTION 0xFFA0C58E + +/* CR1460, WPS privacy bit check disable */ +#define OID_CUSTOM_DISABLE_PRIVACY_CHECK 0xFFA0C600 + +/* Precedent OIDs */ +#define OID_CUSTOM_MCR_RW 0xFFA0C801 +#define OID_CUSTOM_EEPROM_RW 0xFFA0C803 +#define OID_CUSTOM_SW_CTRL 0xFFA0C805 +#define OID_CUSTOM_MEM_DUMP 0xFFA0C807 + +/* RF Test specific OIDs */ +#define OID_CUSTOM_TEST_MODE 0xFFA0C901 +#define OID_CUSTOM_TEST_RX_STATUS 0xFFA0C903 +#define OID_CUSTOM_TEST_TX_STATUS 0xFFA0C905 +#define OID_CUSTOM_ABORT_TEST_MODE 0xFFA0C906 +#define OID_CUSTOM_MTK_WIFI_TEST 0xFFA0C911 + +/* BWCS */ +#define OID_CUSTOM_BWCS_CMD 0xFFA0C931 +#define OID_CUSTOM_SINGLE_ANTENNA 0xFFA0C932 +#define OID_CUSTOM_SET_PTA 0xFFA0C933 + +/* NVRAM */ +#define OID_CUSTOM_MTK_NVRAM_RW 0xFFA0C941 +#define OID_CUSTOM_CFG_SRC_TYPE 0xFFA0C942 +#define OID_CUSTOM_EEPROM_TYPE 0xFFA0C943 + +#if CFG_SUPPORT_WAPI +#define OID_802_11_WAPI_MODE 0xFFA0CA00 +#define OID_802_11_WAPI_ASSOC_INFO 0xFFA0CA01 +#define OID_802_11_SET_WAPI_KEY 0xFFA0CA02 +#endif + +#if CFG_SUPPORT_WPS2 +#define OID_802_11_WSC_ASSOC_INFO 0xFFA0CB00 +#endif + +/* Define magic key of test mode (Don't change it for future compatibity) */ +#define PRIV_CMD_TEST_MAGIC_KEY 2011 + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +/* NIC BBCR configuration entry structure */ +typedef struct _PRIV_CONFIG_ENTRY { + UINT_8 ucOffset; + UINT_8 ucValue; +} PRIV_CONFIG_ENTRY, *PPRIV_CONFIG_ENTRY; + +typedef WLAN_STATUS(*PFN_OID_HANDLER_FUNC_REQ) (IN PVOID prAdapter, + IN OUT PVOID pvBuf, IN UINT_32 u4BufLen, OUT PUINT_32 pu4OutInfoLen); + +typedef enum _ENUM_OID_METHOD_T { + ENUM_OID_GLUE_ONLY, + ENUM_OID_GLUE_EXTENSION, + ENUM_OID_DRIVER_CORE +} ENUM_OID_METHOD_T, *P_ENUM_OID_METHOD_T; + +/* OID set/query processing entry */ +typedef struct _WLAN_REQ_ENTRY { + UINT_32 rOid; /* OID */ + PUINT_8 pucOidName; /* OID name text */ + BOOLEAN fgQryBufLenChecking; + BOOLEAN fgSetBufLenChecking; + ENUM_OID_METHOD_T eOidMethod; + UINT_32 u4InfoBufLen; + PFN_OID_HANDLER_FUNC_REQ pfOidQueryHandler; /* PFN_OID_HANDLER_FUNC */ + PFN_OID_HANDLER_FUNC_REQ pfOidSetHandler; /* PFN_OID_HANDLER_FUNC */ +} WLAN_REQ_ENTRY, *P_WLAN_REQ_ENTRY; + +typedef struct _NDIS_TRANSPORT_STRUCT { + UINT_32 ndisOidCmd; + UINT_32 inNdisOidlength; + UINT_32 outNdisOidLength; + UINT_8 ndisOidContent[16]; +} NDIS_TRANSPORT_STRUCT, *P_NDIS_TRANSPORT_STRUCT; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +int +priv_set_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int +priv_get_int(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +int +priv_set_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int +priv_get_ints(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +int +priv_set_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int +priv_get_struct(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN OUT char *pcExtra); + +UINT_32 CmdStringDecParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen); + +UINT_32 CmdStringMacParse(IN UINT_8 *InStr, OUT UINT_8 **OutStr, OUT UINT_32 *OutLen, OUT UINT_8 *OutMac); + +int +priv_set_string(IN struct net_device *prNetDev, + IN struct iw_request_info *prIwReqInfo, IN union iwreq_data *prIwReqData, IN char *pcExtra); + +int priv_support_ioctl(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +int priv_support_driver_cmd(IN struct net_device *prDev, IN OUT struct ifreq *prReq, IN int i4Cmd); + +INT_32 priv_driver_cmds(IN struct net_device *prNetDev, IN PCHAR pcCommand, IN INT_32 i4TotalLen); + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _GL_WEXT_PRIV_H */ diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c new file mode 100644 index 0000000000000..fba854cfd68e1 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/linux/platform.c @@ -0,0 +1,542 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/linux/platform.c#1 +*/ + +/*! \file "platform.c" + \brief This file including the protocol layer privacy function. + + This file provided the macros and functions library support for the + protocol layer security setting from wlan_oid.c and for parse.c and + rsn.c and nic_privacy.c + +*/ + +/* +** Log: platform.c + * + * 11 14 2011 cm.chang + * NULL + * Fix compiling warning + * + * 11 10 2011 cp.wu + * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer + * 1. eliminaite direct calls to printk in porting layer. + * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms. + * + * 09 13 2011 jeffrey.chang + * [WCXRP00000983] [MT6620][Wi-Fi Driver] invalid pointer casting causes kernel panic during p2p connection + * fix the pointer casting + * + * 06 29 2011 george.huang + * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 + * . + * + * 06 28 2011 george.huang + * [WCXRP00000818] [MT6620 Wi-Fi][Driver] Remove unused code segment regarding CONFIG_IPV6 + * remove un-used code + * + * 05 11 2011 jeffrey.chang + * NULL + * fix build error + * + * 05 09 2011 jeffrey.chang + * [WCXRP00000710] [MT6620 Wi-Fi] Support pattern filter update function on IP address change + * support ARP filter through kernel notifier + * + * 04 08 2011 pat.lu + * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver + * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile setting for PC Linux driver + * + * 03 22 2011 pat.lu + * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build + * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment. + * + * 03 21 2011 cp.wu + * [WCXRP00000540] [MT5931][Driver] Add eHPI8/eHPI16 support to Linux Glue Layer + * improve portability for awareness of early version of linux kernel and wireless extension. + * + * 03 18 2011 jeffrey.chang + * [WCXRP00000512] [MT6620 Wi-Fi][Driver] modify the net device relative functions to support the H/W multiple queue + * remove early suspend functions + * + * 03 03 2011 jeffrey.chang + * NULL + * add the ARP filter callback + * + * 02 15 2011 jeffrey.chang + * NULL + * to support early suspend in android + * + * 02 01 2011 cp.wu + * [WCXRP00000413] [MT6620 Wi-Fi][Driver] Merge 1103 changes on NVRAM file path change to DaVinci main trunk and V1.1 + * branch + * upon Jason Zhang(NVRAM owner)'s change, ALPS has modified its NVRAM storage from /nvram/... to /data/nvram/... + * + * 11 01 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000150] [MT6620 Wi-Fi][Driver] + * Add implementation for querying current TX rate from firmware auto rate module + * 1) Query link speed (TX rate) from firmware directly with buffering mechanism to reduce overhead + * 2) Remove CNM CH-RECOVER event handling + * 3) cfg read/write API renamed with kal prefix for unified naming rules. + * + * 10 18 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check[WCXRP00000086] [MT6620 Wi-Fi][Driver] + * The mac address is all zero at android + * complete implementation of Android NVRAM access + * + * 10 05 2010 cp.wu + * [WCXRP00000056] [MT6620 Wi-Fi][Driver] NVRAM implementation with Version Check + * 1) add NVRAM access API + * 2) fake scanning result when NVRAM doesn't exist and/or version mismatch. (off by compiler option) + * 3) add OID implementation for NVRAM read/write service + * +** +*/ +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ +#include +#include +#include +#include +#include + +#include + +#include "gl_os.h" + +#ifndef CONFIG_X86 +#if defined(CONFIG_HAS_EARLY_SUSPEND) +#include +#endif +#endif + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ +#define WIFI_NVRAM_FILE_NAME "/etc/firmware/nvram/WIFI" +#define WIFI_NVRAM_CUSTOM_NAME "/etc/firmware/nvram/WIFI_CUSTOM" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +static int netdev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + UINT_8 ip[4] = { 0 }; + UINT_32 u4NumIPv4 = 0; +/* #ifdef CONFIG_IPV6 */ +#if 0 + UINT_8 ip6[16] = { 0 }; /* FIX ME: avoid to allocate large memory in stack */ + UINT_32 u4NumIPv6 = 0; +#endif + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + struct net_device *prDev = ifa->ifa_dev->dev; + UINT_32 i; + P_PARAM_NETWORK_ADDRESS_IP prParamIpAddr; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, ERROR, "netdev_event: device is empty.\n"); + return NOTIFY_DONE; + } + DBGLOG(REQ, INFO, "netdev_event, addr=%x, notification=%lx, dev_name=%s\n", + ifa->ifa_address, notification, prDev->name); + if (!fgIsUnderSuspend) + return NOTIFY_DONE; + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, WARN, "netdev_event: not our device\n"); + return NOTIFY_DONE; + } +#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ + { + /* printk(KERN_INFO "[netdev_event] IPV4_DAD is unlock now!!\n"); */ + prGlueInfo->fgIsDad = FALSE; + } +#endif + + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + + if (prGlueInfo == NULL) { + DBGLOG(REQ, ERROR, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + ASSERT(prGlueInfo); + + /* <3> get the IPv4 address */ + if (!prDev || !(prDev->ip_ptr) || + !((struct in_device *)(prDev->ip_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local))) { + DBGLOG(REQ, INFO, "ip is not available.\n"); + return NOTIFY_DONE; + } + + kalMemCopy(ip, &(((struct in_device *)(prDev->ip_ptr))->ifa_list->ifa_local), sizeof(ip)); + DBGLOG(REQ, INFO, "ip is %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]); + + /* todo: traverse between list to find whole sets of IPv4 addresses */ + if (!((ip[0] == 0) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 0))) + u4NumIPv4++; +/* #ifdef CONFIG_IPV6 */ +#if 0 + if (!prDev || !(prDev->ip6_ptr) || + !((struct in_device *)(prDev->ip6_ptr))->ifa_list || + !(&(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local))) { + DBGLOG(REQ, INFO, "ipv6 is not available.\n"); + return NOTIFY_DONE; + } + + kalMemCopy(ip6, &(((struct in_device *)(prDev->ip6_ptr))->ifa_list->ifa_local), sizeof(ip6)); + DBGLOG(REQ, INFO, "ipv6 is %d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d.%d\n", + ip6[0], ip6[1], ip6[2], ip6[3], + ip6[4], ip6[5], ip6[6], ip6[7], ip6[8], ip6[9], ip6[10], ip6[11], ip6[12], ip6[13], ip6[14], ip6[15]); + + /* todo: traverse between list to find whole sets of IPv6 addresses */ + if (!((ip6[0] == 0) && (ip6[1] == 0) && (ip6[2] == 0) && (ip6[3] == 0) && (ip6[4] == 0) && (ip6[5] == 0))) + /* u4NumIPv6++; */ +#endif + + /* here we can compare the dev with other network's netdev to */ + /* set the proper arp filter */ + /* */ + /* IMPORTANT: please make sure if the context can sleep, if the context can't sleep */ + /* we should schedule a kernel thread to do this for us */ + + /* <7> set up the ARP filter */ + { + WLAN_STATUS rStatus = WLAN_STATUS_FAILURE; + UINT_32 u4SetInfoLen = 0; + UINT_8 aucBuf[32] = { 0 }; + UINT_32 u4Len = OFFSET_OF(PARAM_NETWORK_ADDRESS_LIST, arAddress); + P_PARAM_NETWORK_ADDRESS_LIST prParamNetAddrList = (P_PARAM_NETWORK_ADDRESS_LIST) aucBuf; + P_PARAM_NETWORK_ADDRESS prParamNetAddr = prParamNetAddrList->arAddress; + +/* #ifdef CONFIG_IPV6 */ +#if 0 + prParamNetAddrList->u4AddressCount = u4NumIPv4 + u4NumIPv6; +#else + prParamNetAddrList->u4AddressCount = u4NumIPv4; +#endif + prParamNetAddrList->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + for (i = 0; i < u4NumIPv4; i++) { + prParamNetAddr->u2AddressLength = sizeof(PARAM_NETWORK_ADDRESS_IP); /* 4;; */ + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; +#if 0 + kalMemCopy(prParamNetAddr->aucAddress, ip, sizeof(ip)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip); +#else + prParamIpAddr = (P_PARAM_NETWORK_ADDRESS_IP) prParamNetAddr->aucAddress; + kalMemCopy(&prParamIpAddr->in_addr, ip, sizeof(ip)); + prParamNetAddr = + (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(PARAM_NETWORK_ADDRESS)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(PARAM_NETWORK_ADDRESS); +#endif + } +/* #ifdef CONFIG_IPV6 */ +#if 0 + for (i = 0; i < u4NumIPv6; i++) { + prParamNetAddr->u2AddressLength = 6; + prParamNetAddr->u2AddressType = PARAM_PROTOCOL_ID_TCP_IP; + kalMemCopy(prParamNetAddr->aucAddress, ip6, sizeof(ip6)); + prParamNetAddr = (P_PARAM_NETWORK_ADDRESS) ((PUINT_8) prParamNetAddr + sizeof(ip6)); + u4Len += OFFSET_OF(PARAM_NETWORK_ADDRESS, aucAddress) + sizeof(ip6); + } +#endif + ASSERT(u4Len <= sizeof(aucBuf)); + + DBGLOG(REQ, INFO, "kalIoctl (0x%p, 0x%p)\n", prGlueInfo, prParamNetAddrList); + + rStatus = kalIoctl(prGlueInfo, + wlanoidSetNetworkAddress, + (PVOID) prParamNetAddrList, u4Len, FALSE, FALSE, TRUE, FALSE, &u4SetInfoLen); + + if (rStatus != WLAN_STATUS_SUCCESS) + DBGLOG(REQ, ERROR, "set HW pattern filter fail 0x%x\n", rStatus); + } + + return NOTIFY_DONE; + +} + +/* #if CFG_SUPPORT_HOTSPOT_2_0 */ +#if 0 +static int net6dev_event(struct notifier_block *nb, unsigned long notification, void *ptr) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; + struct net_device *prDev = ifa->idev->dev; + P_GLUE_INFO_T prGlueInfo = NULL; + + if (prDev == NULL) { + DBGLOG(REQ, INFO, "net6dev_event: device is empty.\n"); + return NOTIFY_DONE; + } + + if ((strncmp(prDev->name, "p2p", 3) != 0) && (strncmp(prDev->name, "wlan", 4) != 0)) { + DBGLOG(REQ, INFO, "net6dev_event: xxx\n"); + return NOTIFY_DONE; + } + + if (strncmp(prDev->name, "p2p", 3) == 0) { + /* because we store the address of prGlueInfo in p2p's private date of net device */ + /* *((P_GLUE_INFO_T *) netdev_priv(prGlueInfo->prP2PInfo->prDevHandler)) = prGlueInfo; */ + prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev)); + } else { /* wlan0 */ + prGlueInfo = (P_GLUE_INFO_T) netdev_priv(prDev); + } + + if (prGlueInfo == NULL) { + DBGLOG(REQ, INFO, "netdev_event: prGlueInfo is empty.\n"); + return NOTIFY_DONE; + } + /* printk(KERN_INFO "[net6dev_event] IPV6_DAD is unlock now!!\n"); */ + prGlueInfo->fgIs6Dad = FALSE; + + return NOTIFY_DONE; +} +#endif + +static struct notifier_block inetaddr_notifier = { + .notifier_call = netdev_event, +}; + +#if 0 /* CFG_SUPPORT_HOTSPOT_2_0 */ +static struct notifier_block inet6addr_notifier = { + .notifier_call = net6dev_event, +}; +#endif + +void wlanRegisterNotifier(void) +{ + register_inetaddr_notifier(&inetaddr_notifier); + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* register_inet6addr_notifier(&inet6addr_notifier); */ +#endif +} + +/* EXPORT_SYMBOL(wlanRegisterNotifier); */ + +void wlanUnregisterNotifier(void) +{ + unregister_inetaddr_notifier(&inetaddr_notifier); + +#if CFG_SUPPORT_HOTSPOT_2_0 + /* unregister_inetaddr_notifier(&inet6addr_notifier); */ +#endif +} + +/* EXPORT_SYMBOL(wlanUnregisterNotifier); */ + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Utility function for reading data from files on NVRAM-FS +* +* \param[in] +* filename +* len +* offset +* \param[out] +* buf +* \return +* actual length of data being read +*/ +/*----------------------------------------------------------------------------*/ +static int nvram_read(char *filename, char *buf, ssize_t len, int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + + fd = filp_open(filename, O_RDONLY, 0644); + + if (IS_ERR(fd)) { + DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to open!!\n"); + return -1; + } + + do { + //if ((fd->f_op == NULL) || (fd->f_op->read == NULL)) { + if ( fd->f_op == NULL ) { + DBGLOG(INIT, INFO, "[MT6620][nvram_read] : file can not be read!!\n"); + break; + } + + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, "[MT6620][nvram_read] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + + retLen = vfs_read(fd, buf, len, &fd->f_pos); + + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAM */ + + return -EIO; + +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief Utility function for writing data to files on NVRAM-FS +* +* \param[in] +* filename +* buf +* len +* offset +* \return +* actual length of data being written +*/ +/*----------------------------------------------------------------------------*/ +static int nvram_write(char *filename, char *buf, ssize_t len, int offset) +{ +#if CFG_SUPPORT_NVRAM + struct file *fd; + int retLen = -1; + + mm_segment_t old_fs = get_fs(); + + set_fs(KERNEL_DS); + + fd = filp_open(filename, O_WRONLY | O_CREAT, 0644); + + if (IS_ERR(fd)) { + DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to open!!\n"); + return -1; + } + + do { + if ((fd->f_op == NULL) || (fd->f_op->write == NULL)) { + DBGLOG(INIT, INFO, "[MT6620][nvram_write] : file can not be write!!\n"); + break; + } + /* End of if */ + if (fd->f_pos != offset) { + if (fd->f_op->llseek) { + if (fd->f_op->llseek(fd, offset, 0) != offset) { + DBGLOG(INIT, INFO, "[MT6620][nvram_write] : failed to seek!!\n"); + break; + } + } else { + fd->f_pos = offset; + } + } + + retLen = vfs_write(fd, buf, len, &fd->f_pos); + + } while (FALSE); + + filp_close(fd, NULL); + + set_fs(old_fs); + + return retLen; + +#else /* !CFG_SUPPORT_NVRAMS */ + + return -EIO; + +#endif +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief API for reading data on NVRAM +* +* \param[in] +* prGlueInfo +* u4Offset +* \param[out] +* pu2Data +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCfgDataRead16(IN P_GLUE_INFO_T prGlueInfo, IN UINT_32 u4Offset, OUT PUINT_16 pu2Data) +{ + if (pu2Data == NULL) + return FALSE; + + if (nvram_read(WIFI_NVRAM_FILE_NAME, + (char *)pu2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +} + +/*----------------------------------------------------------------------------*/ +/*! +* \brief API for writing data on NVRAM +* +* \param[in] +* prGlueInfo +* u4Offset +* u2Data +* \return +* TRUE +* FALSE +*/ +/*----------------------------------------------------------------------------*/ +BOOLEAN kalCfgDataWrite16(IN P_GLUE_INFO_T prGlueInfo, UINT_32 u4Offset, UINT_16 u2Data) +{ + if (nvram_write(WIFI_NVRAM_FILE_NAME, + (char *)&u2Data, sizeof(unsigned short), u4Offset) != sizeof(unsigned short)) { + return FALSE; + } else { + return TRUE; + } +} diff --git a/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h b/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h new file mode 100644 index 0000000000000..9444d415c60e8 --- /dev/null +++ b/drivers/misc/mediatek/connectivity/wlan/gen2/os/version.h @@ -0,0 +1,190 @@ +/* +** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/os/version.h#1 +*/ + +/*! \file "version.h" + \brief Driver's version definition + +*/ + +/* +** Log: version.h + * + * 11 01 2011 chinglan.wang + * NULL + * Change the version number to v2.0.1.1. + * + * 08 26 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.9.. + * + * 08 23 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.8. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * correct typo. + * + * 08 15 2011 cp.wu + * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree + * for building MT6628 Win32 driver environment + * + * 08 03 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.7. + * + * 07 24 2011 puff.wen + * NULL + * [MT5931][Beta 5]Change the version number to v0.2.2.0 + * + * 06 01 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.6.. + * + * 05 09 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.5.. + * + * 04 19 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.4. + * + * 04 18 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.3. + * + * 03 25 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.2. + * + * 03 21 2011 chinglan.wang + * NULL + * Change the version number to 2.0.0.1. + * + * 03 18 2011 chinglan.wang + * NULL + * Change the version number to v2.0.0.0. + * + * 02 11 2011 chinglan.wang + * NULL + * Change to the version 1.2.0.2. + * + * 02 10 2011 chinglan.wang + * NULL + * Change the version to 1.2.0.1. + * + * 02 08 2011 cp.wu + * [WCXRP00000427] [MT6620 Wi-Fi][Driver] Modify veresion information to match with release revision number + * change version number to v1.2.0.0 for preparing v1.2 software package release. + * + * 12 10 2010 kevin.huang + * [WCXRP00000128] [MT6620 Wi-Fi][Driver] Add proc support to Android Driver for debug and driver status check + * Add Linux Proc Support + * + * 10 07 2010 cp.wu + * [WCXRP00000083] [MT5931][Driver][FW] Add necessary logic for MT5931 first connection + * [WINDDK] build system changes for MT5931 + * + * 07 08 2010 cp.wu + * + * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository. + * + * 06 06 2010 kevin.huang + * [WPD00003832][MT6620 5931] Create driver base + * [MT6620 5931] Create driver base +** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-12-14 14:10:55 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-17 22:41:00 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-13 16:20:33 GMT mtk01084 +** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:27:13 GMT mtk01426 +** Init for develop +** +*/ + +#ifndef _VERSION_H +#define _VERSION_H +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +#ifndef NIC_AUTHOR +#define NIC_AUTHOR "NIC_AUTHOR" +#endif +#ifndef NIC_DESC +#define NIC_DESC "NIC_DESC" +#endif + +#ifndef NIC_NAME +#if defined(MT6620) +#define NIC_NAME "MT6620" +#define NIC_DEVICE_ID "MT6620" +#define NIC_DEVICE_ID_LOW "mt6620" +#elif defined(MT6628) +#define NIC_NAME "MT6582" +#define NIC_DEVICE_ID "MT6582" +#define NIC_DEVICE_ID_LOW "mt6582" +#endif +#endif + +/* NIC driver information */ +#define NIC_VENDOR "MediaTek Inc." +#define NIC_VENDOR_OUI {0x00, 0x0C, 0xE7} + +#if defined(MT6620) +#define NIC_PRODUCT_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. MT6620 Wireless LAN Adapter Driver" +#elif defined(MT6628) +/* #define NIC_PRODUCT_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter" */ +/* #define NIC_DRIVER_NAME "MediaTek Inc. MT6628 Wireless LAN Adapter Driver" */ +#define NIC_PRODUCT_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter" +#define NIC_DRIVER_NAME "MediaTek Inc. MT6582 Wireless LAN Adapter Driver" +#endif + +/* Define our driver version */ +#define NIC_DRIVER_MAJOR_VERSION 2 +#define NIC_DRIVER_MINOR_VERSION 0 +#define NIC_DRIVER_VERSION (2, 0, 1, 1) +#define NIC_DRIVER_VERSION_STRING "2.0.1.1" + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _VERSION_H */ diff --git a/drivers/misc/mediatek/include/mt-plat/aee.h b/drivers/misc/mediatek/include/mt-plat/aee.h new file mode 100644 index 0000000000000..d1cf448dafb21 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/aee.h @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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(__AEE_H__) +#define __AEE_H__ + +#include +#include + +#define AEE_MODULE_NAME_LENGTH 64 +#define AEE_PROCESS_NAME_LENGTH 256 +#define AEE_BACKTRACE_LENGTH 3072 + +typedef enum { + AE_DEFECT_FATAL, + AE_DEFECT_EXCEPTION, + AE_DEFECT_WARNING, + AE_DEFECT_REMINDING, + AE_DEFECT_ATTR_END +} AE_DEFECT_ATTR; + +typedef enum { + AE_KE = 0, /* Fatal Exception */ + AE_HWT, + AE_REBOOT, + AE_NE, + AE_JE, + AE_SWT, + AE_EE, + AE_EXP_ERR_END, + AE_ANR, /* Error or Warning or Defect */ + AE_RESMON, + AE_MODEM_WARNING, + AE_WTF, + AE_WRN_ERR_END, + AE_MANUAL, /* Manual Raise */ + AE_EXP_CLASS_END, + + AE_KERNEL_PROBLEM_REPORT = 1000, + AE_SYSTEM_JAVA_DEFECT, + AE_SYSTEM_NATIVE_DEFECT, + AE_MANUAL_MRDUMP_KEY, +} AE_EXP_CLASS; /* General Program Exception Class */ + +typedef enum { + AEE_REBOOT_MODE_NORMAL = 0, + AEE_REBOOT_MODE_KERNEL_OOPS, + AEE_REBOOT_MODE_KERNEL_PANIC, + AEE_REBOOT_MODE_NESTED_EXCEPTION, + AEE_REBOOT_MODE_WDT, + AEE_REBOOT_MODE_MANUAL_KDUMP, +} AEE_REBOOT_MODE; + +#define AEE_SZ_SYMBOL_L 140 +#define AEE_SZ_SYMBOL_S 80 +struct aee_bt_frame { + __u64 pc; + __u64 lr; + __u32 pad[5]; + char pc_symbol[AEE_SZ_SYMBOL_S]; /* Now we use different symbol length for PC &LR */ + char lr_symbol[AEE_SZ_SYMBOL_L]; +}; + +/* aee_process_info struct should strictly small than ipanic_buffer, now 4KB */ +struct aee_process_info { + char process_path[AEE_PROCESS_NAME_LENGTH]; + char backtrace[AEE_BACKTRACE_LENGTH]; + struct aee_bt_frame ke_frame; +}; + +struct aee_process_bt { + __u32 pid; + __u32 nr_entries; + struct aee_bt_frame *entries; +}; + + +struct aee_thread_reg { + pid_t tid; + struct pt_regs regs; +}; + +struct aee_user_thread_stack { + pid_t tid; + int StackLength; + unsigned char *Userthread_Stack; /*8k stack ,define to char only for match 64bit/32bit*/ +}; + +struct aee_user_thread_maps { + pid_t tid; + int Userthread_mapsLength; + unsigned char *Userthread_maps; /*8k stack ,define to char only for match 64bit/32bit*/ +}; + + + +struct aee_oops { + struct list_head list; + AE_DEFECT_ATTR attr; + AE_EXP_CLASS clazz; + + char module[AEE_MODULE_NAME_LENGTH]; + /* consist with struct aee_process_info */ + char process_path[AEE_PROCESS_NAME_LENGTH]; + char backtrace[AEE_BACKTRACE_LENGTH]; + struct aee_bt_frame ke_frame; + + char *detail; + int detail_len; + + char *console; + int console_len; + + char *android_main; + int android_main_len; + char *android_radio; + int android_radio_len; + char *android_system; + int android_system_len; + + char *userspace_info; + int userspace_info_len; + + char *mmprofile; + int mmprofile_len; + + char *mini_rdump; + int mini_rdump_len; + + + struct aee_user_thread_stack userthread_stack; + struct aee_thread_reg userthread_reg; + struct aee_user_thread_maps userthread_maps; + + int dump_option; +}; + +struct aee_kernel_api { + void (*kernel_reportAPI)(const AE_DEFECT_ATTR attr, const int db_opt, const char *module, + const char *msg); + void (*md_exception)(const char *assert_type, const int *log, int log_size, const int *phy, + int phy_size, const char *detail, const int db_opt); + void (*md32_exception)(const char *assert_type, const int *log, int log_size, + const int *phy, int phy_size, const char *detail, const int db_opt); + void (*combo_exception)(const char *assert_type, const int *log, int log_size, + const int *phy, int phy_size, const char *detail, const int db_opt); + void (*scp_exception)(const char *assert_type, const int *log, int log_size, + const int *phy, int phy_size, const char *detail, const int db_opt); +}; + +void aee_sram_printk(const char *fmt, ...); +int aee_nested_printf(const char *fmt, ...); +void aee_wdt_irq_info(void); +void aee_wdt_fiq_info(void *arg, void *regs, void *svc_sp); +void aee_trigger_kdb(void); +struct aee_oops *aee_oops_create(AE_DEFECT_ATTR attr, AE_EXP_CLASS clazz, const char *module); +void aee_oops_set_backtrace(struct aee_oops *oops, const char *backtrace); +void aee_oops_set_process_path(struct aee_oops *oops, const char *process_path); +void aee_oops_free(struct aee_oops *oops); +/* powerkey press,modules use bits */ +#define AE_WDT_Powerkey_DEVICE_PATH "/dev/kick_powerkey" +#define WDT_SETBY_DEFAULT (0) +#define WDT_SETBY_Backlight (1<<0) +#define WDT_SETBY_Display (1<<1) +#define WDT_SETBY_SF (1<<2) +#define WDT_SETBY_PM (1<<3) +#define WDT_SETBY_WMS_DISABLE_PWK_MONITOR (0xAEEAEE00) +#define WDT_SETBY_WMS_ENABLE_PWK_MONITOR (0xAEEAEE01) +#define WDT_PWK_HANG_FORCE_HWT (0xAEE0FFFF) + +/* QHQ RT Monitor */ +#define AEEIOCTL_RT_MON_Kick _IOR('p', 0x0A, int) +#define AE_WDT_DEVICE_PATH "/dev/RT_Monitor" +/* QHQ RT Monitor end */ + +/* DB dump option bits, set relative bit to 1 to include related file in db */ +#define DB_OPT_DEFAULT (0) +#define DB_OPT_FTRACE (1<<0) +#define DB_OPT_PRINTK_TOO_MUCH (1<<1) +#define DB_OPT_NE_JBT_TRACES (1<<2) +#define DB_OPT_SWT_JBT_TRACES (1<<3) +#define DB_OPT_VM_TRACES (1<<4) +#define DB_OPT_DUMPSYS_ACTIVITY (1<<5) +#define DB_OPT_DUMPSYS_WINDOW (1<<6) +#define DB_OPT_DUMPSYS_GFXINFO (1<<7) +#define DB_OPT_DUMPSYS_SURFACEFLINGER (1<<8) +#define DB_OPT_DISPLAY_HANG_DUMP (1<<9) +#define DB_OPT_LOW_MEMORY_KILLER (1<<10) +#define DB_OPT_PROC_MEM (1<<11) +#define DB_OPT_FS_IO_LOG (1<<12) +#define DB_OPT_PROCESS_COREDUMP (1<<13) +#define DB_OPT_VM_HPROF (1<<14) +#define DB_OPT_PROCMEM (1<<15) +#define DB_OPT_DUMPSYS_INPUT (1<<16) +#define DB_OPT_MMPROFILE_BUFFER (1<<17) +#define DB_OPT_BINDER_INFO (1<<18) +#define DB_OPT_WCN_ISSUE_INFO (1<<19) +#define DB_OPT_DUMMY_DUMP (1<<20) +#define DB_OPT_PID_MEMORY_INFO (1<<21) +#define DB_OPT_VM_OOME_HPROF (1<<22) +#define DB_OPT_PID_SMAPS (1<<23) +#define DB_OPT_PROC_CMDQ_INFO (1<<24) +#define DB_OPT_PROC_USKTRK (1<<25) +#define DB_OPT_SF_RTT_DUMP (1<<26) +#define DB_OPT_PAGETYPE_INFO (1<<27) +#define DB_OPT_DUMPSYS_PROCSTATS (1<<28) +#define DB_OPT_DUMP_DISPLAY (1<<29) +#define DB_OPT_NATIVE_BACKTRACE (1<<30) +#define DB_OPT_AARCH64 (1<<31) + +#define aee_kernel_exception(module, msg...) \ + aee_kernel_exception_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) +#define aee_kernel_warning(module, msg...) \ + aee_kernel_warning_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) +#define aee_kernel_reminding(module, msg...) \ + aee_kernel_reminding_api(__FILE__, __LINE__, DB_OPT_DEFAULT, module, msg) +#define aee_kernel_dal_show(msg) \ + aee_kernel_dal_api(__FILE__, __LINE__, msg) + +#define aed_md_exception(log, log_size, phy, phy_size, detail) \ + aed_md_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) +#define aed_md32_exception(log, log_size, phy, phy_size, detail) \ + aed_md32_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) +#define aed_scp_exception(log, log_size, phy, phy_size, detail) \ + aed_scp_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) +#define aed_combo_exception(log, log_size, phy, phy_size, detail) \ + aed_combo_exception_api(log, log_size, phy, phy_size, detail, DB_OPT_DEFAULT) + +void aee_kernel_exception_api(const char *file, const int line, const int db_opt, + const char *module, const char *msg, ...); +void aee_kernel_warning_api(const char *file, const int line, const int db_opt, const char *module, + const char *msg, ...); +void aee_kernel_reminding_api(const char *file, const int line, const int db_opt, + const char *module, const char *msg, ...); +void aee_kernel_dal_api(const char *file, const int line, const char *msg); + +void aed_md_exception_api(const int *log, int log_size, const int *phy, int phy_size, + const char *detail, const int db_opt); +void aed_md32_exception_api(const int *log, int log_size, const int *phy, int phy_size, + const char *detail, const int db_opt); +void aed_scp_exception_api(const int *log, int log_size, const int *phy, int phy_size, + const char *detail, const int db_opt); +void aed_combo_exception_api(const int *log, int log_size, const int *phy, int phy_size, + const char *detail, const int db_opt); + +void aee_kernel_wdt_kick_Powkey_api(const char *module, int msg); +int aee_kernel_wdt_kick_api(int kinterval); +void aee_powerkey_notify_press(unsigned long pressed); +int aee_kernel_Powerkey_is_press(void); + +void ipanic_recursive_ke(struct pt_regs *regs, struct pt_regs *excp_regs, int cpu); + +/* QHQ RT Monitor */ +void aee_kernel_RT_Monitor_api(int lParam); +/* QHQ RT Monitor end */ +void mt_fiq_printf(const char *fmt, ...); +void aee_register_api(struct aee_kernel_api *aee_api); +int aee_in_nested_panic(void); +void aee_stop_nested_panic(struct pt_regs *regs); +void aee_wdt_dump_info(void); +void aee_wdt_printf(const char *fmt, ...); + +void aee_fiq_ipi_cpu_stop(void *arg, void *regs, void *svc_sp); + +#if defined(CONFIG_MTK_AEE_DRAM_CONSOLE) +void aee_dram_console_reserve_memory(void); +#else +static inline void aee_dram_console_reserve_memory(void) +{ +} +#endif + +extern void *aee_excp_regs; /* To store latest exception, in case of stack corruption */ +#endif /* __AEE_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mrdump.h b/drivers/misc/mediatek/include/mt-plat/mrdump.h new file mode 100644 index 0000000000000..b6bdfa2f7617c --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mrdump.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#if !defined(__MRDUMP_H__) +#define __MRDUMP_H__ + +#include +#include +#include +#include +#include + +#ifdef __aarch64__ +#define reg_pc pc +#define reg_lr regs[30] +#define reg_sp sp +#define reg_fp regs[29] +#else +#define reg_pc ARM_pc +#define reg_lr ARM_lr +#define reg_sp ARM_sp +#define reg_ip ARM_ip +#define reg_fp ARM_fp +#endif + +#define MRDUMP_CPU_MAX 16 + +#define MRDUMP_DEV_NULL 0 +#define MRDUMP_DEV_SDCARD 1 +#define MRDUMP_DEV_EMMC 2 + +#define MRDUMP_FS_NULL 0 +#define MRDUMP_FS_VFAT 1 +#define MRDUMP_FS_EXT4 2 + +#define MRDUMP_GO_DUMP "MRDUMP04" + +typedef uint32_t arm32_gregset_t[18]; +typedef uint64_t aarch64_gregset_t[34]; + +struct mrdump_crash_record { + int reboot_mode; + + char msg[128]; + char backtrace[512]; + + uint32_t fault_cpu; + + union { + arm32_gregset_t arm32_regs; + aarch64_gregset_t aarch64_regs; + } cpu_regs[MRDUMP_CPU_MAX]; +}; + +struct mrdump_machdesc { + uint32_t crc; + + uint32_t output_device; + + uint32_t nr_cpus; + + uint64_t page_offset; + uint64_t high_memory; + + uint64_t vmalloc_start; + uint64_t vmalloc_end; + + uint64_t modules_start; + uint64_t modules_end; + + uint64_t phys_offset; + uint64_t master_page_table; + + uint32_t output_fstype; + uint32_t output_lbaooo; +}; + +struct mrdump_control_block { + char sig[8]; + + struct mrdump_machdesc machdesc; + struct mrdump_crash_record crash_record; +}; + +/* NOTE!! any change to this struct should be compatible in aed */ +struct mrdump_mini_reg_desc { + unsigned long reg; /* register value */ + unsigned long kstart; /* start kernel addr of memory dump */ + unsigned long kend; /* end kernel addr of memory dump */ + unsigned long pos; /* next pos to dump */ + int valid; /* 1: valid regiser, 0: invalid regiser */ + int pad; /* reserved */ + loff_t offset; /* offset in buffer */ +}; + +/* it should always be smaller than MRDUMP_MINI_HEADER_SIZE */ +struct mrdump_mini_header { + struct mrdump_mini_reg_desc reg_desc[ELF_NGREG]; +}; + +#define MRDUMP_MINI_NR_SECTION 60 +#define MRDUMP_MINI_SECTION_SIZE (32 * 1024) +#define NT_IPANIC_MISC 4095 +#define MRDUMP_MINI_NR_MISC 20 + +struct mrdump_mini_elf_misc { + unsigned long vaddr; + unsigned long paddr; + unsigned long start; + unsigned long size; +}; + +#define NOTE_NAME_SHORT 12 +#define NOTE_NAME_LONG 20 + +struct mrdump_mini_elf_psinfo { + struct elf_note note; + char name[NOTE_NAME_SHORT]; + struct elf_prpsinfo data; +}; + +struct mrdump_mini_elf_prstatus { + struct elf_note note; + char name[NOTE_NAME_SHORT]; + struct elf_prstatus data; +}; + +struct mrdump_mini_elf_note { + struct elf_note note; + char name[NOTE_NAME_LONG]; + struct mrdump_mini_elf_misc data; +}; + +struct mrdump_mini_elf_header { + struct elfhdr ehdr; + struct elf_phdr phdrs[MRDUMP_MINI_NR_SECTION]; + struct mrdump_mini_elf_psinfo psinfo; + struct mrdump_mini_elf_prstatus prstatus[NR_CPUS + 1]; + struct mrdump_mini_elf_note misc[MRDUMP_MINI_NR_MISC]; +}; + +typedef struct mrdump_rsvmem_block { + phys_addr_t start_addr; + phys_addr_t size; +} mrdump_rsvmem_block_t; + + +#define MRDUMP_MINI_HEADER_SIZE ALIGN(sizeof(struct mrdump_mini_elf_header), PAGE_SIZE) +#define MRDUMP_MINI_DATA_SIZE (MRDUMP_MINI_NR_SECTION * MRDUMP_MINI_SECTION_SIZE) +#define MRDUMP_MINI_BUF_SIZE (MRDUMP_MINI_HEADER_SIZE + MRDUMP_MINI_DATA_SIZE) + +#ifdef CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR +#define MRDUMP_MINI_BUF_PADDR (CONFIG_MTK_RAM_CONSOLE_DRAM_ADDR + 0xf0000) +#else +#define MRDUMP_MINI_BUF_PADDR 0 +#endif + +int mrdump_init(void); +void __mrdump_create_oops_dump(AEE_REBOOT_MODE reboot_mode, struct pt_regs *regs, const char *msg, + ...); +#if defined(CONFIG_MTK_AEE_IPANIC) +void mrdump_rsvmem(void); +#else +static inline void mrdump_rsvmem(void) +{ +} +#endif + +#if defined(CONFIG_MTK_AEE_MRDUMP) +void aee_kdump_reboot(AEE_REBOOT_MODE, const char *msg, ...); +#else +static inline void aee_kdump_reboot(AEE_REBOOT_MODE reboot_mode, const char *msg, ...) +{ +} +#endif + +typedef int (*mrdump_write)(void *buf, int off, int len, int encrypt); +#if defined(CONFIG_MTK_AEE_IPANIC) +int mrdump_mini_create_oops_dump(AEE_REBOOT_MODE reboot_mode, mrdump_write write, + loff_t sd_offset, const char *msg, va_list ap); +void mrdump_mini_reserve_memory(void); +#else +static inline int mrdump_mini_create_oops_dump(AEE_REBOOT_MODE reboot_mode, mrdump_write write, + loff_t sd_offset, const char *msg, va_list ap) +{ + return 0; +} + +static inline void mrdump_mini_reserve_memory(void) +{ +} +#endif + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h b/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h new file mode 100644 index 0000000000000..1b60f007d0fdf --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt7622/include/mach/mtk_thermal.h @@ -0,0 +1,295 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MT8167_THERMAL_H +#define _MT8167_THERMAL_H + +#include +#include +#include +#include + +#include +#include + +#include "sync_write.h" + +extern void __iomem *thermal_base; +extern void __iomem *auxadc_ts_base; +extern void __iomem *apmixed_base; +extern void __iomem *pericfg_base; +extern int auxadc_ts_phy_base; +extern int apmixed_phy_base; + +#define THERM_CTRL_BASE_2 thermal_base +#define AUXADC_BASE_2 auxadc_ts_base +#define PERICFG_BASE pericfg_base +#define APMIXED_BASE_2 apmixed_base + +#define MT6752_EVB_BUILD_PASS /*Jerry fix build error FIX_ME*/ + +/******************************************************************************* +* AUXADC Register Definition +******************************************************************************/ +/*AUXADC_BASE: 0xF1001000 from Vincent Liang 2014.5.8*/ + +#define AUXADC_CON0_V (AUXADC_BASE_2 + 0x000) /*yes, 0x11003000*/ +#define AUXADC_CON1_V (AUXADC_BASE_2 + 0x004) +#define AUXADC_CON1_SET_V (AUXADC_BASE_2 + 0x008) +#define AUXADC_CON1_CLR_V (AUXADC_BASE_2 + 0x00C) +#define AUXADC_CON2_V (AUXADC_BASE_2 + 0x010) +/*#define AUXADC_CON3_V (AUXADC_BASE_2 + 0x014)*/ +#define AUXADC_DAT0_V (AUXADC_BASE_2 + 0x014) +#define AUXADC_DAT1_V (AUXADC_BASE_2 + 0x018) +#define AUXADC_DAT2_V (AUXADC_BASE_2 + 0x01C) +#define AUXADC_DAT3_V (AUXADC_BASE_2 + 0x020) +#define AUXADC_DAT4_V (AUXADC_BASE_2 + 0x024) +#define AUXADC_DAT5_V (AUXADC_BASE_2 + 0x028) +#define AUXADC_DAT6_V (AUXADC_BASE_2 + 0x02C) +#define AUXADC_DAT7_V (AUXADC_BASE_2 + 0x030) +#define AUXADC_DAT8_V (AUXADC_BASE_2 + 0x034) +#define AUXADC_DAT9_V (AUXADC_BASE_2 + 0x038) +#define AUXADC_DAT10_V (AUXADC_BASE_2 + 0x03C) +#define AUXADC_DAT11_V (AUXADC_BASE_2 + 0x040) +#define AUXADC_MISC_V (AUXADC_BASE_2 + 0x094) + +#define AUXADC_CON0_P (auxadc_ts_phy_base + 0x000) +#define AUXADC_CON1_P (auxadc_ts_phy_base + 0x004) +#define AUXADC_CON1_SET_P (auxadc_ts_phy_base + 0x008) +#define AUXADC_CON1_CLR_P (auxadc_ts_phy_base + 0x00C) +#define AUXADC_CON2_P (auxadc_ts_phy_base + 0x010) +/*#define AUXADC_CON3_P (auxadc_ts_phy_base + 0x014)*/ +#define AUXADC_DAT0_P (auxadc_ts_phy_base + 0x014) +#define AUXADC_DAT1_P (auxadc_ts_phy_base + 0x018) +#define AUXADC_DAT2_P (auxadc_ts_phy_base + 0x01C) +#define AUXADC_DAT3_P (auxadc_ts_phy_base + 0x020) +#define AUXADC_DAT4_P (auxadc_ts_phy_base + 0x024) +#define AUXADC_DAT5_P (auxadc_ts_phy_base + 0x028) +#define AUXADC_DAT6_P (auxadc_ts_phy_base + 0x02C) +#define AUXADC_DAT7_P (auxadc_ts_phy_base + 0x030) +#define AUXADC_DAT8_P (auxadc_ts_phy_base + 0x034) +#define AUXADC_DAT9_P (auxadc_ts_phy_base + 0x038) +#define AUXADC_DAT10_P (auxadc_ts_phy_base + 0x03C) +#define AUXADC_DAT11_P (auxadc_ts_phy_base + 0x040) + +#define AUXADC_MISC_P (auxadc_ts_phy_base + 0x094) + +/******************************************************************************* +* Peripheral Configuration Register Definition +******************************************************************************/ +/*#define PERICFG_BASE (0x10002000)*/ +#define PERI_GLOBALCON_RST0 (pericfg_base + 0x000) /*yes, 0x10002000*/ +/******************************************************************************* + * APMixedSys Configuration Register Definition + ******************************************************************************/ +#define TS_CON0 (APMIXED_BASE_2 + 0x600) /*yes 0x10209000*/ +#define TS_CON1 (APMIXED_BASE_2 + 0x604) +#define TS_CON0_TM (APMIXED_BASE_2 + 0x600) /* yes 0x10209000 */ +#define TS_CON1_TM (APMIXED_BASE_2 + 0x604) +#define TS_CON0_P (apmixed_phy_base + 0x600) +#define TS_CON1_P (apmixed_phy_base + 0x604) + +/******************************************************************************* + * Thermal Controller Register Definition + ******************************************************************************/ +#define TEMPMONCTL0 (THERM_CTRL_BASE_2 + 0x000) /*yes 0x1100B000*/ +#define TEMPMONCTL1 (THERM_CTRL_BASE_2 + 0x004) +#define TEMPMONCTL2 (THERM_CTRL_BASE_2 + 0x008) +#define TEMPMONINT (THERM_CTRL_BASE_2 + 0x00C) +#define TEMPMONINTSTS (THERM_CTRL_BASE_2 + 0x010) +#define TEMPMONIDET0 (THERM_CTRL_BASE_2 + 0x014) +#define TEMPMONIDET1 (THERM_CTRL_BASE_2 + 0x018) +#define TEMPMONIDET2 (THERM_CTRL_BASE_2 + 0x01C) +#define TEMPH2NTHRE (THERM_CTRL_BASE_2 + 0x024) +#define TEMPHTHRE (THERM_CTRL_BASE_2 + 0x028) +#define TEMPCTHRE (THERM_CTRL_BASE_2 + 0x02C) +#define TEMPOFFSETH (THERM_CTRL_BASE_2 + 0x030) +#define TEMPOFFSETL (THERM_CTRL_BASE_2 + 0x034) +#define TEMPMSRCTL0 (THERM_CTRL_BASE_2 + 0x038) +#define TEMPMSRCTL1 (THERM_CTRL_BASE_2 + 0x03C) +#define TEMPAHBPOLL (THERM_CTRL_BASE_2 + 0x040) +#define TEMPAHBTO (THERM_CTRL_BASE_2 + 0x044) +#define TEMPADCPNP0 (THERM_CTRL_BASE_2 + 0x048) +#define TEMPADCPNP1 (THERM_CTRL_BASE_2 + 0x04C) +#define TEMPADCPNP2 (THERM_CTRL_BASE_2 + 0x050) +#define TEMPADCPNP3 (THERM_CTRL_BASE_2 + 0x0B4) + +#define TEMPADCMUX (THERM_CTRL_BASE_2 + 0x054) +#define TEMPADCEXT (THERM_CTRL_BASE_2 + 0x058) +#define TEMPADCEXT1 (THERM_CTRL_BASE_2 + 0x05C) +#define TEMPADCEN (THERM_CTRL_BASE_2 + 0x060) +#define TEMPPNPMUXADDR (THERM_CTRL_BASE_2 + 0x064) +#define TEMPADCMUXADDR (THERM_CTRL_BASE_2 + 0x068) +#define TEMPADCEXTADDR (THERM_CTRL_BASE_2 + 0x06C) +#define TEMPADCEXT1ADDR (THERM_CTRL_BASE_2 + 0x070) +#define TEMPADCENADDR (THERM_CTRL_BASE_2 + 0x074) +#define TEMPADCVALIDADDR (THERM_CTRL_BASE_2 + 0x078) +#define TEMPADCVOLTADDR (THERM_CTRL_BASE_2 + 0x07C) +#define TEMPRDCTRL (THERM_CTRL_BASE_2 + 0x080) +#define TEMPADCVALIDMASK (THERM_CTRL_BASE_2 + 0x084) +#define TEMPADCVOLTAGESHIFT (THERM_CTRL_BASE_2 + 0x088) +#define TEMPADCWRITECTRL (THERM_CTRL_BASE_2 + 0x08C) +#define TEMPMSR0 (THERM_CTRL_BASE_2 + 0x090) +#define TEMPMSR1 (THERM_CTRL_BASE_2 + 0x094) +#define TEMPMSR2 (THERM_CTRL_BASE_2 + 0x098) +#define TEMPMSR3 (THERM_CTRL_BASE_2 + 0x0B8) + +#define TEMPIMMD0 (THERM_CTRL_BASE_2 + 0x0A0) +#define TEMPIMMD1 (THERM_CTRL_BASE_2 + 0x0A4) +#define TEMPIMMD2 (THERM_CTRL_BASE_2 + 0x0A8) +#define TEMPIMMD3 (THERM_CTRL_BASE_2 + 0x0BC) + + +#define TEMPPROTCTL (THERM_CTRL_BASE_2 + 0x0C0) +#define TEMPPROTTA (THERM_CTRL_BASE_2 + 0x0C4) +#define TEMPPROTTB (THERM_CTRL_BASE_2 + 0x0C8) +#define TEMPPROTTC (THERM_CTRL_BASE_2 + 0x0CC) + +#define TEMPSPARE0 (THERM_CTRL_BASE_2 + 0x0F0) +#define TEMPSPARE1 (THERM_CTRL_BASE_2 + 0x0F4) +#define TEMPSPARE2 (THERM_CTRL_BASE_2 + 0x0F8) +#define TEMPSPARE3 (THERM_CTRL_BASE_2 + 0x0FC) + +#define PTPCORESEL (THERM_CTRL_BASE_2 + 0x400) +#define THERMINTST (THERM_CTRL_BASE_2 + 0x404) +#define PTPODINTST (THERM_CTRL_BASE_2 + 0x408) +#define THSTAGE0ST (THERM_CTRL_BASE_2 + 0x40C) +#define THSTAGE1ST (THERM_CTRL_BASE_2 + 0x410) +#define THSTAGE2ST (THERM_CTRL_BASE_2 + 0x414) +#define THAHBST0 (THERM_CTRL_BASE_2 + 0x418) +#define THAHBST1 (THERM_CTRL_BASE_2 + 0x41C) /*Only for DE debug*/ +#define PTPSPARE0 (THERM_CTRL_BASE_2 + 0x420) +#define PTPSPARE1 (THERM_CTRL_BASE_2 + 0x424) +#define PTPSPARE2 (THERM_CTRL_BASE_2 + 0x428) +#define PTPSPARE3 (THERM_CTRL_BASE_2 + 0x42C) +#define THSLPEVEB (THERM_CTRL_BASE_2 + 0x430) + + +#define PTPSPARE0_P (thermal_phy_base + 0x420) +#define PTPSPARE1_P (thermal_phy_base + 0x424) +#define PTPSPARE2_P (thermal_phy_base + 0x428) +#define PTPSPARE3_P (thermal_phy_base + 0x42C) + +/******************************************************************************* + * Thermal Controller Register Mask Definition + ******************************************************************************/ +#define THERMAL_ENABLE_SEN0 0x1 +#define THERMAL_ENABLE_SEN1 0x2 +#define THERMAL_ENABLE_SEN2 0x4 +#define THERMAL_MONCTL0_MASK 0x00000007 + +#define THERMAL_PUNT_MASK 0x00000FFF +#define THERMAL_FSINTVL_MASK 0x03FF0000 +#define THERMAL_SPINTVL_MASK 0x000003FF +#define THERMAL_MON_INT_MASK 0x0007FFFF + +#define THERMAL_MON_CINTSTS0 0x000001 +#define THERMAL_MON_HINTSTS0 0x000002 +#define THERMAL_MON_LOINTSTS0 0x000004 +#define THERMAL_MON_HOINTSTS0 0x000008 +#define THERMAL_MON_NHINTSTS0 0x000010 +#define THERMAL_MON_CINTSTS1 0x000020 +#define THERMAL_MON_HINTSTS1 0x000040 +#define THERMAL_MON_LOINTSTS1 0x000080 +#define THERMAL_MON_HOINTSTS1 0x000100 +#define THERMAL_MON_NHINTSTS1 0x000200 +#define THERMAL_MON_CINTSTS2 0x000400 +#define THERMAL_MON_HINTSTS2 0x000800 +#define THERMAL_MON_LOINTSTS2 0x001000 +#define THERMAL_MON_HOINTSTS2 0x002000 +#define THERMAL_MON_NHINTSTS2 0x004000 +#define THERMAL_MON_TOINTSTS 0x008000 +#define THERMAL_MON_IMMDINTSTS0 0x010000 +#define THERMAL_MON_IMMDINTSTS1 0x020000 +#define THERMAL_MON_IMMDINTSTS2 0x040000 +#define THERMAL_MON_FILTINTSTS0 0x080000 +#define THERMAL_MON_FILTINTSTS1 0x100000 +#define THERMAL_MON_FILTINTSTS2 0x200000 + + +#define THERMAL_tri_SPM_State0 0x20000000 +#define THERMAL_tri_SPM_State1 0x40000000 +#define THERMAL_tri_SPM_State2 0x80000000 + + +#define THERMAL_MSRCTL0_MASK 0x00000007 +#define THERMAL_MSRCTL1_MASK 0x00000038 +#define THERMAL_MSRCTL2_MASK 0x000001C0 + +enum thermal_sensor_name { + THERMAL_SENSOR1 = 0,/*TS_MCU1*/ + THERMAL_SENSOR_NUM +}; + +enum thermal_bank_name { + THERMAL_BANK0 = 0, /*CPU (TS_MCU1) (TS1)*/ + THERMAL_BANK_NUM +}; + +struct TS_SVS { + unsigned int ts_MTS; + unsigned int ts_BTS; +}; + +struct mtk_gpu_power_info { + unsigned int gpufreq_khz; + unsigned int gpufreq_power; +}; + +/* svs driver need this function */ +extern void get_thermal_slope_intercept(struct TS_SVS *ts_info, enum thermal_bank_name ts_bank); + +/* mtk_thermal_platform.c need this */ +extern void set_taklking_flag(bool flag); + +#define THERMAL_WRAP_WR32(val, addr) mt_reg_sync_writel((val), ((void *)addr)) + +enum MTK_THERMAL_SENSOR_CPU_ID_MET { + MTK_THERMAL_SENSOR_TS1 = 0, + MTK_THERMAL_SENSOR_TS2, + MTK_THERMAL_SENSOR_TS3, + MTK_THERMAL_SENSOR_TS4, + MTK_THERMAL_SENSOR_TSABB, + + ATM_CPU_LIMIT, + ATM_GPU_LIMIT, + + MTK_THERMAL_SENSOR_CPU_COUNT +}; + +extern int tscpu_get_cpu_temp_met(enum MTK_THERMAL_SENSOR_CPU_ID_MET id); +extern int mtk_gpufreq_register(struct mtk_gpu_power_info *freqs, int num); + +typedef void (*met_thermalsampler_funcMET)(void); +void mt_thermalsampler_registerCB(met_thermalsampler_funcMET pCB); + +void tscpu_start_thermal(void); +void tscpu_stop_thermal(void); +void tscpu_cancel_thermal_timer(void); +void tscpu_start_thermal_timer(void); +int mtkts_bts_get_hw_temp(void); + +extern int get_immediate_ts1_wrap(void); +extern int get_immediate_ts2_wrap(void); +extern int get_immediate_ts3_wrap(void); + +extern int is_cpu_power_unlimit(void); /* in mtk_ts_cpu.c */ +extern int is_cpu_power_min(void); /* in mtk_ts_cpu.c */ +extern int get_cpu_target_tj(void); +extern int get_cpu_target_offset(void); + +extern int mtktscpu_debug_log; + +#endif + diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h new file mode 100644 index 0000000000000..142a007805b95 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_freqhopping.h @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2011 MediaTek, Inc. + * + * Author: Holmes Chiou + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 __MT_FREQHOPPING_H__ +#define __MT_FREQHOPPING_H__ + +#define MT_FHPLL_MAX 6 +#define MT_SSC_NR_PREDEFINE_SETTING 10 /* TODO: is 10 a good number ? */ + +#define MEMPLL_SSC 0 +#define MAINPLL_SSC 1 + +#define FHTAG "[FH]" + +#define VERBOSE_DEBUG 0 + +#if VERBOSE_DEBUG +#define FH_MSG(fmt, args...) \ + pr_debug(FHTAG""fmt" <- %s(): L<%d> PID<%s><%d>\n", ##args, __func__, __LINE__, current->comm, current->pid) +#else + +#if 1 /* log level is 6 xlog */ +#define FH_MSG(fmt, args...) pr_debug(fmt, ##args) +#else /* log level is 4 (printk) */ +#define FH_MSG(fmt, args...) printk(FHTAG""fmt"\n", ##args) +#endif + +#endif + +/* not support at mt2701 yet */ +/* DRAMC */ +#define FULLY_VERSION_FHCTL 0 + +enum FH_FH_STATUS { + FH_FH_DISABLE = 0, + FH_FH_ENABLE_SSC, + FH_FH_ENABLE_DFH, + FH_FH_ENABLE_DVFS, +}; + +enum FH_PLL_STATUS { + FH_PLL_DISABLE = 0, + FH_PLL_ENABLE = 1 +}; + +/* TODO: FREQ_MODIFIED should not be here */ +/* FH_PLL_STATUS_FREQ_MODIFIED = 3 */ + + +enum FH_CMD { + FH_CMD_ENABLE = 1, + FH_CMD_DISABLE, + FH_CMD_ENABLE_USR_DEFINED, + FH_CMD_DISABLE_USR_DEFINED, + FH_CMD_INTERNAL_MAX_CMD, +/* TODO: do we need these cmds ? + * FH_CMD_PLL_ENABLE, + * FH_CMD_PLL_DISABLE, + * FH_CMD_EXT_ALL_FULL_RANGE_CMD, + * FH_CMD_EXT_ALL_HALF_RANGE_CMD, + * FH_CMD_EXT_DISABLE_ALL_CMD, + * FH_CMD_EXT_DESIGNATED_PLL_FULL_RANGE_CMD, + * FH_CMD_EXT_DESIGNATED_PLL_AND_SETTING_CMD +*/ +}; + +/* + * enum FH_OPCODE{ + * FH_OPCODE_ENABLE_WITH_ID = 1, + * FH_OPCODE_ENABLE_WITHOUT_ID, + * FH_OPCODE_DISABLE, + * }; +*/ + +enum FH_PLL_ID { + MT658X_FH_MINIMUMM_PLL = 0, + MT658X_FH_ARM_PLL = MT658X_FH_MINIMUMM_PLL, + MT658X_FH_MAIN_PLL = 1, + MT658X_FH_MEM_PLL = 2, + MT658X_FH_MSDC_PLL = 3, + MT658X_FH_MM_PLL = 4, /* MT658X_FH_TVD_PLL = 4, */ + MT658X_FH_VENC_PLL = 5, /* MT658X_FH_LVDS_PLL = 5, */ + /* 8127 FHCTL MB */ + MT658X_FH_TVD_PLL = 6, /* MT658X_FH_TVD_PLL = 6, */ + MT658X_FH_MAXIMUMM_PLL = MT658X_FH_TVD_PLL, + /* 8127 FHCTL ME */ + MT658X_FH_PLL_TOTAL_NUM +}; + +/* keep track the status of each PLL */ +/* TODO: do we need another "uint mode" for Dynamic FH */ +typedef struct { + unsigned int fh_status; + unsigned int pll_status; + unsigned int setting_id; + unsigned int curr_freq; + unsigned int user_defined; +} fh_pll_t; + + +/* Record the owner of enable freq hopping <==TBD */ +struct freqhopping_pll { + union { + int mt_pll[MT_FHPLL_MAX]; + struct { + int mt_arm_fhpll; + int mt_main_fhpll; + int mt_mem_fhpll; + int mt_msdc_fhpll; + int mt_mm_fhpll; + int mt_venc_fhpll; + }; + }; +}; + +struct freqhopping_ssc { + unsigned int freq; + unsigned int dt; + unsigned int df; + unsigned int upbnd; + unsigned int lowbnd; + unsigned int dds; +}; + +struct freqhopping_ioctl { + unsigned int pll_id; + struct freqhopping_ssc ssc_setting; /* used only when user-define */ + int result; +}; + +int freqhopping_config(unsigned int pll_id, unsigned long vco_freq, unsigned int enable); +void mt_freqhopping_init(void); +void mt_freqhopping_pll_init(void); +int mt_h2l_mempll(void); +int mt_l2h_mempll(void); +int mt_h2l_dvfs_mempll(void); +int mt_l2h_dvfs_mempll(void); +int mt_dfs_armpll(unsigned int current_freq, unsigned int target_freq); +int mt_is_support_DFS_mode(void); +void mt_fh_popod_save(void); +void mt_fh_popod_restore(void); +int mt_fh_dram_overclock(int clk); +int mt_fh_get_dramc(void); +unsigned int mt_get_emi_freq(void); + +#endif /* !__MT_FREQHOPPING_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h new file mode 100644 index 0000000000000..0c049db9aa977 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mt_spm_mtcmos.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include + +#define STA_POWER_DOWN 0 +#define STA_POWER_ON 1 + +/* + * 1. for CPU MTCMOS: CPU0, CPU1, CPU2, CPU3, DBG0, CPU4, CPU5, CPU6, CPU7, DBG1, CPUSYS1 + * 2. call spm_mtcmos_cpu_lock/unlock() before/after any operations + */ +extern int spm_mtcmos_cpu_init(void); +extern void spm_mtcmos_cpu_lock(unsigned long *flags); +extern void spm_mtcmos_cpu_unlock(unsigned long *flags); +extern int spm_mtcmos_ctrl_cpu(unsigned int cpu, int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu0(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu1(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu2(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu3(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu4(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu5(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu6(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpu7(int state, int chkWfiBeforePdn); +extern int spm_mtcmos_ctrl_cpusys0(int state, int chkWfiBeforePdn); +extern bool spm_cpusys0_can_power_down(void); diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h new file mode 100644 index 0000000000000..28176b3cd9af1 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_boot_share_page.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 MediaTek Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __MTK_BOOT_SHARE_PAGE_H__ +#define __MTK_BOOT_SHARE_PAGE_H__ + +#define BOOT_SHARE_BASE (0xC0002000) /* address in linux kernel */ +#define BOOT_SHARE_SIZE (0x1000) /* page size 4K bytes */ + +#define BOOT_SHARE_MAGIC (0x4545544D) /* MTEE */ + +/* Memory map & defines for boot share page */ +/* + * Note: + * 1. BOOT_SHARE_XXXXX_OFST is the address offset related to BOOT_SHARE_BASE + */ +#define BOOT_SHARE_MAGIC1_OFST (0) +#define BOOT_SHARE_MAGIC1_SIZE (4) + +#define BOOT_SHARE_DEV_INFO_OFST (BOOT_SHARE_MAGIC1_OFST+BOOT_SHARE_MAGIC1_SIZE) +#define BOOT_SHARE_DEV_INFO_SIZE (16) + +#define BOOT_SHARE_HOTPLUG_OFST (1008) /* 16 bytes for hotplug/jump-reg */ +#define BOOT_SHARE_HOTPLUG_SIZE (32) + +#define BOOT_SHARE_MAGIC2_OFST (4092) +#define BOOT_SHARE_MAGIC2_SIZE (4) + +#endif /* __MTK_BOOT_SHARE_PAGE_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h new file mode 100644 index 0000000000000..eefdaad4aaa5d --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt8127/include/mach/mtk_thermal.h @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. + */ + +#ifndef _MT8127_THERMAL_H +#define _MT8127_THERMAL_H + +#include +#include +#include +#include + +#include +#include + +#include "mt-plat/sync_write.h" +#include + +/* #include */ +/* #include "../../../../../thermal/mt8127/inc/mt_gpufreq.h" */ + +#if 1 +extern void __iomem *thermal_base; +extern void __iomem *auxadc_ts_base; +extern void __iomem *pericfg_base; +extern void __iomem *apmixed_ts_base; + +extern int mtktscpu_limited_dmips; + +void __attribute__ ((weak)) mt_gpufreq_thermal_protect(unsigned int limited_power) { +} + +unsigned int __attribute__ ((weak)) mt_gpufreq_get_cur_freq(void) { + return 0; +} + +u32 __attribute__ ((weak)) get_devinfo_with_index(u32 index) { + return 0; +} + +extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int *rawdata); +extern int IMM_IsAdcInitReady(void); +extern int PMIC_IMM_GetOneChannelValue(int dwChannel, int deCount, int trimd); +extern int thermal_phy_base; +extern int auxadc_ts_phy_base; +extern int apmixed_phy_base; +extern int pericfg_phy_base; + +/* extern int last_abb_t; */ +/* extern int last_CPU2_t; */ +extern int get_immediate_temp2_wrap(void); +extern void mtkts_dump_cali_info(void); +extern u32 get_devinfo_with_index(u32 index); +extern int bts_cur_temp; + +#define THERM_CTRL_BASE_2 thermal_base +#define AUXADC_BASE_2 auxadc_ts_base +#define PERICFG_BASE_2 pericfg_base +#define APMIXED_BASE_2 apmixed_ts_base +#endif + +/******************************************************************************* + * AUXADC Register Definition + ******************************************************************************/ +#define AUXADC_CON0_V (AUXADC_BASE_2 + 0x000) /* yes, 0x11001000 */ +#define AUXADC_CON1_V (AUXADC_BASE_2 + 0x004) +#define AUXADC_CON1_SET_V (AUXADC_BASE_2 + 0x008) +#define AUXADC_CON1_CLR_V (AUXADC_BASE_2 + 0x00C) +#define AUXADC_CON2_V (AUXADC_BASE_2 + 0x010) +#define AUXADC_DAT0_V (AUXADC_BASE_2 + 0x014) +#define AUXADC_DAT1_V (AUXADC_BASE_2 + 0x018) +#define AUXADC_DAT2_V (AUXADC_BASE_2 + 0x01C) +#define AUXADC_DAT3_V (AUXADC_BASE_2 + 0x020) +#define AUXADC_DAT4_V (AUXADC_BASE_2 + 0x024) +#define AUXADC_DAT5_V (AUXADC_BASE_2 + 0x028) +#define AUXADC_DAT6_V (AUXADC_BASE_2 + 0x02C) +#define AUXADC_DAT7_V (AUXADC_BASE_2 + 0x030) +#define AUXADC_DAT8_V (AUXADC_BASE_2 + 0x034) +#define AUXADC_DAT9_V (AUXADC_BASE_2 + 0x038) +#define AUXADC_DAT10_V (AUXADC_BASE_2 + 0x03C) +#define AUXADC_DAT11_V (AUXADC_BASE_2 + 0x040) +#define AUXADC_MISC_V (AUXADC_BASE_2 + 0x094) +#define AUXADC_CON0_P (auxadc_ts_phy_base + 0x000) +#define AUXADC_CON1_P (auxadc_ts_phy_base + 0x004) +#define AUXADC_CON1_SET_P (auxadc_ts_phy_base + 0x008) +#define AUXADC_CON1_CLR_P (auxadc_ts_phy_base + 0x00C) +#define AUXADC_CON2_P (auxadc_ts_phy_base + 0x010) +#define AUXADC_DAT0_P (auxadc_ts_phy_base + 0x014) +#define AUXADC_DAT1_P (auxadc_ts_phy_base + 0x018) +#define AUXADC_DAT2_P (auxadc_ts_phy_base + 0x01C) +#define AUXADC_DAT3_P (auxadc_ts_phy_base + 0x020) +#define AUXADC_DAT4_P (auxadc_ts_phy_base + 0x024) +#define AUXADC_DAT5_P (auxadc_ts_phy_base + 0x028) +#define AUXADC_DAT6_P (auxadc_ts_phy_base + 0x02C) +#define AUXADC_DAT7_P (auxadc_ts_phy_base + 0x030) +#define AUXADC_DAT8_P (auxadc_ts_phy_base + 0x034) +#define AUXADC_DAT9_P (auxadc_ts_phy_base + 0x038) +#define AUXADC_DAT10_P (auxadc_ts_phy_base + 0x03C) +#define AUXADC_DAT11_P (auxadc_ts_phy_base + 0x040) +#define AUXADC_MISC_P (auxadc_ts_phy_base + 0x094) + +/******************************************************************************* + * Peripheral Configuration Register Definition + ******************************************************************************/ +#define PERI_GLOBALCON_RST0 (PERICFG_BASE_2 + 0x000) /* yes, 0x10003000 */ + +/******************************************************************************* + * APMixedSys Configuration Register Definition + ******************************************************************************/ +#define TS_CON0 (APMIXED_BASE_2 + 0x600) /* yes 0x10209000 */ +#define TS_CON1 (APMIXED_BASE_2 + 0x604) +/******************************************************************************* + * Thermal Controller Register Definition + ******************************************************************************/ +#define TEMPMONCTL0 (THERM_CTRL_BASE_2 + 0x000) /* yes 0x1100B000 */ +#define TEMPMONCTL1 (THERM_CTRL_BASE_2 + 0x004) +#define TEMPMONCTL2 (THERM_CTRL_BASE_2 + 0x008) +#define TEMPMONINT (THERM_CTRL_BASE_2 + 0x00C) +#define TEMPMONINTSTS (THERM_CTRL_BASE_2 + 0x010) +#define TEMPMONIDET0 (THERM_CTRL_BASE_2 + 0x014) +#define TEMPMONIDET1 (THERM_CTRL_BASE_2 + 0x018) +#define TEMPMONIDET2 (THERM_CTRL_BASE_2 + 0x01C) +#define TEMPH2NTHRE (THERM_CTRL_BASE_2 + 0x024) +#define TEMPHTHRE (THERM_CTRL_BASE_2 + 0x028) +#define TEMPCTHRE (THERM_CTRL_BASE_2 + 0x02C) +#define TEMPOFFSETH (THERM_CTRL_BASE_2 + 0x030) +#define TEMPOFFSETL (THERM_CTRL_BASE_2 + 0x034) +#define TEMPMSRCTL0 (THERM_CTRL_BASE_2 + 0x038) +#define TEMPMSRCTL1 (THERM_CTRL_BASE_2 + 0x03C) +#define TEMPAHBPOLL (THERM_CTRL_BASE_2 + 0x040) +#define TEMPAHBTO (THERM_CTRL_BASE_2 + 0x044) +#define TEMPADCPNP0 (THERM_CTRL_BASE_2 + 0x048) +#define TEMPADCPNP1 (THERM_CTRL_BASE_2 + 0x04C) +#define TEMPADCPNP2 (THERM_CTRL_BASE_2 + 0x050) +#define TEMPADCPNP3 (THERM_CTRL_BASE_2 + 0x0B4) + +#define TEMPADCMUX (THERM_CTRL_BASE_2 + 0x054) +#define TEMPADCEXT (THERM_CTRL_BASE_2 + 0x058) +#define TEMPADCEXT1 (THERM_CTRL_BASE_2 + 0x05C) +#define TEMPADCEN (THERM_CTRL_BASE_2 + 0x060) +#define TEMPPNPMUXADDR (THERM_CTRL_BASE_2 + 0x064) +#define TEMPADCMUXADDR (THERM_CTRL_BASE_2 + 0x068) +#define TEMPADCEXTADDR (THERM_CTRL_BASE_2 + 0x06C) +#define TEMPADCEXT1ADDR (THERM_CTRL_BASE_2 + 0x070) +#define TEMPADCENADDR (THERM_CTRL_BASE_2 + 0x074) +#define TEMPADCVALIDADDR (THERM_CTRL_BASE_2 + 0x078) +#define TEMPADCVOLTADDR (THERM_CTRL_BASE_2 + 0x07C) +#define TEMPRDCTRL (THERM_CTRL_BASE_2 + 0x080) +#define TEMPADCVALIDMASK (THERM_CTRL_BASE_2 + 0x084) +#define TEMPADCVOLTAGESHIFT (THERM_CTRL_BASE_2 + 0x088) +#define TEMPADCWRITECTRL (THERM_CTRL_BASE_2 + 0x08C) +#define TEMPMSR0 (THERM_CTRL_BASE_2 + 0x090) +#define TEMPMSR1 (THERM_CTRL_BASE_2 + 0x094) +#define TEMPMSR2 (THERM_CTRL_BASE_2 + 0x098) +#define TEMPMSR3 (THERM_CTRL_BASE_2 + 0x0B8) + +#define TEMPIMMD0 (THERM_CTRL_BASE_2 + 0x0A0) +#define TEMPIMMD1 (THERM_CTRL_BASE_2 + 0x0A4) +#define TEMPIMMD2 (THERM_CTRL_BASE_2 + 0x0A8) + +#define TEMPPROTCTL (THERM_CTRL_BASE_2 + 0x0C0) +#define TEMPPROTTA (THERM_CTRL_BASE_2 + 0x0C4) +#define TEMPPROTTB (THERM_CTRL_BASE_2 + 0x0C8) +#define TEMPPROTTC (THERM_CTRL_BASE_2 + 0x0CC) + +#define TEMPSPARE0 (THERM_CTRL_BASE_2 + 0x0F0) +#define TEMPSPARE1 (THERM_CTRL_BASE_2 + 0x0F4) +#define TEMPSPARE2 (THERM_CTRL_BASE_2 + 0x0F8) +#define TEMPSPARE3 (THERM_CTRL_BASE_2 + 0x0FC) + +#define PTPCORESEL (THERM_CTRL_BASE_2 + 0x400) +#define THERMINTST (THERM_CTRL_BASE_2 + 0x404) +#define PTPODINTST (THERM_CTRL_BASE_2 + 0x408) +#define THSTAGE0ST (THERM_CTRL_BASE_2 + 0x40C) +#define THSTAGE1ST (THERM_CTRL_BASE_2 + 0x410) +#define THSTAGE2ST (THERM_CTRL_BASE_2 + 0x414) +#define THAHBST0 (THERM_CTRL_BASE_2 + 0x418) +#define THAHBST1 (THERM_CTRL_BASE_2 + 0x41C) /* Only for DE debug */ +#define PTPSPARE0 (THERM_CTRL_BASE_2 + 0x420) +#define PTPSPARE1 (THERM_CTRL_BASE_2 + 0x424) +#define PTPSPARE2 (THERM_CTRL_BASE_2 + 0x428) +#define PTPSPARE3 (THERM_CTRL_BASE_2 + 0x42C) +#define THSLPEVEB (THERM_CTRL_BASE_2 + 0x430) + +/******************************************************************************* + * Thermal Controller Register Mask Definition + ******************************************************************************/ +#define THERMAL_ENABLE_SEN0 0x1 +#define THERMAL_ENABLE_SEN1 0x2 +#define THERMAL_ENABLE_SEN2 0x4 +#define THERMAL_MONCTL0_MASK 0x00000007 + +#define THERMAL_PUNT_MASK 0x00000FFF +#define THERMAL_FSINTVL_MASK 0x03FF0000 +#define THERMAL_SPINTVL_MASK 0x000003FF +#define THERMAL_MON_INT_MASK 0x0007FFFF + +#define THERMAL_MON_CINTSTS0 0x000001 +#define THERMAL_MON_HINTSTS0 0x000002 +#define THERMAL_MON_LOINTSTS0 0x000004 +#define THERMAL_MON_HOINTSTS0 0x000008 +#define THERMAL_MON_NHINTSTS0 0x000010 +#define THERMAL_MON_CINTSTS1 0x000020 +#define THERMAL_MON_HINTSTS1 0x000040 +#define THERMAL_MON_LOINTSTS1 0x000080 +#define THERMAL_MON_HOINTSTS1 0x000100 +#define THERMAL_MON_NHINTSTS1 0x000200 +#define THERMAL_MON_CINTSTS2 0x000400 +#define THERMAL_MON_HINTSTS2 0x000800 +#define THERMAL_MON_LOINTSTS2 0x001000 +#define THERMAL_MON_HOINTSTS2 0x002000 +#define THERMAL_MON_NHINTSTS2 0x004000 +#define THERMAL_MON_TOINTSTS 0x008000 +#define THERMAL_MON_IMMDINTSTS0 0x010000 +#define THERMAL_MON_IMMDINTSTS1 0x020000 +#define THERMAL_MON_IMMDINTSTS2 0x040000 +#define THERMAL_MON_FILTINTSTS0 0x080000 +#define THERMAL_MON_FILTINTSTS1 0x100000 +#define THERMAL_MON_FILTINTSTS2 0x200000 + + +#define THERMAL_tri_SPM_State0 0x20000000 +#define THERMAL_tri_SPM_State1 0x40000000 +#define THERMAL_tri_SPM_State2 0x80000000 + + +#define THERMAL_MSRCTL0_MASK 0x00000007 +#define THERMAL_MSRCTL1_MASK 0x00000038 +#define THERMAL_MSRCTL2_MASK 0x000001C0 + +/* extern int thermal_one_shot_handler(int times); */ + +typedef enum { + THERMAL_SENSOR1 = 0, /* TS1 */ + THERMAL_SENSOR_NUM +} thermal_sensor_name; + +struct TS_PTPOD { + unsigned int ts_MTS; + unsigned int ts_BTS; +}; + +extern void get_thermal_slope_intercept(struct TS_PTPOD *ts_info); +extern void set_taklking_flag(bool flag); +extern int tscpu_get_cpu_temp(void); + +/*5 thermal sensors*/ +typedef enum { + MTK_THERMAL_SENSOR_TS1 = 0, + ATM_CPU_LIMIT, + ATM_GPU_LIMIT, + MTK_THERMAL_SENSOR_CPU_COUNT +} MTK_THERMAL_SENSOR_CPU_ID_MET; + +struct mtk_cpu_power_info { + unsigned int cpufreq_khz; + unsigned int cpufreq_ncpu; + unsigned int cpufreq_power; +}; +extern int mtk_cpufreq_register(struct mtk_cpu_power_info *freqs, int num); + +extern int tscpu_get_cpu_temp_met(MTK_THERMAL_SENSOR_CPU_ID_MET id); + + +typedef void (*met_thermalsampler_funcMET) (void); +void mt_thermalsampler_registerCB(met_thermalsampler_funcMET pCB); + +void tscpu_start_thermal(void); +void tscpu_stop_thermal(void); +void tscpu_cancel_thermal_timer(void); +void tscpu_start_thermal_timer(void); +int mtkts_AP_get_hw_temp(void); + +extern int amddulthro_backoff(int level); +/* extern int IMM_GetOneChannelValue(int dwChannel, int data[4], int *rawdata); */ +/* extern int IMM_IsAdcInitReady(void); */ +extern int get_immediate_temp2_wrap(void); +extern void mtkts_dump_cali_info(void); +extern unsigned int read_dram_temperature(void); +extern int mtk_thermal_get_cpu_load_sum(void); + +/********************************** + * Power table struct for thermal + **********************************/ +struct mt_gpufreq_power_table_info { + unsigned int gpufreq_khz; + unsigned int gpufreq_volt; + unsigned int gpufreq_power; +}; + +extern int mtk_gpufreq_register(struct mt_gpufreq_power_table_info *freqs, int num); +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mt_sched.h b/drivers/misc/mediatek/include/mt-plat/mt_sched.h new file mode 100644 index 0000000000000..71206f0805482 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mt_sched.h @@ -0,0 +1,34 @@ +/* +* Copyright (C) 2016 MediaTek Inc. +* +* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details. +*/ + +#ifdef CONFIG_MTK_SCHED_RQAVG_US +/* + * @cpu: cpu id + * @reset: reset the statistic start time after this time query + * @use_maxfreq: caculate cpu loading with max cpu max frequency + * return: cpu loading as percentage (0~100) + */ +extern unsigned int sched_get_percpu_load(int cpu, bool reset, bool use_maxfreq); + +/* + * return: heavy task(loading>90%) number in the system + */ +extern unsigned int sched_get_nr_heavy_task(void); + +/* + * @threshold: heavy task loading threshold (0~1023) + * return: heavy task(loading>threshold) number in the system + */ +extern unsigned int sched_get_nr_heavy_task_by_threshold(unsigned int threshold); +#endif /* CONFIG_MTK_SCHED_RQAVG_US */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_io.h b/drivers/misc/mediatek/include/mt-plat/mtk_io.h new file mode 100644 index 0000000000000..de17db505d3e5 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_io.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __MT_IO_H__ +#define __MT_IO_H__ + +/* only for arm64 */ +#ifdef CONFIG_ARM64 +#define IOMEM(a) ((void __force __iomem *)((a))) +#endif + +#endif /* !__MT_IO_H__ */ + diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h b/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h new file mode 100644 index 0000000000000..d679c5a1ce738 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_lpae.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * 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 __MTK_LPAE_H__ +#define __MTK_LPAE_H__ +#ifdef CONFIG_MTK_LM_MODE + +#include + +#define INTERAL_MAPPING_OFFSET (0x40000000) +#define INTERAL_MAPPING_LIMIT (INTERAL_MAPPING_OFFSET + 0x80000000) + +#define MT_OVERFLOW_ADDR_START 0x100000000ULL + +unsigned int __attribute__((weak)) enable_4G(void) +{ + return 0; +} + +/* For HW modules which support 33-bit address setting */ +#define CROSS_OVERFLOW_ADDR_TRANSFER(phy_addr, size, ret) \ + do { \ + ret = 0; \ + if (enable_4G()) {\ + if (((phys_addr_t)phy_addr < MT_OVERFLOW_ADDR_START)\ + && (((phys_addr_t)phy_addr + size) >= MT_OVERFLOW_ADDR_START)) \ + ret = MT_OVERFLOW_ADDR_START - phy_addr; \ + } \ + } while (0) \ + +/* For SPM and MD32 only in ROME */ +#define MAPPING_DRAM_ACCESS_ADDR(phy_addr) \ + do { \ + if (enable_4G()) {\ + if (phy_addr >= INTERAL_MAPPING_OFFSET && phy_addr < INTERAL_MAPPING_LIMIT) \ + phy_addr += INTERAL_MAPPING_OFFSET; \ + } \ + } while (0)\ + +#else /* !CONFIG_ARM_LPAE */ + +#define CROSS_OVERFLOW_ADDR_TRANSFER(phy_addr, size, ret) +#define MAPPING_DRAM_ACCESS_ADDR(phy_addr) +#define MT_OVERFLOW_ADDR_START 0 + +static inline unsigned int enable_4G(void) +{ + return 0; +} + +#endif +#endif /*!__MTK_LPAE_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h b/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h new file mode 100644 index 0000000000000..7baafc4329bfc --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_mdm_monitor.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MTK_MDM_MONITOR_H +#define _MTK_MDM_MONITOR_H + +struct md_info { + char *attribute; + int value; + char *unit; + int invalid_value; + int index; +}; + +extern +int mtk_mdm_get_md_info(struct md_info **p_inf, int *size); + +extern +int mtk_mdm_start_query(void); + +extern +int mtk_mdm_stop_query(void); + +extern +int mtk_mdm_set_signal_period(int second); + +extern +int mtk_mdm_set_md1_signal_period(int second); + +extern +int mtk_mdm_set_md2_signal_period(int second); +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h b/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h new file mode 100644 index 0000000000000..8f20f38b75d6c --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_platform_debug.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2016 MediaTek Inc. + * + * 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 __MTK_PLATFORM_DEBUG_H__ +#define __MTK_PLATFORM_DEBUG_H__ + +#ifdef CONFIG_MTK_PLAT_SRAM_FLAG +/* plat_sram_flag */ +extern int set_sram_flag_lastpc_valid(void); +extern int set_sram_flag_dfd_valid(void); +extern int set_sram_flag_etb_user(unsigned int etb_id, unsigned int user_id); +#endif + +#ifdef CONFIG_MTK_DFD_INTERNAL_DUMP +extern int dfd_setup(void); +#endif + +#endif /* __MTK_PLATFORM_DEBUG_H__ */ diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h b/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h new file mode 100644 index 0000000000000..3a94a1bbcd241 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_ram_console.h @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __MTK_RAM_CONSOLE_H__ +#define __MTK_RAM_CONSOLE_H__ + +#include +#include + +typedef enum { + AEE_FIQ_STEP_FIQ_ISR_BASE = 1, + AEE_FIQ_STEP_WDT_FIQ_INFO = 4, + AEE_FIQ_STEP_WDT_FIQ_STACK, + AEE_FIQ_STEP_WDT_FIQ_LOOP, + AEE_FIQ_STEP_WDT_FIQ_DONE, + AEE_FIQ_STEP_WDT_IRQ_INFO = 8, + AEE_FIQ_STEP_WDT_IRQ_KICK, + AEE_FIQ_STEP_WDT_IRQ_SMP_STOP, + AEE_FIQ_STEP_WDT_IRQ_TIME, + AEE_FIQ_STEP_WDT_IRQ_STACK, + AEE_FIQ_STEP_WDT_IRQ_GIC, + AEE_FIQ_STEP_WDT_IRQ_LOCALTIMER, + AEE_FIQ_STEP_WDT_IRQ_IDLE, + AEE_FIQ_STEP_WDT_IRQ_SCHED, + AEE_FIQ_STEP_WDT_IRQ_DONE, + AEE_FIQ_STEP_KE_WDT_INFO = 20, + AEE_FIQ_STEP_KE_WDT_PERCPU, + AEE_FIQ_STEP_KE_WDT_LOG, + AEE_FIQ_STEP_KE_SCHED_DEBUG, + AEE_FIQ_STEP_KE_EINT_DEBUG, + AEE_FIQ_STEP_KE_WDT_DONE, + AEE_FIQ_STEP_KE_IPANIC_DIE = 32, + AEE_FIQ_STEP_KE_IPANIC_START, + AEE_FIQ_STEP_KE_IPANIC_OOP_HEADER, + AEE_FIQ_STEP_KE_IPANIC_DETAIL, + AEE_FIQ_STEP_KE_IPANIC_CONSOLE, + AEE_FIQ_STEP_KE_IPANIC_USERSPACE, + AEE_FIQ_STEP_KE_IPANIC_ANDROID, + AEE_FIQ_STEP_KE_IPANIC_MMPROFILE, + AEE_FIQ_STEP_KE_IPANIC_HEADER, + AEE_FIQ_STEP_KE_IPANIC_DONE, + AEE_FIQ_STEP_KE_NESTED_PANIC = 64, +} AEE_FIQ_STEP_NUM; + +#ifdef CONFIG_MTK_RAM_CONSOLE +extern int aee_rr_curr_fiq_step(void); +extern void aee_rr_rec_fiq_step(u8 i); +extern void aee_rr_rec_reboot_mode(u8 mode); +extern void aee_rr_rec_kdump_params(void *params); +extern void aee_rr_rec_last_irq_enter(int cpu, int irq, u64 j); +extern void aee_rr_rec_last_irq_exit(int cpu, int irq, u64 j); +extern void aee_rr_rec_last_sched_jiffies(int cpu, u64 j, const char *comm); +extern void aee_sram_fiq_log(const char *msg); +extern void ram_console_write(struct console *console, const char *s, unsigned int count); +extern void aee_sram_fiq_save_bin(const char *buffer, size_t len); +extern void aee_rr_rec_hotplug_footprint(int cpu, u8 fp); +extern void aee_rr_rec_hotplug_cpu_event(u8 val); +extern void aee_rr_rec_hotplug_cb_index(u8 val); +extern void aee_rr_rec_hotplug_cb_fp(unsigned long val); +#ifdef CONFIG_MTK_EMMC_SUPPORT +extern void last_kmsg_store_to_emmc(void); +#endif + +#else +static inline void aee_rr_rec_hotplug_footprint(int cpu, u8 fp) +{ +} +static inline void aee_rr_rec_hotplug_cpu_event(u8 val) +{ +} +static inline void aee_rr_rec_hotplug_cb_index(u8 val) +{ +} +static inline void aee_rr_rec_hotplug_cb_fp(unsigned long val) +{ +} +static inline int aee_rr_curr_fiq_step(void) +{ + return 0; +} + +static inline void aee_rr_rec_fiq_step(u8 i) +{ +} + +static inline unsigned int aee_rr_curr_exp_type(void) +{ + return 0; +} + +static inline void aee_rr_rec_exp_type(unsigned int type) +{ +} + +static inline void aee_rr_rec_reboot_mode(u8 mode) +{ +} + +static inline void aee_rr_rec_kdump_params(void *params) +{ +} + +static inline void aee_rr_rec_last_irq_enter(int cpu, int irq, u64 j) +{ +} + +static inline void aee_rr_rec_last_irq_exit(int cpu, int irq, u64 j) +{ +} + +static inline void aee_rr_rec_last_sched_jiffies(int cpu, u64 j, const char *comm) +{ +} + +static inline void aee_sram_fiq_log(const char *msg) +{ +} + +static inline void ram_console_write(struct console *console, const char *s, unsigned int count) +{ +} + +static inline void aee_sram_fiq_save_bin(unsigned char *buffer, size_t len) +{ +} + +#ifdef CONFIG_MTK_EMMC_SUPPORT +static inline void last_kmsg_store_to_emmc(void) +{ +} +#endif + +#endif /* CONFIG_MTK_RAM_CONSOLE */ + +#ifdef CONFIG_MTK_AEE_IPANIC +extern int ipanic_kmsg_write(unsigned int part, const char *buf, size_t size); +extern int ipanic_kmsg_get_next(int *count, u64 *id, enum pstore_type_id *type, struct timespec *time, + char **buf, struct pstore_info *psi); +#else +static inline int ipanic_kmsg_write(unsigned int part, const char *buf, size_t size) +{ + return 0; +} + +static inline int ipanic_kmsg_get_next(int *count, u64 *id, enum pstore_type_id *type, struct timespec *time, + char **buf, struct pstore_info *psi) +{ + return 0; +} +#endif /* CONFIG_MTK_AEE_IPANIC */ + +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h b/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h new file mode 100644 index 0000000000000..2181e99895934 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_rtc.h @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 MTK_RTC_H +#define MTK_RTC_H + +#include +#include +#include + +typedef enum { + RTC_GPIO_USER_WIFI = 8, + RTC_GPIO_USER_GPS = 9, + RTC_GPIO_USER_BT = 10, + RTC_GPIO_USER_FM = 11, + RTC_GPIO_USER_PMIC = 12, +} rtc_gpio_user_t; + +#ifdef CONFIG_MTK_RTC + +/* + * NOTE: + * 1. RTC_GPIO always exports 32K enabled by some user even if the phone is powered off + */ + +extern unsigned long rtc_read_hw_time(void); +extern void rtc_gpio_enable_32k(rtc_gpio_user_t user); +extern void rtc_gpio_disable_32k(rtc_gpio_user_t user); +extern bool rtc_gpio_32k_status(void); + +/* for AUDIOPLL (deprecated) */ +extern void rtc_enable_abb_32k(void); +extern void rtc_disable_abb_32k(void); + +/* NOTE: used in Sleep driver to workaround Vrtc-Vore level shifter issue */ +extern void rtc_enable_writeif(void); +extern void rtc_disable_writeif(void); + +extern void rtc_mark_recovery(void); +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) +extern void rtc_mark_kpoc(void); +#endif/*if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)*/ +extern void rtc_mark_fast(void); +extern u16 rtc_rdwr_uart_bits(u16 *val); +extern void rtc_bbpu_power_down(void); +extern void rtc_read_pwron_alarm(struct rtc_wkalrm *alm); +extern int get_rtc_spare_fg_value(void); +extern int set_rtc_spare_fg_value(int val); +extern void rtc_irq_handler(void); +extern bool crystal_exist_status(void); +extern void mt_power_off(void); +#else/*ifdef CONFIG_MTK_RTC*/ +#define rtc_read_hw_time() ({ 0; }) +#define rtc_gpio_enable_32k(user) do {} while (0) +#define rtc_gpio_disable_32k(user) do {} while (0) +#define rtc_gpio_32k_status() do {} while (0) +#define rtc_enable_abb_32k() do {} while (0) +#define rtc_disable_abb_32k() do {} while (0) +#define rtc_enable_writeif() do {} while (0) +#define rtc_disable_writeif() do {} while (0) +#define rtc_mark_recovery() do {} while (0) +#if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING) +#define rtc_mark_kpoc() do {} while (0) +#endif/*if defined(CONFIG_MTK_KERNEL_POWER_OFF_CHARGING)*/ +#define rtc_mark_fast() do {} while (0) +#define rtc_rdwr_uart_bits(val) ({ 0; }) +#define rtc_bbpu_power_down() do {} while (0) +#define rtc_read_pwron_alarm(alm) do {} while (0) +#define get_rtc_spare_fg_value() ({ 0; }) +#define set_rtc_spare_fg_value(val) ({ 0; }) +#define rtc_irq_handler() do {} while (0) +#define crystal_exist_status() do {} while (0) +__weak void mt_power_off(void); +#endif/*ifdef CONFIG_MTK_RTC*/ +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h new file mode 100644 index 0000000000000..eac6bc713c985 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_ext_control.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009 Travis Geiselbrecht + * + * 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. + */ + +#ifndef _MTK_THERMAL_EXT_CONTROL_H +#define _MTK_THERMAL_EXT_CONTROL_H + +#define THERMAL_MD32_IPI_MSG_BASE 0x1F00 +#define THERMAL_AP_IPI_MSG_BASE 0x2F00 + +typedef enum { + THERMAL_AP_IPI_MSG_SET_TZ_THRESHOLD = THERMAL_AP_IPI_MSG_BASE, + THERMAL_AP_IPI_MSG_MD32_START, + + THERMAL_MD32_IPI_MSG_READY = THERMAL_MD32_IPI_MSG_BASE, + THERMAL_MD32_IPI_MSG_MD32_START_ACK, + THERMAL_MD32_IPI_MSG_REACH_THRESHOLD, +} thermal_ipi_msg_id; + +typedef enum { +/* MTK_THERMAL_EXT_SENSOR_CPU = 0, */ + MTK_THERMAL_EXT_SENSOR_ABB = 0, + MTK_THERMAL_EXT_SENSOR_PMIC, + MTK_THERMAL_EXT_SENSOR_BATTERY, + MTK_THERMAL_EXT_SENSOR_COUNT +} MTK_THERMAL_EXT_SENSOR_ID; + +typedef struct { + int id; /* id of this tz */ + int polling_delay; /* polling delay of this tz */ + long high_trip_point; /* high threshold of this tz */ + long low_trip_point; /* low threshold of this tz */ +} thermal_zone_data; + +typedef struct { + int id; /* id of this tz */ + long high_trip_point; /* high threshold of this tz */ + long low_trip_point; /* low threshold of this tz */ + long temperature; /* Current temperature gotten from TS */ +} thermal_zone_status; + +typedef struct { + short id; + union { + thermal_zone_data tz; + thermal_zone_status tz_status; + } data; +} thermal_ipi_msg; + +#endif /* _MTK_THERMAL_EXT_CONTROL_H */ diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h new file mode 100644 index 0000000000000..7903b49dc419c --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_monitor.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MTK_THERMAL_MONITOR_H +#define _MTK_THERMAL_MONITOR_H + +#include + +/* + * MTK_THERMAL_WRAPPER_BYPASS = 1 (use original Linux Thermal API) + * MTK_THERMAL_WRAPPER_BYPASS = 0 (use MTK Thermal API Monitor) + */ +#define MTK_THERMAL_WRAPPER_BYPASS 0 + +#if MTK_THERMAL_WRAPPER_BYPASS +/* Original LTF API */ +#define mtk_thermal_zone_device_register thermal_zone_device_register +#define mtk_thermal_zone_device_unregister thermal_zone_device_unregister +#define mtk_thermal_cooling_device_unregister thermal_cooling_device_unregister +#define mtk_thermal_cooling_device_register thermal_cooling_device_register +#define mtk_thermal_zone_bind_cooling_device thermal_zone_bind_cooling_device + +#else + +struct thermal_cooling_device_ops_extra { + int (*set_cur_temp)(struct thermal_cooling_device *, unsigned long); +}; + +extern +struct thermal_zone_device *mtk_thermal_zone_device_register_wrapper +(char *type, int trips, void *devdata, const struct thermal_zone_device_ops *ops, +int tc1, int tc2, int passive_delay, int polling_delay); + +extern +void mtk_thermal_zone_device_unregister_wrapper(struct thermal_zone_device *tz); + +extern +struct thermal_cooling_device *mtk_thermal_cooling_device_register_wrapper +(char *type, void *devdata, const struct thermal_cooling_device_ops *ops); + +extern +struct thermal_cooling_device *mtk_thermal_cooling_device_register_wrapper_extra +(char *type, void *devdata, const struct thermal_cooling_device_ops *ops, +const struct thermal_cooling_device_ops_extra *ops_ext); + +extern +int mtk_thermal_cooling_device_add_exit_point +(struct thermal_cooling_device *cdev, int exit_point); + +extern +void mtk_thermal_cooling_device_unregister_wrapper(struct thermal_cooling_device *cdev); + +extern int mtk_thermal_zone_bind_cooling_device_wrapper +(struct thermal_zone_device *tz, int trip, struct thermal_cooling_device *cdev); + +extern int mtk_thermal_zone_bind_trigger_trip(struct thermal_zone_device *tz, int trip, int mode); +#define mtk_thermal_zone_device_register mtk_thermal_zone_device_register_wrapper +#define mtk_thermal_zone_device_unregister mtk_thermal_zone_device_unregister_wrapper +#define mtk_thermal_cooling_device_unregister mtk_thermal_cooling_device_unregister_wrapper +#define mtk_thermal_cooling_device_register mtk_thermal_cooling_device_register_wrapper +#define mtk_thermal_zone_bind_cooling_device mtk_thermal_zone_bind_cooling_device_wrapper + +#endif + +typedef enum { + MTK_THERMAL_SENSOR_CPU = 0, + MTK_THERMAL_SENSOR_ABB, + MTK_THERMAL_SENSOR_PMIC, + MTK_THERMAL_SENSOR_BATTERY, + MTK_THERMAL_SENSOR_MD1, + MTK_THERMAL_SENSOR_MD2, + MTK_THERMAL_SENSOR_WIFI, + MTK_THERMAL_SENSOR_BATTERY2, + MTK_THERMAL_SENSOR_BUCK, + MTK_THERMAL_SENSOR_AP, + MTK_THERMAL_SENSOR_PCB1, + MTK_THERMAL_SENSOR_PCB2, + MTK_THERMAL_SENSOR_SKIN, + MTK_THERMAL_SENSOR_XTAL, + MTK_THERMAL_SENSOR_MD_PA, + + MTK_THERMAL_SENSOR_COUNT +} MTK_THERMAL_SENSOR_ID; + +extern int mtk_thermal_get_temp(MTK_THERMAL_SENSOR_ID id); +extern struct proc_dir_entry *mtk_thermal_get_proc_drv_therm_dir_entry(void); + +/* This API function is implemented in mediatek/kernel/drivers/leds/leds.c */ +extern int setMaxbrightness(int max_level, int enable); + +extern void machine_power_off(void); +#endif diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h new file mode 100644 index 0000000000000..305574031196a --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_platform.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MTK_THERMAL_PLATFORM_H +#define _MTK_THERMAL_PLATFORM_H + +#include +#include + +extern +int mtk_thermal_get_cpu_info(int *nocores, int **cpufreq, int **cpuloading); + +extern +int mtk_thermal_get_gpu_info(int *nocores, int **gpufreq, int **gpuloading); + +extern +int mtk_thermal_get_batt_info(int *batt_voltage, int *batt_current, int *batt_temp); + +extern +int mtk_thermal_get_extra_info(int *no_extra_attr, + char ***attr_names, int **attr_values, char ***attr_unit); + +extern +int mtk_thermal_force_get_batt_temp(void); + + +enum { + MTK_THERMAL_SCEN_CALL = 0x1 +}; + +extern +unsigned int mtk_thermal_set_user_scenarios(unsigned int mask); + +extern +unsigned int mtk_thermal_clear_user_scenarios(unsigned int mask); + + +#if defined(CONFIG_MTK_SMART_BATTERY) +/* global variable from battery driver... */ +extern kal_bool gFG_Is_Charging; +#endif + +extern int force_get_tbat(void); +#endif /* _MTK_THERMAL_PLATFORM_H */ + + +typedef enum { + TA_DAEMON_CMD_GET_INIT_FLAG = 0, + TA_DAEMON_CMD_SET_DAEMON_PID, + TA_DAEMON_CMD_NOTIFY_DAEMON, + TA_DAEMON_CMD_NOTIFY_DAEMON_CATMINIT, + TA_DAEMON_CMD_SET_TTJ, + TA_DAEMON_CMD_GET_TPCB, + + TA_DAEMON_CMD_TO_KERNEL_NUMBER +} TA_DAEMON_CTRL_CMD_TO_KERNEL; /*must sync userspace/kernel: TA_DAEMON_CTRL_CMD_FROM_USER*/ + +#define TAD_NL_MSG_T_HDR_LEN 12 +#define TAD_NL_MSG_MAX_LEN 2048 + +struct tad_nl_msg_t { + unsigned int tad_cmd; + unsigned int tad_data_len; + unsigned int tad_ret_data_len; + char tad_data[TAD_NL_MSG_MAX_LEN]; +}; + +enum { + TA_CATMPLUS = 1, + TA_CONTINUOUS = 2, + TA_CATMPLUS_TTJ = 3 +}; + + +struct cATM_params_t { + int CATM_ON; + int K_TT; + int K_SUM_TT_LOW; + int K_SUM_TT_HIGH; + int MIN_SUM_TT; + int MAX_SUM_TT; + int MIN_TTJ; + int CATMP_STEADY_TTJ_DELTA; +}; +struct continuetm_params_t { + int STEADY_TARGET_TJ; + int MAX_TARGET_TJ; + int TRIP_TPCB; + int STEADY_TARGET_TPCB; +}; + + +struct CATM_T { + struct cATM_params_t t_catm_par; + struct continuetm_params_t t_continuetm_par; +}; +extern struct CATM_T thermal_atm_t; +int wakeup_ta_algo(int flow_state); +int ta_get_ttj(void); + +extern int mtk_thermal_get_tpcb_target(void); +extern int tsatm_thermal_get_catm_type(void); + + diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h new file mode 100644 index 0000000000000..1c23a9f4a862e --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_trace.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM thermal + +#if !defined(_MTK_THERMAL_TRACE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _MTK_THERMAL_TRACE_H + +#include + +TRACE_EVENT(cooling_device_state, + TP_PROTO(int device, unsigned long state), + TP_ARGS(device, state), TP_STRUCT__entry(__field(int, device) + __field(unsigned long, state) + ), + TP_fast_assign(__entry->device = device; + __entry->state = state;), + TP_printk("cooling_device=%d, state=%lu\n", __entry->device, __entry->state) +); + +TRACE_EVENT(thermal_zone_state, + TP_PROTO(int device, int state), + TP_ARGS(device, state), TP_STRUCT__entry(__field(int, device) + __field(int, state) + ), + TP_fast_assign(__entry->device = device; + __entry->state = state;), + TP_printk("thermal_zone=%d, state=%d\n", __entry->device, __entry->state) +); +#endif /* _MTK_THERMAL_TRACE_H */ + +/* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE mach/mtk_thermal_trace +#include diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h new file mode 100644 index 0000000000000..dfcef3d952fc7 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_thermal_typedefs.h @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _TYPEDEFS_H +#define _TYPEDEFS_H + +#include + +/* --------------------------------------------------------------------------- */ +/* Basic Type Definitions */ +/* --------------------------------------------------------------------------- */ + +typedef volatile unsigned char *P_kal_uint8; +typedef volatile unsigned short *P_kal_uint16; +typedef volatile unsigned int *P_kal_uint32; + +typedef long LONG; +typedef unsigned char UBYTE; +typedef short SHORT; + +typedef signed char kal_int8; +typedef signed short kal_int16; +typedef signed int kal_int32; +typedef long long kal_int64; +typedef unsigned char kal_uint8; +typedef unsigned short kal_uint16; +typedef unsigned int kal_uint32; +typedef unsigned long long kal_uint64; +typedef char kal_char; + +typedef unsigned int *UINT32P; +typedef volatile unsigned short *UINT16P; +typedef volatile unsigned char *UINT8P; +typedef unsigned char *U8P; + +typedef volatile unsigned char *P_U8; +typedef volatile signed char *P_S8; +typedef volatile unsigned short *P_U16; +typedef volatile signed short *P_S16; +typedef volatile unsigned int *P_U32; +typedef volatile signed int *P_S32; +typedef unsigned long long *P_U64; +typedef signed long long *P_S64; + +typedef unsigned char U8; +typedef signed char S8; +typedef unsigned short U16; +typedef signed short S16; +typedef unsigned int U32; +typedef signed int S32; +typedef unsigned long long U64; +typedef signed long long S64; +/* typedef unsigned char bool; */ + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned short USHORT; +typedef signed char INT8; +typedef signed short INT16; +typedef signed int INT32; +typedef unsigned int DWORD; +typedef void VOID; +typedef unsigned char BYTE; +typedef float FLOAT; + +typedef char *LPCSTR; +typedef short *LPWSTR; + + +/* --------------------------------------------------------------------------- */ +/* Constants */ +/* --------------------------------------------------------------------------- */ + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef NULL +#define NULL (0) +#endif + +/* enum boolean {false, true}; */ +enum { RX, TX, NONE }; + +#ifndef BOOL +typedef unsigned char BOOL; +#endif + +#ifndef BATTERY_BOOL +#define BATTERY_BOOL +typedef enum { + KAL_FALSE = 0, + KAL_TRUE = 1, +} kal_bool; +#endif + +/* --------------------------------------------------------------------------- */ +/* Type Casting */ +/* --------------------------------------------------------------------------- */ + +#define AS_INT32(x) (*(INT32 *)((void *)x)) +#define AS_INT16(x) (*(INT16 *)((void *)x)) +#define AS_INT8(x) (*(INT8 *)((void *)x)) + +#define AS_UINT32(x) (*(UINT32 *)((void *)x)) +#define AS_UINT16(x) (*(UINT16 *)((void *)x)) +#define AS_UINT8(x) (*(UINT8 *)((void *)x)) + + +/* --------------------------------------------------------------------------- */ +/* Register Manipulations */ +/* --------------------------------------------------------------------------- */ + +#define READ_REGISTER_UINT32(reg) \ + (*(volatile UINT32 * const)(reg)) + +#define WRITE_REGISTER_UINT32(reg, val) \ + ((*(volatile UINT32 * const)(reg)) = (val)) + +#define READ_REGISTER_UINT16(reg) \ + ((*(volatile UINT16 * const)(reg))) + +#define WRITE_REGISTER_UINT16(reg, val) \ + ((*(volatile UINT16 * const)(reg)) = (val)) + +#define READ_REGISTER_UINT8(reg) \ + ((*(volatile UINT8 * const)(reg))) + +#define WRITE_REGISTER_UINT8(reg, val) \ + ((*(volatile UINT8 * const)(reg)) = (val)) + +#define INREG8(x) READ_REGISTER_UINT8((UINT8 *)((void *)(x))) +#define OUTREG8(x, y) WRITE_REGISTER_UINT8((UINT8 *)((void *)(x)), (UINT8)(y)) +#define SETREG8(x, y) OUTREG8(x, INREG8(x)|(y)) +#define CLRREG8(x, y) OUTREG8(x, INREG8(x)&~(y)) +#define MASKREG8(x, y, z) OUTREG8(x, (INREG8(x)&~(y))|(z)) + +#define INREG16(x) READ_REGISTER_UINT16((UINT16 *)((void *)(x))) +#define OUTREG16(x, y) WRITE_REGISTER_UINT16((UINT16 *)((void *)(x)), (UINT16)(y)) +#define SETREG16(x, y) OUTREG16(x, INREG16(x)|(y)) +#define CLRREG16(x, y) OUTREG16(x, INREG16(x)&~(y)) +#define MASKREG16(x, y, z) OUTREG16(x, (INREG16(x)&~(y))|(z)) + +#define INREG32(x) READ_REGISTER_UINT32((UINT32 *)((void *)(x))) +#define OUTREG32(x, y) WRITE_REGISTER_UINT32((UINT32 *)((void *)(x)), (UINT32)(y)) +#define SETREG32(x, y) OUTREG32(x, INREG32(x)|(y)) +#define CLRREG32(x, y) OUTREG32(x, INREG32(x)&~(y)) +#define MASKREG32(x, y, z) OUTREG32(x, (INREG32(x)&~(y))|(z)) + + +#define DRV_Reg8(addr) INREG8(addr) +#define DRV_WriteReg8(addr, data) OUTREG8(addr, data) +#define DRV_SetReg8(addr, data) SETREG8(addr, data) +#define DRV_ClrReg8(addr, data) CLRREG8(addr, data) + +#define DRV_Reg16(addr) INREG16(addr) +#define DRV_WriteReg16(addr, data) OUTREG16(addr, data) +#define DRV_SetReg16(addr, data) SETREG16(addr, data) +#define DRV_ClrReg16(addr, data) CLRREG16(addr, data) + +#define DRV_Reg32(addr) INREG32(addr) +#define DRV_WriteReg32(addr, data) OUTREG32(addr, data) +#define DRV_SetReg32(addr, data) SETREG32(addr, data) +#define DRV_ClrReg32(addr, data) CLRREG32(addr, data) + +/* !!! DEPRECATED, WILL BE REMOVED LATER !!! */ +#define DRV_Reg(addr) DRV_Reg16(addr) +#define DRV_WriteReg(addr, data) DRV_WriteReg16(addr, data) +#define DRV_SetReg(addr, data) DRV_SetReg16(addr, data) +#define DRV_ClrReg(addr, data) DRV_ClrReg16(addr, data) + + +/* --------------------------------------------------------------------------- */ +/* Compiler Time Deduction Macros */ +/* --------------------------------------------------------------------------- */ + + + +/* --------------------------------------------------------------------------- */ +/* Assertions */ +/* --------------------------------------------------------------------------- */ + +/* +*#ifndef ASSERT +*#define ASSERT(expr) BUG_ON(!(expr)) +*#endif +* +*#ifndef NOT_IMPLEMENTED +*#define NOT_IMPLEMENTED() BUG_ON(1) +*#endif +*/ +#define STATIC_ASSERT(pred) STATIC_ASSERT_X(pred, __LINE__) +#define STATIC_ASSERT_X(pred, line) STATIC_ASSERT_XX(pred, line) +#define STATIC_ASSERT_XX(pred, line) \ +extern char assertion_failed_at_##line[(pred) ? 1 : -1] + +/* --------------------------------------------------------------------------- */ +/* Resolve Compiler Warnings */ +/* --------------------------------------------------------------------------- */ + +#define NOT_REFERENCED(x) { (x) = (x); } + + +/* --------------------------------------------------------------------------- */ +/* Utilities */ +/* --------------------------------------------------------------------------- */ + +#define MAXIMUM(A, B) (((A) > (B))?(A):(B)) +#define MINIMUM(A, B) (((A) < (B))?(A):(B)) + +#define ARY_SIZE(x) (sizeof((x)) / sizeof((x[0]))) +#define DVT_DELAYMACRO(u4Num) \ +{ \ + UINT32 u4Count = 0; \ + for (u4Count = 0; u4Count < u4Num; u4Count++) \ + ; \ +} \ + +#define A68351B 0 +#define B68351B 1 +#define B68351D 2 +#define B68351E 3 +#define UNKNOWN_IC_VERSION 0xFF + + +#endif /* _TYPEDEFS_H */ diff --git a/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h b/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h new file mode 100644 index 0000000000000..0a4fda1916540 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/mtk_wcn_cmb_stub.h @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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. + */ + +/*! \file + * \brief Declaration of library functions + * + * Any definitions in this file will be shared among GLUE Layer and internal Driver Stack. +*/ + +#ifndef _MTK_WCN_CMB_STUB_H_ +#define _MTK_WCN_CMB_STUB_H_ + +#include + +/******************************************************************************* +* C O M P I L E R F L A G S +******************************************************************************** +*/ + +/******************************************************************************* +* M A C R O S +******************************************************************************** +*/ +/* Audio GPIO naming style for 73/75/77 */ +/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_0 1 */ +/* Audio GPIO naming style for 89/8135 */ +/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_1 1 */ +/* Audio GPIO naming style for 6592 */ +/* #define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_2 1 */ +/* Audio GPIO naming style for 6595 */ +#define MTK_WCN_CMB_AUD_IO_NAMING_STYLE_3 1 +#define MTK_WCN_CMB_FOR_SDIO_1V_AUTOK 1 + +/******************************************************************************* +* E X T E R N A L R E F E R E N C E S +******************************************************************************** +*/ + +/******************************************************************************* +* C O N S T A N T S +******************************************************************************** +*/ + +/******************************************************************************* +* D A T A T Y P E S +******************************************************************************** +*/ +typedef enum { + CMB_STUB_AIF_0 = 0, /* 0000: BT_PCM_OFF & FM analog (line in/out) */ + CMB_STUB_AIF_1 = 1, /* 0001: BT_PCM_ON & FM analog (in/out) */ + CMB_STUB_AIF_2 = 2, /* 0010: BT_PCM_OFF & FM digital (I2S) */ + CMB_STUB_AIF_3 = 3, /* 0011: BT_PCM_ON & FM digital (I2S) (invalid in 73evb & 1.2 phone configuration) */ + CMB_STUB_AIF_4 = 4, /* 0100: BT_I2S & FM disable in special projects, e.g. protea*/ + CMB_STUB_AIF_MAX = 5, +} CMB_STUB_AIF_X; + +/*COMBO_CHIP_AUDIO_PIN_CTRL*/ +typedef enum { + CMB_STUB_AIF_CTRL_DIS = 0, + CMB_STUB_AIF_CTRL_EN = 1, + CMB_STUB_AIF_CTRL_MAX = 2, +} CMB_STUB_AIF_CTRL; + +typedef enum { + COMBO_FUNC_TYPE_BT = 0, + COMBO_FUNC_TYPE_FM = 1, + COMBO_FUNC_TYPE_GPS = 2, + COMBO_FUNC_TYPE_WIFI = 3, + COMBO_FUNC_TYPE_WMT = 4, + COMBO_FUNC_TYPE_STP = 5, + COMBO_FUNC_TYPE_NUM = 6 +} COMBO_FUNC_TYPE; + +typedef enum { + COMBO_IF_UART = 0, + COMBO_IF_MSDC = 1, + COMBO_IF_BTIF = 2, + COMBO_IF_MAX, +} COMBO_IF; + +typedef void (*wmt_bgf_eirq_cb) (void); +typedef int (*wmt_aif_ctrl_cb) (CMB_STUB_AIF_X, CMB_STUB_AIF_CTRL); +typedef void (*wmt_func_ctrl_cb) (unsigned int, unsigned int); +typedef signed long (*wmt_thermal_query_cb) (void); +typedef int (*wmt_deep_idle_ctrl_cb) (unsigned int); +typedef int (*wmt_func_do_reset) (unsigned int); + +/* for DVFS driver do 1v autok */ +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +typedef unsigned int (*wmt_get_drv_status)(unsigned int); +#endif + +typedef void (*msdc_sdio_irq_handler_t) (void *); /* external irq handler */ +typedef void (*pm_callback_t) (pm_message_t state, void *data); + +struct sdio_ops { + void (*sdio_request_eirq)(msdc_sdio_irq_handler_t irq_handler, void *data); + void (*sdio_enable_eirq)(void); + void (*sdio_disable_eirq)(void); + void (*sdio_register_pm)(pm_callback_t pm_cb, void *data); +}; + +typedef struct _CMB_STUB_CB_ { + unsigned int size; /* structure size */ + /*wmt_bgf_eirq_cb bgf_eirq_cb; *//* remove bgf_eirq_cb from stub. handle it in platform */ + wmt_aif_ctrl_cb aif_ctrl_cb; + wmt_func_ctrl_cb func_ctrl_cb; + wmt_thermal_query_cb thermal_query_cb; + wmt_deep_idle_ctrl_cb deep_idle_ctrl_cb; + wmt_func_do_reset wmt_do_reset_cb; +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK + wmt_get_drv_status get_drv_status_cb; +#endif +} CMB_STUB_CB, *P_CMB_STUB_CB; + +/******************************************************************************* +* P U B L I C D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* P R I V A T E D A T A +******************************************************************************** +*/ + +/******************************************************************************* +* F U N C T I O N D E C L A R A T I O N S +******************************************************************************** +*/ + +extern struct sdio_ops mt_sdio_ops[4]; + +extern int mtk_wcn_cmb_stub_reg(P_CMB_STUB_CB p_stub_cb); +extern int mtk_wcn_cmb_stub_unreg(void); + +extern int mtk_wcn_cmb_stub_aif_ctrl(CMB_STUB_AIF_X state, CMB_STUB_AIF_CTRL ctrl); + +static inline int mtk_wcn_cmb_stub_audio_ctrl(CMB_STUB_AIF_X state) +{ +/* return mtk_wcn_cmb_stub_aif_ctrl(state, 1); */ + return 0; +} + +extern int mt_combo_plt_enter_deep_idle(COMBO_IF src); +extern int mt_combo_plt_exit_deep_idle(COMBO_IF src); + +/* Use new mtk_wcn_stub APIs instead of old mt_combo ones for kernel to control + * function on/off. + */ +extern void mtk_wcn_cmb_stub_func_ctrl(unsigned int type, unsigned int on); +extern int mtk_wcn_cmb_stub_query_ctrl(void); +extern int board_sdio_ctrl(unsigned int sdio_port_num, unsigned int on); +extern int mtk_wcn_sdio_irq_flag_set(int falg); + +#if MTK_WCN_CMB_FOR_SDIO_1V_AUTOK +extern int mtk_wcn_cmb_stub_1vautok_for_dvfs(void); +#endif + +extern int mtk_wcn_wmt_chipid_query(void); +extern void mtk_wcn_wmt_set_chipid(int chipid); + +/* mtk_uart_pdn_enable -- request uart port enter/exit deep idle mode, this API is defined in uart driver + * + * @ port - uart port name, Eg: "ttyMT0", "ttyMT1", "ttyMT2" + * @ enable - "1", enable deep idle; "0", disable deep idle + * + * Return 0 if success, else -1 + */ +extern unsigned int mtk_uart_pdn_enable(char *port, int enable); +/******************************************************************************* +* F U N C T I O N S +******************************************************************************** +*/ + +#endif /* _MTK_WCN_CMB_STUB_H_ */ diff --git a/drivers/misc/mediatek/include/mt-plat/rt-regmap.h b/drivers/misc/mediatek/include/mt-plat/rt-regmap.h new file mode 100644 index 0000000000000..9a45e23005cad --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/rt-regmap.h @@ -0,0 +1,291 @@ +/* drivers/misc/mediatek/include/mt-plat/rt-regmap.h + * Header of Richtek regmap with debugfs Driver + * + * Copyright (C) 2014 Richtek Technology Corp. + * Jeff Chang + * + * 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. + */ + +#ifndef MISC_MEDIATEK_RT_REGMAP_H +#define MISC_MEDIATEK_RT_REGMAP_H + +#include +#include + +/* #define RT_REGMAP_VERSION "1.1.11_G" */ + +enum rt_access_mode { + RT_1BYTE_MODE = 1, + RT_2BYTE_MODE = 2, + RT_4BYTE_MODE = 4, +}; + +/* start : the start address of group + * end : the end address of group + * mode : access mode (1,2,4 bytes) + */ +struct rt_access_group { + u32 start; + u32 end; + enum rt_access_mode mode; +}; + +/* rt_reg_type + * RT_NORMAL : Write data without mask + * Read from cache + * RT_WBITS : Write data with mask + * Read from cache + * RT_VOLATILE : Write data to chip directly + * Read data from chip + * RT_RESERVE : Reserve registers (Write/Read as RT_NORMAL) + */ + +#define RT_REG_TYPE_MASK (0x03) +#define RT_NORMAL (0x00) +#define RT_WBITS (0x01) +#define RT_VOLATILE (0x02) +#define RT_RESERVE (0x03) + +/* RT_WR_ONCE : write once will check write data and cache data, + * if write data = cache data, data will not be writen. + */ +#define RT_WR_ONCE (0x08) +#define RT_NORMAL_WR_ONCE (RT_NORMAL|RT_WR_ONCE) +#define RT_WBITS_WR_ONCE (RT_WBITS|RT_WR_ONCE) + +enum rt_data_format { + RT_LITTLE_ENDIAN, + RT_BIG_ENDIAN, +}; + +/* rt_regmap_mode + * 0 0 0 0 0 0 0 0 + * | | | | | | + * | | | |__| byte_mode + * | |__| || + * | || Cache_mode + * | Block_mode + * Debug_mode + */ + +#define RT_BYTE_MODE_MASK (0x01) +/* 1 byte for each register*/ +#define RT_SINGLE_BYTE (0 << 0) +/* multi bytes for each regiseter*/ +#define RT_MULTI_BYTE (1 << 0) + +#define RT_CACHE_MODE_MASK (0x06) +/* write to cache and chip synchronously */ +#define RT_CACHE_WR_THROUGH (0 << 1) +/* write to cache and chip asynchronously */ +#define RT_CACHE_WR_BACK (1 << 1) +/* disable cache */ +#define RT_CACHE_DISABLE (2 << 1) + +#define RT_IO_BLK_MODE_MASK (0x18) +/* pass through all write function */ +#define RT_IO_PASS_THROUGH (0 << 3) +/* block all write function */ +#define RT_IO_BLK_ALL (1 << 3) +/* block cache write function */ +#define RT_IO_BLK_CACHE (2 << 3) +/* block chip write function */ +#define RT_IO_BLK_CHIP (3 << 3) + +#define DBG_MODE_MASK (0x20) +/* create general debugfs for register map */ +#define RT_DBG_GENERAL (0 << 5) +/* create node for each regisetr map by register address*/ +#define RT_DBG_SPECIAL (1 << 5) + + +/* struct rt_register + * + * Ricktek register map structure for store mapping data + * @addr: register address. + * @name: register name. + * @size: register byte size. + * @reg_type: register R/W type ( RT_NORMAL, RT_WBITS, RT_VOLATILE, RT_RESERVE) + * @wbit_mask: register writeable bits mask; + * @cache_data: cache data for store cache value. + */ +struct rt_register { + u32 addr; + const char *name; + unsigned int size; + unsigned char reg_type; + unsigned char *wbit_mask; + unsigned char *cache_data; +}; + +/* Declare a rt_register by RT_REG_DECL + * @_addr: regisetr address. + * @_reg_length: register data length. + * @_reg_type: register type (rt_reg_type). + * @_mask: register writealbe mask. + */ +#define RT_REG_DECL(_addr, _reg_length, _reg_type, _mask_...) \ + static unsigned char rt_writable_mask_##_addr[_reg_length] = _mask_;\ + static struct rt_register rt_register_##_addr = { \ + .addr = _addr, \ + .size = _reg_length,\ + .reg_type = _reg_type,\ + .wbit_mask = rt_writable_mask_##_addr,\ + } + +/* Declare a rt_register by RT_NAMED_REG_DECL + * @_name: a name for a rt_register. + */ +#define RT_NAMED_REG_DECL(_addr, _name, _reg_length, _reg_type, _mask_...) \ + static unsigned char rt_writable_mask_##_addr[_reg_length] = _mask_;\ + static struct rt_register rt_register_##_addr = { \ + .addr = _addr, \ + .name = _name, \ + .size = _reg_length,\ + .reg_type = _reg_type,\ + .wbit_mask = rt_writable_mask_##_addr,\ + } + +#define RT_REG(_addr) (&rt_register_##_addr) + +/* rt_regmap_properties + * @name: the name of debug node. + * @aliases: alisis name of rt_regmap_device. + * @register_num: the number of rt_register_map registers. + * @rm: rt_regiseter_map pointer array. + * @group: register map access group. + * @rt_format: default is little endian. + * @rt_regmap_mode: rt_regmap_device mode. + * @io_log_en: enable/disable io log + */ +struct rt_regmap_properties { + const char *name; + const char *aliases; + int register_num; + struct rt_register **rm; + struct rt_access_group *group; + enum rt_data_format rt_format; + unsigned char rt_regmap_mode; + unsigned char io_log_en:1; +}; + +/* A passing struct for rt_regmap_reg_read and rt_regmap_reg_write function + * reg: regmap addr. + * mask: mask for update bits. + * rt_data: register value. + */ +struct rt_reg_data { + u32 reg; + u32 mask; + union { + u32 data_u32; + u16 data_u16; + u8 data_u8; + u8 data[4]; + } rt_data; +}; + +struct rt_regmap_device; + +struct rt_debug_st { + void *info; + int id; +}; + +/* basic chip read/write function */ +struct rt_regmap_fops { + int (*read_device)(void *client, u32 addr, int leng, void *dst); + int (*write_device)(void *client, u32 addr, int leng, const void *src); +}; + +/* with slave address */ +extern struct rt_regmap_device* + rt_regmap_device_register_ex(struct rt_regmap_properties *props, + struct rt_regmap_fops *rops, + struct device *parent, + void *client, int slv_addr, void *drvdata); + +static inline struct rt_regmap_device* + rt_regmap_device_register(struct rt_regmap_properties *props, + struct rt_regmap_fops *rops, + struct device *parent, + struct i2c_client *client, void *drvdata) +{ + return rt_regmap_device_register_ex(props, rops, parent, + client, client->addr, drvdata); +} + +extern void rt_regmap_device_unregister(struct rt_regmap_device *rd); + +extern int rt_regmap_cache_init(struct rt_regmap_device *rd); + +extern int rt_regmap_cache_reload(struct rt_regmap_device *rd); + +extern int rt_regmap_block_write(struct rt_regmap_device *rd, u32 reg, + int bytes, const void *rc); +extern int rt_asyn_regmap_block_write(struct rt_regmap_device *rd, u32 reg, + int bytes, const void *rc); +extern int rt_regmap_block_read(struct rt_regmap_device *rd, u32 reg, + int bytes, void *dst); + +extern int _rt_regmap_reg_read(struct rt_regmap_device *rd, + struct rt_reg_data *rrd); +extern int _rt_regmap_reg_write(struct rt_regmap_device *rd, + struct rt_reg_data *rrd); +extern int _rt_asyn_regmap_reg_write(struct rt_regmap_device *rd, + struct rt_reg_data *rrd); +extern int _rt_regmap_update_bits(struct rt_regmap_device *rd, + struct rt_reg_data *rrd); + +static inline int rt_regmap_reg_read(struct rt_regmap_device *rd, + struct rt_reg_data *rrd, u32 reg) +{ + rrd->reg = reg; + return _rt_regmap_reg_read(rd, rrd); +}; + +static inline int rt_regmap_reg_write(struct rt_regmap_device *rd, + struct rt_reg_data *rrd, u32 reg, const u32 data) +{ + rrd->reg = reg; + rrd->rt_data.data_u32 = data; + return _rt_regmap_reg_write(rd, rrd); +}; + +static inline int rt_asyn_regmap_reg_write(struct rt_regmap_device *rd, + struct rt_reg_data *rrd, u32 reg, const u32 data) +{ + rrd->reg = reg; + rrd->rt_data.data_u32 = data; + return _rt_asyn_regmap_reg_write(rd, rrd); +}; + +static inline int rt_regmap_update_bits(struct rt_regmap_device *rd, + struct rt_reg_data *rrd, u32 reg, u32 mask, u32 data) +{ + rrd->reg = reg; + rrd->mask = mask; + rrd->rt_data.data_u32 = data; + return _rt_regmap_update_bits(rd, rrd); +} + +extern void rt_regmap_cache_backup(struct rt_regmap_device *rd); + +extern void rt_regmap_cache_sync(struct rt_regmap_device *rd); +extern void rt_regmap_cache_write_back(struct rt_regmap_device *rd, u32 reg); + +extern int rt_is_reg_readable(struct rt_regmap_device *rd, u32 reg); +extern int rt_is_reg_volatile(struct rt_regmap_device *rd, u32 reg); +extern int rt_get_regsize(struct rt_regmap_device *rd, u32 reg); +extern void rt_cache_getlasterror(struct rt_regmap_device *rd, char *buf); +extern void rt_cache_clrlasterror(struct rt_regmap_device *rd); + +extern int rt_regmap_add_debugfs(struct rt_regmap_device *rd, const char *name, + umode_t mode, void *data, const struct file_operations *fops); + +#define to_rt_regmap_device(obj) container_of(obj, struct rt_regmap_device, dev) + +#endif /*MISC_MEDIATEK_RT_REGMAP_H*/ diff --git a/drivers/misc/mediatek/include/mt-plat/sync_write.h b/drivers/misc/mediatek/include/mt-plat/sync_write.h new file mode 100644 index 0000000000000..f9e5fe4c23e17 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/sync_write.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 _MT_SYNC_WRITE_H +#define _MT_SYNC_WRITE_H + +#if defined(__KERNEL__) + +#include +#include + +/* + * Define macros. + */ +#define mt_reg_sync_writel(v, a) \ + do { \ + __raw_writel((v), (void __force __iomem *)((a))); \ + mb(); \ + } while (0) + +#define mt_reg_sync_writew(v, a) \ + do { \ + __raw_writew((v), (void __force __iomem *)((a))); \ + mb(); \ + } while (0) + +#define mt_reg_sync_writeb(v, a) \ + do { \ + __raw_writeb((v), (void __force __iomem *)((a))); \ + mb(); \ + } while (0) + +#ifdef CONFIG_64BIT +#define mt_reg_sync_writeq(v, a) \ + do { \ + __raw_writeq((v), (void __force __iomem *)((a))); \ + mb(); \ + } while (0) +#endif + +#else /* __KERNEL__ */ + +#include +#include +#include +#include +#include + +#define mt_reg_sync_writel(v, a) mt65xx_reg_sync_writel(v, a) +#define mt_reg_sync_writew(v, a) mt65xx_reg_sync_writew(v, a) +#define mt_reg_sync_writeb(v, a) mt65xx_reg_sync_writeb(v, a) + +#define mb() \ + { \ + __asm__ __volatile__ ("dsb" : : : "memory"); \ + } + +#define mt65xx_reg_sync_writel(v, a) \ + do { \ + *(volatile unsigned int *)(a) = (v); \ + mb(); \ + } while (0) + +#define mt65xx_reg_sync_writew(v, a) \ + do { \ + *(volatile unsigned short *)(a) = (v); \ + mb(); \ + } while (0) + +#define mt65xx_reg_sync_writeb(v, a) \ + do { \ + *(volatile unsigned char *)(a) = (v); \ + mb(); \ + } while (0) + +#endif /* __KERNEL__ */ + +#endif /* !_MT_SYNC_WRITE_H */ diff --git a/drivers/misc/mediatek/include/mt-plat/wakelock.h b/drivers/misc/mediatek/include/mt-plat/wakelock.h new file mode 100644 index 0000000000000..f4a698a228803 --- /dev/null +++ b/drivers/misc/mediatek/include/mt-plat/wakelock.h @@ -0,0 +1,67 @@ +/* include/linux/wakelock.h + * + * Copyright (C) 2007-2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _LINUX_WAKELOCK_H +#define _LINUX_WAKELOCK_H + +#include +#include + +/* A wake_lock prevents the system from entering suspend or other low power + * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock + * prevents a full system suspend. + */ + +enum { + WAKE_LOCK_SUSPEND, /* Prevent suspend */ + WAKE_LOCK_TYPE_COUNT +}; + +struct wake_lock { + struct wakeup_source ws; +}; + +static inline void wake_lock_init(struct wake_lock *lock, int type, + const char *name) +{ + wakeup_source_init(&lock->ws, name); +} + +static inline void wake_lock_destroy(struct wake_lock *lock) +{ + wakeup_source_trash(&lock->ws); +} + +static inline void wake_lock(struct wake_lock *lock) +{ + __pm_stay_awake(&lock->ws); +} + +static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) +{ + __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout)); +} + +static inline void wake_unlock(struct wake_lock *lock) +{ + __pm_relax(&lock->ws); +} + +static inline int wake_lock_active(struct wake_lock *lock) +{ + return lock->ws.active; +} + +#endif diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index e9e054a15b7d2..014f9878998fa 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -1453,6 +1453,22 @@ static const struct of_device_id of_pwrap_match_tbl[] = { }; MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); +struct regmap *pwrap_node_to_regmap(struct device_node *np) +{ + struct platform_device *pdev; + struct pmic_wrapper *wrp; + + pdev = of_find_device_by_node(np); + + if (!pdev) + return ERR_PTR(-ENODEV); + + wrp = platform_get_drvdata(pdev); + + return wrp->regmap; +} +EXPORT_SYMBOL_GPL(pwrap_node_to_regmap); + static int pwrap_probe(struct platform_device *pdev) { int ret, irq; diff --git a/include/linux/soc/mediatek/pmic_wrap.h b/include/linux/soc/mediatek/pmic_wrap.h new file mode 100644 index 0000000000000..5b5c85272c58b --- /dev/null +++ b/include/linux/soc/mediatek/pmic_wrap.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2015 MediaTek Inc. + * + * 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 __SOC_MEDIATEK_PMIC_WRAP_H +#define __SOC_MEDIATEK_PMIC_WRAP_H + +extern struct regmap *pwrap_node_to_regmap(struct device_node *np); + +#endif /* __SOC_MEDIATEK_PMIC_WRAP_H */ diff --git a/include/linux/wakelock.h b/include/linux/wakelock.h new file mode 100644 index 0000000000000..f4a698a228803 --- /dev/null +++ b/include/linux/wakelock.h @@ -0,0 +1,67 @@ +/* include/linux/wakelock.h + * + * Copyright (C) 2007-2012 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 _LINUX_WAKELOCK_H +#define _LINUX_WAKELOCK_H + +#include +#include + +/* A wake_lock prevents the system from entering suspend or other low power + * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock + * prevents a full system suspend. + */ + +enum { + WAKE_LOCK_SUSPEND, /* Prevent suspend */ + WAKE_LOCK_TYPE_COUNT +}; + +struct wake_lock { + struct wakeup_source ws; +}; + +static inline void wake_lock_init(struct wake_lock *lock, int type, + const char *name) +{ + wakeup_source_init(&lock->ws, name); +} + +static inline void wake_lock_destroy(struct wake_lock *lock) +{ + wakeup_source_trash(&lock->ws); +} + +static inline void wake_lock(struct wake_lock *lock) +{ + __pm_stay_awake(&lock->ws); +} + +static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) +{ + __pm_wakeup_event(&lock->ws, jiffies_to_msecs(timeout)); +} + +static inline void wake_unlock(struct wake_lock *lock) +{ + __pm_relax(&lock->ws); +} + +static inline int wake_lock_active(struct wake_lock *lock) +{ + return lock->ws.active; +} + +#endif diff --git a/include/net/genetlink.h b/include/net/genetlink.h index decf6012a4016..51f501528c7c2 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -144,6 +144,52 @@ struct genl_ops { }; int genl_register_family(struct genl_family *family); + +/** + * genl_register_family_with_ops - register a generic netlink family with ops + * @family: generic netlink family + * @ops: operations to be registered + * @n_ops: number of elements to register + * + * Registers the specified family and operations from the specified table. + * Only one family may be registered with the same family name or identifier. + * + * The family id may equal GENL_ID_GENERATE causing an unique id to + * be automatically generated and assigned. + * + * Either a doit or dumpit callback must be specified for every registered + * operation or the function will fail. Only one operation structure per + * command identifier may be registered. + * + * See include/net/genetlink.h for more documenation on the operations + * structure. + * + * Return 0 on success or a negative error code. + */ +static inline int +_genl_register_family_with_ops_grps(struct genl_family *family, + const struct genl_ops *ops, size_t n_ops, + const struct genl_multicast_group *mcgrps, + size_t n_mcgrps) +{ + family->module = THIS_MODULE; + family->ops = ops; + family->n_ops = n_ops; + family->mcgrps = mcgrps; + family->n_mcgrps = n_mcgrps; + return genl_register_family(family); +} + +#define genl_register_family_with_ops(family, ops) \ + _genl_register_family_with_ops_grps((family), \ + (ops), ARRAY_SIZE(ops), \ + NULL, 0) +#define genl_register_family_with_ops_groups(family, ops, grps) \ + _genl_register_family_with_ops_grps((family), \ + (ops), ARRAY_SIZE(ops), \ + (grps), ARRAY_SIZE(grps)) + + int genl_unregister_family(const struct genl_family *family); void genl_notify(const struct genl_family *family, struct sk_buff *skb, struct genl_info *info, u32 group, gfp_t flags); diff --git a/include/uapi/linux/genetlink.h b/include/uapi/linux/genetlink.h index 877f7fa954666..62fb239d99076 100644 --- a/include/uapi/linux/genetlink.h +++ b/include/uapi/linux/genetlink.h @@ -28,6 +28,7 @@ struct genlmsghdr { * List of reserved static generic netlink identifiers: */ #define GENL_ID_CTRL NLMSG_MIN_TYPE +#define GENL_ID_GENERATE 0 #define GENL_ID_VFS_DQUOT (NLMSG_MIN_TYPE + 1) #define GENL_ID_PMCRAID (NLMSG_MIN_TYPE + 2) /* must be last reserved + 1 */ From 46e4cb19f25dd1a6a3dc50db4e92986cf7d82f89 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 10 May 2018 19:46:08 +0200 Subject: [PATCH 02/40] making it bootable (wifi still not working) --- arch/arm/boot/dts/mt7623.dtsi | 42 ++++++++++---------- build.log | 11 ----- build.sh | 9 ++++- include/{linux => }/soc/mediatek/pmic_wrap.h | 0 4 files changed, 28 insertions(+), 34 deletions(-) rename include/{linux => }/soc/mediatek/pmic_wrap.h (100%) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 13d60589b3899..033513d41e85c 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -359,6 +359,17 @@ #io-channel-cells = <1>; }; + uart2: serial@11004000 { + compatible = "mediatek,mt7623-uart", + "mediatek,mt6577-uart"; + reg = <0 0x11004000 0 0x400>; + interrupts = ; + clocks = <&pericfg CLK_PERI_UART2_SEL>, + <&pericfg CLK_PERI_UART2>; + clock-names = "baud", "bus"; + status = "disabled"; + }; + uart0: serial@11002000 { compatible = "mediatek,mt7623-uart", "mediatek,mt6577-uart"; @@ -381,17 +392,6 @@ status = "disabled"; }; - uart2: serial@11004000 { - compatible = "mediatek,mt7623-uart", - "mediatek,mt6577-uart"; - reg = <0 0x11004000 0 0x400>; - interrupts = ; - clocks = <&pericfg CLK_PERI_UART2_SEL>, - <&pericfg CLK_PERI_UART2>; - clock-names = "baud", "bus"; - status = "disabled"; - }; - uart3: serial@11005000 { compatible = "mediatek,mt7623-uart", "mediatek,mt6577-uart"; @@ -672,24 +672,24 @@ "top_syspll_d5"; }; - mmc0: mmc@11230000 { + mmc1: mmc@11240000 { compatible = "mediatek,mt7623-mmc", "mediatek,mt2701-mmc"; - reg = <0 0x11230000 0 0x1000>; - interrupts = ; - clocks = <&pericfg CLK_PERI_MSDC30_0>, - <&topckgen CLK_TOP_MSDC30_0_SEL>; + reg = <0 0x11240000 0 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI_MSDC30_1>, + <&topckgen CLK_TOP_MSDC30_1_SEL>; clock-names = "source", "hclk"; status = "disabled"; }; - mmc1: mmc@11240000 { + mmc0: mmc@11230000 { compatible = "mediatek,mt7623-mmc", "mediatek,mt2701-mmc"; - reg = <0 0x11240000 0 0x1000>; - interrupts = ; - clocks = <&pericfg CLK_PERI_MSDC30_1>, - <&topckgen CLK_TOP_MSDC30_1_SEL>; + reg = <0 0x11230000 0 0x1000>; + interrupts = ; + clocks = <&pericfg CLK_PERI_MSDC30_0>, + <&topckgen CLK_TOP_MSDC30_0_SEL>; clock-names = "source", "hclk"; status = "disabled"; }; diff --git a/build.log b/build.log index 36f9622df99d2..e69de29bb2d1d 100644 --- a/build.log +++ b/build.log @@ -1,11 +0,0 @@ -drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c:32:36: fatal error: soc/mediatek/pmic_wrap.h: No such file or directory -compilation terminated. -make[7]: *** [drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.o] Error 1 -make[6]: *** [drivers/misc/mediatek/connectivity/common/conn_soc/mt7623] Error 2 -make[5]: *** [drivers/misc/mediatek/connectivity/common/conn_soc] Error 2 -make[4]: *** [drivers/misc/mediatek/connectivity/common] Error 2 -make[3]: *** [drivers/misc/mediatek/connectivity] Error 2 -make[2]: *** [drivers/misc/mediatek] Error 2 -make[1]: *** [drivers/misc] Error 2 -make[1]: *** Waiting for unfinished jobs.... -make: *** [drivers] Error 2 diff --git a/build.sh b/build.sh index ab2cd5d6c88fe..f8e0c2b2247ed 100755 --- a/build.sh +++ b/build.sh @@ -10,6 +10,10 @@ crosscompile=0 if [[ -z $(cat /proc/cpuinfo | grep -i 'model name.*ArmV7') ]]; then if [[ -z "$(which arm-linux-gnueabihf-gcc)" ]];then echo "please install gcc-arm-linux-gnueabihf";exit 1;fi + CCVER=$(arm-linux-gnueabihf-gcc --version |grep arm| sed -e 's/^.* \([0-9]\.[0-9-]\).*$/\1/') + if [[ $CCVER =~ ^7 ]]; then + echo "arm-linux-gnueabihf-gcc version 7 currently not supported";exit 1; + fi export ARCH=arm;export CROSS_COMPILE=arm-linux-gnueabihf- crosscompile=1 fi; @@ -94,7 +98,7 @@ function build { exec 3> >(tee build.log) export LOCALVERSION="-${gitbranch}" - make ${CFLAGS} 2>&3 #&& make modules_install 2>&3 + make ${MAKEFLAGS} 2>&3 #&& make modules_install 2>&3 ret=$? exec 3>&- @@ -160,7 +164,8 @@ function prepare_SD { if [ -n "$kernver" ]; then action=$1 LANG=C - CFLAGS=-j$(grep ^processor /proc/cpuinfo | wc -l) + MAKEFLAGS=-j$(grep ^processor /proc/cpuinfo | wc -l) + # export KCFLAGS="-I/usr/lib/gcc-cross/arm-linux-gnueabihf/7/include" case "$action" in "reset") diff --git a/include/linux/soc/mediatek/pmic_wrap.h b/include/soc/mediatek/pmic_wrap.h similarity index 100% rename from include/linux/soc/mediatek/pmic_wrap.h rename to include/soc/mediatek/pmic_wrap.h From 7aedade67e055b5477303544787aeef5ea6ddd57 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Thu, 10 May 2018 20:40:43 +0200 Subject: [PATCH 03/40] [wifi] adding dtsnodes except btif (already in mt7623n-rfb-nand.dts) --- arch/arm/boot/dts/mt7623.dtsi | 59 ++++++++++++++++--- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 42 +++++++++++++ 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 033513d41e85c..fcbb14910cd68 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -198,6 +198,14 @@ }; }; + watchdog: watchdog@10007000 { + compatible = "mediatek,mt7623-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; + interrupts = ; + #reset-cells = <1>; + }; + timer { compatible = "arm,armv7-timer"; interrupt-parent = <&gic>; @@ -494,16 +502,27 @@ nvmem-cell-names = "calibration-data"; }; - btif: serial@1100c000 { - compatible = "mediatek,mt7623-btif", - "mediatek,mtk-btif"; + btif_tx: btif_tx@11000780 { + compatible = "mediatek,btif_tx"; + reg = <0 0x11000780 0 0x80>; + interrupts = ; + status = "okay"; + }; + + btif_rx: btif_rx@11000800 { + compatible = "mediatek,btif_rx"; + reg = <0 0x11000800 0 0x80>; + interrupts = ; + status = "okay"; + }; + + btif: btif@1100c000 { + compatible = "mediatek,btif"; reg = <0 0x1100c000 0 0x1000>; interrupts = ; - clocks = <&pericfg CLK_PERI_BTIF>; - clock-names = "main"; - reg-shift = <2>; - reg-io-width = <4>; - status = "disabled"; + clocks = <&pericfg CLK_PERI_BTIF>, <&pericfg CLK_PERI_AP_DMA>; + clock-names = "btifc", "apdmac"; + status = "okay"; }; nandc: nfi@1100d000 { @@ -694,6 +713,30 @@ status = "disabled"; }; + consys: consys@18070000 { + compatible = "mediatek,mt7623-consys"; + reg = <0 0x18070000 0 0x0200>, /*CONN_MCU_CONFIG_BASE */ + <0 0x10001000 0 0x1600>; /*TOPCKGEN_BASE */ + clocks = <&infracfg CLK_INFRA_CONNMCU>; + clock-names = "consysbus"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_CONN>; + interrupts = , /* BGF_EINT */ + ; /* WDT_EINT */ + resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>; + reset-names = "connsys"; + status="disabled"; + }; + + wifi:wifi@180f0000 { + compatible = "mediatek,mt7623-wifi", + "mediatek,wifi"; + reg = <0 0x180f0000 0 0x005c>; + interrupts = ; + clocks = <&pericfg CLK_PERI_AP_DMA>; + clock-names = "wifi-dma"; + }; + + hifsys: syscon@1a000000 { compatible = "mediatek,mt7623-hifsys", "mediatek,mt2701-hifsys", diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 40f5b1213e76e..67700c45f4e47 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -75,6 +75,18 @@ }; }; + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + consys-reserve-memory { + compatible = "mediatek,consys-reserve-memory"; + no-map; + size = <0 0x100000>; + alignment = <0 0x100000>; + }; + }; + leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -444,6 +456,25 @@ ; }; }; + + consys_pins_default: consys_pins_default { + adie { + pinmux = , + , + , + , + , + , + , + , + , + , + , + ; + bias-disable; + }; + }; + }; &pwm { @@ -480,6 +511,17 @@ }; }; +&consys { + mediatek,pwrap-regmap = <&pwrap>; + pinctrl-names = "default"; + pinctrl-0 = <&consys_pins_default>; + vcn18-supply = <&mt6323_vcn18_reg>; + vcn28-supply = <&mt6323_vcn28_reg>; + vcn33_bt-supply = <&mt6323_vcn33_bt_reg>; + vcn33_wifi-supply = <&mt6323_vcn33_wifi_reg>; + status = "okay"; +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins_a>; From 5cdeb9bf8a940dbb7c0bf9a232b5696f5e10de83 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 11 May 2018 15:17:32 +0200 Subject: [PATCH 04/40] [build.sh] set name of uImage while install --- build.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/build.sh b/build.sh index f8e0c2b2247ed..dbc68f6273ad1 100755 --- a/build.sh +++ b/build.sh @@ -54,13 +54,18 @@ function install { else read -p "Press [enter] to copy data to SD-Card..." if [[ -d /media/$USER/BPI-BOOT ]]; then - kernelfile=/media/$USER/BPI-BOOT/bananapi/bpi-r2/linux/uImage + imagename="uImage_${kernver}-${gitbranch}" + read -e -i $imagename -p "uImage-filename: " input + imagename="${input:-$imagename}" + + echo "Name: $imagename" + kernelfile=/media/$USER/BPI-BOOT/bananapi/bpi-r2/linux/${imagename} if [[ -e $kernelfile ]];then echo "backup of kernel: $kernelfile.bak" cp $kernelfile $kernelfile.bak fi echo "copy new kernel" - cp ./uImage /media/$USER/BPI-BOOT/bananapi/bpi-r2/linux/uImage + cp ./uImage $kernelfile echo "copy modules (root needed because of ext-fs permission)" export INSTALL_MOD_PATH=/media/$USER/BPI-ROOT/; echo "INSTALL_MOD_PATH: $INSTALL_MOD_PATH" From c2300f2fa0d90fc932eee5406e67fbf3b95060dc Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 12 May 2018 09:26:10 +0200 Subject: [PATCH 05/40] removed duplicate watchdog & debug-const to possible crash-location --- arch/arm/boot/dts/mt7623.dtsi | 6 ------ .../mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c | 1 + .../connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c | 2 ++ 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index fcbb14910cd68..7f3c401d4f519 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -275,12 +275,6 @@ clock-names = "mm", "mfg", "ethif"; }; - watchdog: watchdog@10007000 { - compatible = "mediatek,mt7623-wdt", - "mediatek,mt6589-wdt"; - reg = <0 0x10007000 0 0x100>; - }; - timer: timer@10008000 { compatible = "mediatek,mt7623-timer", "mediatek,mt6577-timer"; diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c index fa603c208e59b..428375c0d4593 100644 --- a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c @@ -32,6 +32,7 @@ #endif #define DFT_TAG "[WMT-CTRL]" +#define DEBUG /******************************************************************************* * E X T E R N A L R E F E R E N C E S ******************************************************************************** diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c index 53b69a7b3e872..75c57b2581d78 100644 --- a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c @@ -14,6 +14,8 @@ ******************************************************************************** */ +#define DEBUG + #ifdef DFT_TAG #undef DFT_TAG #endif From b65262d300ab36cea72d5f6f527c29e42fda26a4 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 12 May 2018 15:29:29 +0200 Subject: [PATCH 06/40] [dts] enabled watchdog-node --- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 67700c45f4e47..e3af87a26c548 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -522,6 +522,10 @@ status = "okay"; }; +&watchdog { + status = "okay"; +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins_a>; From 3605bc566ad59e3483fd5cdc2f361a2f6762efcb Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 15 May 2018 17:19:51 +0200 Subject: [PATCH 07/40] [debug] added some debug-infos for wifi-crash @ init-reset Signed-off-by: Frank Wunderlich --- arch/arm/boot/dts/mt7623.dtsi | 1 + drivers/reset/core.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 7f3c401d4f519..96bde4764b5c8 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -718,6 +718,7 @@ ; /* WDT_EINT */ resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>; reset-names = "connsys"; + #reset-cells = <1>; status="disabled"; }; diff --git a/drivers/reset/core.c b/drivers/reset/core.c index da4292e9de978..811d92129da44 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -84,6 +84,7 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { + printk(KERN_WARNING "%s: (%s:%i) of_node=%s", __FUNCTION__, __FILE__, __LINE__, rcdev->of_node ? rcdev->of_node->name : ""); if (!rcdev->of_xlate) { rcdev->of_reset_n_cells = 1; rcdev->of_xlate = of_reset_simple_xlate; @@ -438,6 +439,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, struct of_phandle_args args; int rstc_id; int ret; + printk(KERN_WARNING "%s: (%s:%i) node=%s", __FUNCTION__, __FILE__, __LINE__, node->name); if (!node) return ERR_PTR(-EINVAL); @@ -445,6 +447,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (id) { index = of_property_match_string(node, "reset-names", id); + printk(KERN_WARNING "%s: (%s:%i) index = %i", __FUNCTION__, __FILE__, __LINE__, index); if (index == -EILSEQ) return ERR_PTR(index); if (index < 0) @@ -453,6 +456,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); + printk(KERN_WARNING "%s: (%s:%i) ret = %p", __FUNCTION__, __FILE__, __LINE__, (void*)ret); if (ret == -EINVAL) return ERR_PTR(ret); if (ret) @@ -461,6 +465,8 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_lock(&reset_list_mutex); rcdev = NULL; list_for_each_entry(r, &reset_controller_list, list) { +// printk(KERN_WARNING "%s: (%s:%i) %p == %p", __FUNCTION__, __FILE__, __LINE__, (void*)args.np, (void*)r->of_node); + printk(KERN_WARNING "%s: (%s:%i) %s == %s", __FUNCTION__, __FILE__, __LINE__, args.np ? args.np->name : "", r->of_node ? r->of_node->name : ""); if (args.np == r->of_node) { rcdev = r; break; @@ -470,6 +476,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (!rcdev) { mutex_unlock(&reset_list_mutex); + printk(KERN_WARNING "%s: (%s:%i) !rcdev, returning -EPROBE_DEFER", __FUNCTION__, __FILE__, __LINE__); return ERR_PTR(-EPROBE_DEFER); } @@ -489,6 +496,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_unlock(&reset_list_mutex); + printk(KERN_WARNING "%s: (%s:%i) rstc = %p", __FUNCTION__, __FILE__, __LINE__, (void*)rstc); return rstc; } EXPORT_SYMBOL_GPL(__of_reset_control_get); From 2b93a5c8f40d97cd74dcdbcfde3ed6b424013d15 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 15 May 2018 17:19:51 +0200 Subject: [PATCH 08/40] [debug] added some debug-infos for wifi-crash @ init-reset Signed-off-by: Frank Wunderlich --- arch/arm/boot/dts/mt7623.dtsi | 1 + drivers/reset/core.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 7f3c401d4f519..96bde4764b5c8 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -718,6 +718,7 @@ ; /* WDT_EINT */ resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>; reset-names = "connsys"; + #reset-cells = <1>; status="disabled"; }; diff --git a/drivers/reset/core.c b/drivers/reset/core.c index da4292e9de978..811d92129da44 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -84,6 +84,7 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { + printk(KERN_WARNING "%s: (%s:%i) of_node=%s", __FUNCTION__, __FILE__, __LINE__, rcdev->of_node ? rcdev->of_node->name : ""); if (!rcdev->of_xlate) { rcdev->of_reset_n_cells = 1; rcdev->of_xlate = of_reset_simple_xlate; @@ -438,6 +439,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, struct of_phandle_args args; int rstc_id; int ret; + printk(KERN_WARNING "%s: (%s:%i) node=%s", __FUNCTION__, __FILE__, __LINE__, node->name); if (!node) return ERR_PTR(-EINVAL); @@ -445,6 +447,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (id) { index = of_property_match_string(node, "reset-names", id); + printk(KERN_WARNING "%s: (%s:%i) index = %i", __FUNCTION__, __FILE__, __LINE__, index); if (index == -EILSEQ) return ERR_PTR(index); if (index < 0) @@ -453,6 +456,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); + printk(KERN_WARNING "%s: (%s:%i) ret = %p", __FUNCTION__, __FILE__, __LINE__, (void*)ret); if (ret == -EINVAL) return ERR_PTR(ret); if (ret) @@ -461,6 +465,8 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_lock(&reset_list_mutex); rcdev = NULL; list_for_each_entry(r, &reset_controller_list, list) { +// printk(KERN_WARNING "%s: (%s:%i) %p == %p", __FUNCTION__, __FILE__, __LINE__, (void*)args.np, (void*)r->of_node); + printk(KERN_WARNING "%s: (%s:%i) %s == %s", __FUNCTION__, __FILE__, __LINE__, args.np ? args.np->name : "", r->of_node ? r->of_node->name : ""); if (args.np == r->of_node) { rcdev = r; break; @@ -470,6 +476,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (!rcdev) { mutex_unlock(&reset_list_mutex); + printk(KERN_WARNING "%s: (%s:%i) !rcdev, returning -EPROBE_DEFER", __FUNCTION__, __FILE__, __LINE__); return ERR_PTR(-EPROBE_DEFER); } @@ -489,6 +496,7 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_unlock(&reset_list_mutex); + printk(KERN_WARNING "%s: (%s:%i) rstc = %p", __FUNCTION__, __FILE__, __LINE__, (void*)rstc); return rstc; } EXPORT_SYMBOL_GPL(__of_reset_control_get); From 3a6f93cc5166f0bd712d6cf17f555570bda880e1 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 11:35:07 +0200 Subject: [PATCH 09/40] updated mediatek watchdog-source --- build.log | 22 ++ drivers/clk/mediatek/clk-mt2701.c | 4 +- drivers/clk/mediatek/reset.c | 8 + drivers/watchdog/mtk_wdt.c | 363 +++++++++++++++++++++++++++++- 4 files changed, 385 insertions(+), 12 deletions(-) diff --git a/build.log b/build.log index e69de29bb2d1d..cac6158f74803 100644 --- a/build.log +++ b/build.log @@ -0,0 +1,22 @@ +drivers/watchdog/mtk_wdt.c: In function 'wk_proc_cmd_read': +drivers/watchdog/mtk_wdt.c:529:2: error: implicit declaration of function 'seq_printf' [-Werror=implicit-function-declaration] + seq_printf(s, "enabled timeout\n%-4d %-8d\n", enabled, wdt_dev->timeout); + ^ +drivers/watchdog/mtk_wdt.c: In function 'wk_proc_cmd_open': +drivers/watchdog/mtk_wdt.c:536:9: error: implicit declaration of function 'single_open' [-Werror=implicit-function-declaration] + return single_open(file, wk_proc_cmd_read, NULL); + ^ +drivers/watchdog/mtk_wdt.c: At top level: +drivers/watchdog/mtk_wdt.c:591:10: error: 'seq_read' undeclared here (not in a function) + .read = seq_read, + ^ +drivers/watchdog/mtk_wdt.c:593:12: error: 'seq_lseek' undeclared here (not in a function) + .llseek = seq_lseek, + ^ +drivers/watchdog/mtk_wdt.c:594:13: error: 'single_release' undeclared here (not in a function) + .release = single_release, + ^ +cc1: some warnings being treated as errors +make[2]: *** [drivers/watchdog/mtk_wdt.o] Error 1 +make[1]: *** [drivers/watchdog] Error 2 +make: *** [drivers] Error 2 diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index deca7527f92f6..aa09b75e361e8 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -780,13 +780,14 @@ static int mtk_infrasys_init(struct platform_device *pdev) { int r, i; struct device_node *node = pdev->dev.of_node; - + printk(KERN_WARNING "%s: (%s:%i) of_node=%s", __FUNCTION__, __FILE__, __LINE__, node ? node->name : ""); if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); } else { for (i = 0; i < CLK_INFRA_NR; i++) { if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) infra_clk_data->clks[i] = ERR_PTR(-ENOENT); + printk(KERN_WARNING "%s: (%s:%i) infra_clk_data->clks[%i]=%i", __FUNCTION__, __FILE__, __LINE__, i, (int)infra_clk_data->clks[i]); } } @@ -798,6 +799,7 @@ static int mtk_infrasys_init(struct platform_device *pdev) r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); if (r) return r; + printk(KERN_WARNING "%s: (%s:%i) r=%i", __FUNCTION__, __FILE__, __LINE__, r); mtk_register_reset_controller(node, 2, 0x30); diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index d3551d5efef24..7cb8f3d78dd3d 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c @@ -69,8 +69,11 @@ void mtk_register_reset_controller(struct device_node *np, struct mtk_reset *data; int ret; struct regmap *regmap; + printk(KERN_WARNING "%s: (%s:%i) node=%s", __FUNCTION__, __FILE__, __LINE__, np ? np->name : ""); regmap = syscon_node_to_regmap(np); +// printk(KERN_WARNING "%s: (%s:%i) regmap=%s", __FUNCTION__, __FILE__, __LINE__, regmap ? *regmap->name : ""); + if (IS_ERR(regmap)) { pr_err("Cannot find regmap for %pOF: %ld\n", np, PTR_ERR(regmap)); @@ -78,9 +81,12 @@ void mtk_register_reset_controller(struct device_node *np, } data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) return; + printk(KERN_WARNING "%s: (%s:%i) data=%s", __FUNCTION__, __FILE__, __LINE__, data ? "mem allocated" : ""); + data->regmap = regmap; data->regofs = regofs; data->rcdev.owner = THIS_MODULE; @@ -88,7 +94,9 @@ void mtk_register_reset_controller(struct device_node *np, data->rcdev.ops = &mtk_reset_ops; data->rcdev.of_node = np; + printk(KERN_WARNING "%s: (%s:%i)", __FUNCTION__, __FILE__, __LINE__); ret = reset_controller_register(&data->rcdev); + printk(KERN_WARNING "%s: (%s:%i) ret=%i", __FUNCTION__, __FILE__, __LINE__, ret); if (ret) { pr_err("could not register reset controller: %d\n", ret); kfree(data); diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 7ed417a765c70..43676313f32ba 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -21,14 +21,34 @@ #include #include #include +#include #include #include #include +#include +#include +#include #include +#include #include +#ifdef CONFIG_FIQ_GLUE +#include +#include +#endif #include #include +#include +#include #include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_MT6397_MISC +#include +#endif #define WDT_MAX_TIMEOUT 31 #define WDT_MIN_TIMEOUT 1 @@ -47,37 +67,167 @@ #define WDT_MODE_EXRST_EN (1 << 2) #define WDT_MODE_IRQ_EN (1 << 3) #define WDT_MODE_AUTO_START (1 << 4) +#define WDT_MODE_IRQ_LVL (1 << 5) #define WDT_MODE_DUAL_EN (1 << 6) #define WDT_MODE_KEY 0x22000000 +#define WDT_STATUS 0x0c +#define WDT_NONRST_REG 0x20 +#define WDT_NONRST_REG2 0x24 + #define WDT_SWRST 0x14 #define WDT_SWRST_KEY 0x1209 +#define WDT_SWSYSRST 0x18 +#define WDT_SWSYSRST_KEY 0x88000000 + +#define WDT_REQ_MODE 0x30 +#define WDT_REQ_MODE_KEY 0x33000000 +#define WDT_REQ_IRQ_EN 0x34 +#define WDT_REQ_IRQ_KEY 0x44000000 +#define WDT_REQ_MODE_DEBUG_EN 0x80000 + + #define DRV_NAME "mtk-wdt" -#define DRV_VERSION "1.0" +#define DRV_VERSION "2.0" static bool nowayout = WATCHDOG_NOWAYOUT; static unsigned int timeout = WDT_MAX_TIMEOUT; +struct toprgu_reset { + spinlock_t lock; + void __iomem *toprgu_swrst_base; + int regofs; + struct reset_controller_dev rcdev; +}; + struct mtk_wdt_dev { struct watchdog_device wdt_dev; void __iomem *wdt_base; + int wdt_irq_id; + struct notifier_block restart_handler; + struct toprgu_reset reset_controller; }; -static int mtk_wdt_restart(struct watchdog_device *wdt_dev, - unsigned long action, void *data) +static void __iomem *toprgu_base; +static struct watchdog_device *wdt_dev; + +static int toprgu_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) { - struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev); + unsigned int tmp; + unsigned long flags; + struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev); + + spin_lock_irqsave(&data->lock, flags); + + tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); + tmp |= BIT(id); + tmp |= WDT_SWSYSRST_KEY; + writel(tmp, data->toprgu_swrst_base + data->regofs); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int toprgu_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + unsigned int tmp; + unsigned long flags; + struct toprgu_reset *data = container_of(rcdev, struct toprgu_reset, rcdev); + + spin_lock_irqsave(&data->lock, flags); + + tmp = __raw_readl(data->toprgu_swrst_base + data->regofs); + tmp &= ~BIT(id); + tmp |= WDT_SWSYSRST_KEY; + writel(tmp, data->toprgu_swrst_base + data->regofs); + + spin_unlock_irqrestore(&data->lock, flags); + + return 0; +} + +static int toprgu_reset(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = toprgu_reset_assert(rcdev, id); + if (ret) + return ret; + + return toprgu_reset_deassert(rcdev, id); +} + +static struct reset_control_ops toprgu_reset_ops = { + .assert = toprgu_reset_assert, + .deassert = toprgu_reset_deassert, + .reset = toprgu_reset, +}; + +static void toprgu_register_reset_controller(struct platform_device *pdev, int regofs) +{ + int ret; + struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); + + spin_lock_init(&mtk_wdt->reset_controller.lock); + + mtk_wdt->reset_controller.toprgu_swrst_base = mtk_wdt->wdt_base; + mtk_wdt->reset_controller.regofs = regofs; + mtk_wdt->reset_controller.rcdev.owner = THIS_MODULE; + mtk_wdt->reset_controller.rcdev.nr_resets = 15; + mtk_wdt->reset_controller.rcdev.ops = &toprgu_reset_ops; + mtk_wdt->reset_controller.rcdev.of_node = pdev->dev.of_node; + + ret = reset_controller_register(&mtk_wdt->reset_controller.rcdev); + if (ret) + pr_err("could not register toprgu reset controller: %d\n", ret); +} + +static int mtk_reset_handler(struct notifier_block *this, unsigned long mode, + void *cmd) +{ + struct mtk_wdt_dev *mtk_wdt; void __iomem *wdt_base; + u32 reg; + mtk_wdt = container_of(this, struct mtk_wdt_dev, restart_handler); wdt_base = mtk_wdt->wdt_base; - while (1) { - writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); - mdelay(5); + /* WDT_STATUS will be cleared to zero after writing to WDT_MODE, so we backup it in WDT_NONRST_REG, + * and then print it out in mtk_wdt_probe() after reset + */ + writel(__raw_readl(wdt_base + WDT_STATUS), wdt_base + WDT_NONRST_REG); + + reg = ioread32(wdt_base + WDT_MODE); + reg &= ~(WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EN); + reg |= WDT_MODE_KEY; + iowrite32(reg, wdt_base + WDT_MODE); + + if (cmd && !strcmp(cmd, "rpmbpk")) { + iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 0), wdt_base + WDT_NONRST_REG2); + } else if (cmd && !strcmp(cmd, "recovery")) { + iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 1), wdt_base + WDT_NONRST_REG2); + #ifdef CONFIG_MT6397_MISC + mtk_misc_mark_recovery(); + #endif + } else if (cmd && !strcmp(cmd, "bootloader")) { + iowrite32(ioread32(wdt_base + WDT_NONRST_REG2) | (1 << 2), wdt_base + WDT_NONRST_REG2); + #ifdef CONFIG_MT6397_MISC + mtk_misc_mark_fast(); + #endif } - return 0; + if (!arm_pm_restart) { + while (1) { + writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST); + mdelay(5); + } + } + return NOTIFY_DONE; } static int mtk_wdt_ping(struct watchdog_device *wdt_dev) @@ -86,6 +236,7 @@ static int mtk_wdt_ping(struct watchdog_device *wdt_dev) void __iomem *wdt_base = mtk_wdt->wdt_base; iowrite32(WDT_RST_RELOAD, wdt_base + WDT_RST); + printk_deferred("[WDK]: kick Ex WDT\n"); return 0; } @@ -137,7 +288,8 @@ static int mtk_wdt_start(struct watchdog_device *wdt_dev) return ret; reg = ioread32(wdt_base + WDT_MODE); - reg &= ~(WDT_MODE_IRQ_EN | WDT_MODE_DUAL_EN); + reg |= (WDT_MODE_DUAL_EN | WDT_MODE_IRQ_EN | WDT_MODE_EXRST_EN); + reg &= ~(WDT_MODE_IRQ_LVL | WDT_MODE_EXT_POL_HIGH); reg |= (WDT_MODE_EN | WDT_MODE_KEY); iowrite32(reg, wdt_base + WDT_MODE); @@ -157,13 +309,56 @@ static const struct watchdog_ops mtk_wdt_ops = { .stop = mtk_wdt_stop, .ping = mtk_wdt_ping, .set_timeout = mtk_wdt_set_timeout, - .restart = mtk_wdt_restart, }; +#ifdef CONFIG_FIQ_GLUE +static void wdt_fiq(void *arg, void *regs, void *svc_sp) +{ + unsigned int wdt_mode_val; + void __iomem *wdt_base = ((struct mtk_wdt_dev *)arg)->wdt_base; + + wdt_mode_val = __raw_readl(wdt_base + WDT_STATUS); + writel(wdt_mode_val, wdt_base + WDT_NONRST_REG); + + aee_wdt_fiq_info(arg, regs, svc_sp); +} +#else +static void wdt_report_info(void) +{ + struct task_struct *task; + + task = &init_task; + pr_debug("Qwdt: -- watchdog time out\n"); + + for_each_process(task) { + if (task->state == 0) { + pr_debug("PID: %d, name: %s\n backtrace:\n", task->pid, task->comm); + show_stack(task, NULL); + pr_debug("\n"); + } + } + + pr_debug("backtrace of current task:\n"); + show_stack(NULL, NULL); + pr_debug("Qwdt: -- watchdog time out\n"); +} + +static irqreturn_t mtk_wdt_isr(int irq, void *dev_id) +{ + pr_err("fwq mtk_wdt_isr\n"); + + wdt_report_info(); + BUG(); + + return IRQ_HANDLED; +} +#endif + static int mtk_wdt_probe(struct platform_device *pdev) { struct mtk_wdt_dev *mtk_wdt; struct resource *res; + unsigned int tmp; int err; mtk_wdt = devm_kzalloc(&pdev->dev, sizeof(*mtk_wdt), GFP_KERNEL); @@ -174,9 +369,32 @@ static int mtk_wdt_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); mtk_wdt->wdt_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(mtk_wdt->wdt_base)) return PTR_ERR(mtk_wdt->wdt_base); + pr_err("MTK_WDT_NONRST_REG(%x)\n", __raw_readl(mtk_wdt->wdt_base + WDT_NONRST_REG)); + + mtk_wdt->wdt_irq_id = irq_of_parse_and_map(pdev->dev.of_node, 0); + if (!mtk_wdt->wdt_irq_id) { + pr_err("RGU get IRQ ID failed\n"); + return -ENODEV; + } + +#ifndef CONFIG_FIQ_GLUE + err = request_irq(mtk_wdt->wdt_irq_id, (irq_handler_t)mtk_wdt_isr, IRQF_TRIGGER_NONE, DRV_NAME, mtk_wdt); +#else + mtk_wdt->wdt_irq_id = get_hardware_irq(mtk_wdt->wdt_irq_id); + err = request_fiq(mtk_wdt->wdt_irq_id, wdt_fiq, IRQF_TRIGGER_FALLING, mtk_wdt); +#endif + if (err != 0) { + pr_err("mtk_wdt_probe : failed to request irq (%d)\n", err); + return err; + } + + toprgu_base = mtk_wdt->wdt_base; + wdt_dev = &mtk_wdt->wdt_dev; + mtk_wdt->wdt_dev.info = &mtk_wdt_info; mtk_wdt->wdt_dev.ops = &mtk_wdt_ops; mtk_wdt->wdt_dev.timeout = WDT_MAX_TIMEOUT; @@ -186,7 +404,6 @@ static int mtk_wdt_probe(struct platform_device *pdev) watchdog_init_timeout(&mtk_wdt->wdt_dev, timeout, &pdev->dev); watchdog_set_nowayout(&mtk_wdt->wdt_dev, nowayout); - watchdog_set_restart_priority(&mtk_wdt->wdt_dev, 128); watchdog_set_drvdata(&mtk_wdt->wdt_dev, mtk_wdt); @@ -196,9 +413,40 @@ static int mtk_wdt_probe(struct platform_device *pdev) if (unlikely(err)) return err; + mtk_wdt->restart_handler.notifier_call = mtk_reset_handler; + mtk_wdt->restart_handler.priority = 128; + + if (arm_pm_restart) { + dev_info(&pdev->dev, "register restart_handler on reboot_notifier_list for psci reset\n"); + err = register_reboot_notifier(&mtk_wdt->restart_handler); + if (err != 0) + dev_warn(&pdev->dev, + "cannot register reboot notifier (err=%d)\n", err); + } else { + err = register_restart_handler(&mtk_wdt->restart_handler); + if (err) + dev_warn(&pdev->dev, + "cannot register restart handler (err=%d)\n", err); + } + dev_info(&pdev->dev, "Watchdog enabled (timeout=%d sec, nowayout=%d)\n", mtk_wdt->wdt_dev.timeout, nowayout); + writel(WDT_REQ_MODE_KEY | (__raw_readl(mtk_wdt->wdt_base + WDT_REQ_MODE) & + (~WDT_REQ_MODE_DEBUG_EN)), mtk_wdt->wdt_base + WDT_REQ_MODE); + + toprgu_register_reset_controller(pdev, WDT_SWSYSRST); + + /* enable scpsys thermal and thermal_controller request, and set to reset directly mode */ + tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_MODE) | (1 << 18) | (1 << 0); + tmp |= WDT_REQ_MODE_KEY; + iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_MODE); + + tmp = ioread32(mtk_wdt->wdt_base + WDT_REQ_IRQ_EN); + tmp &= ~((1 << 18) | (1 << 0)); + tmp |= WDT_REQ_IRQ_KEY; + iowrite32(tmp, mtk_wdt->wdt_base + WDT_REQ_IRQ_EN); + return 0; } @@ -214,8 +462,12 @@ static int mtk_wdt_remove(struct platform_device *pdev) { struct mtk_wdt_dev *mtk_wdt = platform_get_drvdata(pdev); + unregister_restart_handler(&mtk_wdt->restart_handler); + watchdog_unregister_device(&mtk_wdt->wdt_dev); + reset_controller_unregister(&mtk_wdt->reset_controller.rcdev); + return 0; } @@ -267,6 +519,95 @@ static struct platform_driver mtk_wdt_driver = { module_platform_driver(mtk_wdt_driver); +static int wk_proc_cmd_read(struct seq_file *s, void *v) +{ + unsigned int enabled = 1; + + if (!(ioread32(toprgu_base + WDT_MODE) & WDT_MODE_EN)) + enabled = 0; + + seq_printf(s, "enabled timeout\n%-4d %-8d\n", enabled, wdt_dev->timeout); + + return 0; +} + +static int wk_proc_cmd_open(struct inode *inode, struct file *file) +{ + return single_open(file, wk_proc_cmd_read, NULL); +} + +static ssize_t wk_proc_cmd_write(struct file *file, const char *buf, size_t count, loff_t *data) +{ + int ret; + int enable; + int timeout; + char wk_cmd_buf[256]; + + if (count == 0) + return -1; + + if (count > 255) + count = 255; + + ret = copy_from_user(wk_cmd_buf, buf, count); + if (ret < 0) + return -1; + + wk_cmd_buf[count] = '\0'; + + pr_debug("Write %s\n", wk_cmd_buf); + + ret = sscanf(wk_cmd_buf, "%d %d", &enable, &timeout); + if (ret != 2) + pr_debug("%s: expect 2 numbers\n", __func__); + + pr_debug("[WDK] enable=%d timeout=%d\n", enable, timeout); + + if (timeout > 20 && timeout <= WDT_MAX_TIMEOUT) { + wdt_dev->timeout = timeout; + mtk_wdt_set_timeout(wdt_dev, wdt_dev->timeout); + } else { + pr_err("[WDK] The timeout(%d) should bigger than 20 and not bigger than %d\n", + timeout, WDT_MAX_TIMEOUT); + + } + + if (enable == 1) { + mtk_wdt_start(wdt_dev); + set_bit(WDOG_ACTIVE, &wdt_dev->status); + pr_err("[WDK] enable wdt\n"); + } else if (enable == 0) { + mtk_wdt_stop(wdt_dev); + clear_bit(WDOG_ACTIVE, &wdt_dev->status); + pr_err("[WDK] disable wdt\n"); + } + + return count; +} + +static const struct file_operations wk_proc_cmd_fops = { + .owner = THIS_MODULE, + .open = wk_proc_cmd_open, + .read = seq_read, + .write = wk_proc_cmd_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init wk_proc_init(void) +{ + struct proc_dir_entry *de = proc_create("wdk", 0660, NULL, &wk_proc_cmd_fops); + + if (!de) + pr_err("[wk_proc_init]: create /proc/wdk failed\n"); + + pr_debug("[WDK] Initialize proc\n"); + + return 0; +} + +late_initcall(wk_proc_init); + module_param(timeout, uint, 0); MODULE_PARM_DESC(timeout, "Watchdog heartbeat in seconds"); From 0fc5b903609d48b8cf340d2b83967b870bfe3135 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 11:57:04 +0200 Subject: [PATCH 10/40] fix compile error after watchdog-driver-update --- build.log | 22 ---------------------- drivers/watchdog/mtk_wdt.c | 1 + 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/build.log b/build.log index cac6158f74803..e69de29bb2d1d 100644 --- a/build.log +++ b/build.log @@ -1,22 +0,0 @@ -drivers/watchdog/mtk_wdt.c: In function 'wk_proc_cmd_read': -drivers/watchdog/mtk_wdt.c:529:2: error: implicit declaration of function 'seq_printf' [-Werror=implicit-function-declaration] - seq_printf(s, "enabled timeout\n%-4d %-8d\n", enabled, wdt_dev->timeout); - ^ -drivers/watchdog/mtk_wdt.c: In function 'wk_proc_cmd_open': -drivers/watchdog/mtk_wdt.c:536:9: error: implicit declaration of function 'single_open' [-Werror=implicit-function-declaration] - return single_open(file, wk_proc_cmd_read, NULL); - ^ -drivers/watchdog/mtk_wdt.c: At top level: -drivers/watchdog/mtk_wdt.c:591:10: error: 'seq_read' undeclared here (not in a function) - .read = seq_read, - ^ -drivers/watchdog/mtk_wdt.c:593:12: error: 'seq_lseek' undeclared here (not in a function) - .llseek = seq_lseek, - ^ -drivers/watchdog/mtk_wdt.c:594:13: error: 'single_release' undeclared here (not in a function) - .release = single_release, - ^ -cc1: some warnings being treated as errors -make[2]: *** [drivers/watchdog/mtk_wdt.o] Error 1 -make[1]: *** [drivers/watchdog] Error 2 -make: *** [drivers] Error 2 diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c index 43676313f32ba..6a361f808aed1 100644 --- a/drivers/watchdog/mtk_wdt.c +++ b/drivers/watchdog/mtk_wdt.c @@ -46,6 +46,7 @@ #include #include #include +#include #ifdef CONFIG_MT6397_MISC #include #endif From 606cd73026562d658b66fbb7b97cf6ec1965a72d Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 13:24:42 +0200 Subject: [PATCH 11/40] Revert "[debug] added some debug-infos for wifi-crash @ init-reset" This reverts commit 3605bc566ad59e3483fd5cdc2f361a2f6762efcb. --- arch/arm/boot/dts/mt7623.dtsi | 1 - drivers/reset/core.c | 8 -------- 2 files changed, 9 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 96bde4764b5c8..7f3c401d4f519 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -718,7 +718,6 @@ ; /* WDT_EINT */ resets = <&watchdog MT2701_TOPRGU_CONN_MCU_RST>; reset-names = "connsys"; - #reset-cells = <1>; status="disabled"; }; diff --git a/drivers/reset/core.c b/drivers/reset/core.c index 811d92129da44..da4292e9de978 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -84,7 +84,6 @@ static int of_reset_simple_xlate(struct reset_controller_dev *rcdev, */ int reset_controller_register(struct reset_controller_dev *rcdev) { - printk(KERN_WARNING "%s: (%s:%i) of_node=%s", __FUNCTION__, __FILE__, __LINE__, rcdev->of_node ? rcdev->of_node->name : ""); if (!rcdev->of_xlate) { rcdev->of_reset_n_cells = 1; rcdev->of_xlate = of_reset_simple_xlate; @@ -439,7 +438,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, struct of_phandle_args args; int rstc_id; int ret; - printk(KERN_WARNING "%s: (%s:%i) node=%s", __FUNCTION__, __FILE__, __LINE__, node->name); if (!node) return ERR_PTR(-EINVAL); @@ -447,7 +445,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (id) { index = of_property_match_string(node, "reset-names", id); - printk(KERN_WARNING "%s: (%s:%i) index = %i", __FUNCTION__, __FILE__, __LINE__, index); if (index == -EILSEQ) return ERR_PTR(index); if (index < 0) @@ -456,7 +453,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, ret = of_parse_phandle_with_args(node, "resets", "#reset-cells", index, &args); - printk(KERN_WARNING "%s: (%s:%i) ret = %p", __FUNCTION__, __FILE__, __LINE__, (void*)ret); if (ret == -EINVAL) return ERR_PTR(ret); if (ret) @@ -465,8 +461,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_lock(&reset_list_mutex); rcdev = NULL; list_for_each_entry(r, &reset_controller_list, list) { -// printk(KERN_WARNING "%s: (%s:%i) %p == %p", __FUNCTION__, __FILE__, __LINE__, (void*)args.np, (void*)r->of_node); - printk(KERN_WARNING "%s: (%s:%i) %s == %s", __FUNCTION__, __FILE__, __LINE__, args.np ? args.np->name : "", r->of_node ? r->of_node->name : ""); if (args.np == r->of_node) { rcdev = r; break; @@ -476,7 +470,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, if (!rcdev) { mutex_unlock(&reset_list_mutex); - printk(KERN_WARNING "%s: (%s:%i) !rcdev, returning -EPROBE_DEFER", __FUNCTION__, __FILE__, __LINE__); return ERR_PTR(-EPROBE_DEFER); } @@ -496,7 +489,6 @@ struct reset_control *__of_reset_control_get(struct device_node *node, mutex_unlock(&reset_list_mutex); - printk(KERN_WARNING "%s: (%s:%i) rstc = %p", __FUNCTION__, __FILE__, __LINE__, (void*)rstc); return rstc; } EXPORT_SYMBOL_GPL(__of_reset_control_get); From 2c4fa3b25b84b2601fdf1cbca9cb46e8245a2c02 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 13:37:10 +0200 Subject: [PATCH 12/40] removed additional debug-infos --- drivers/clk/mediatek/clk-mt2701.c | 4 +--- drivers/clk/mediatek/reset.c | 8 -------- .../mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c | 1 - .../common/conn_soc/mt7623/mtk_wcn_consys_hw.c | 2 -- 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index aa09b75e361e8..deca7527f92f6 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -780,14 +780,13 @@ static int mtk_infrasys_init(struct platform_device *pdev) { int r, i; struct device_node *node = pdev->dev.of_node; - printk(KERN_WARNING "%s: (%s:%i) of_node=%s", __FUNCTION__, __FILE__, __LINE__, node ? node->name : ""); + if (!infra_clk_data) { infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); } else { for (i = 0; i < CLK_INFRA_NR; i++) { if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER)) infra_clk_data->clks[i] = ERR_PTR(-ENOENT); - printk(KERN_WARNING "%s: (%s:%i) infra_clk_data->clks[%i]=%i", __FUNCTION__, __FILE__, __LINE__, i, (int)infra_clk_data->clks[i]); } } @@ -799,7 +798,6 @@ static int mtk_infrasys_init(struct platform_device *pdev) r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); if (r) return r; - printk(KERN_WARNING "%s: (%s:%i) r=%i", __FUNCTION__, __FILE__, __LINE__, r); mtk_register_reset_controller(node, 2, 0x30); diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index 7cb8f3d78dd3d..d3551d5efef24 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c @@ -69,11 +69,8 @@ void mtk_register_reset_controller(struct device_node *np, struct mtk_reset *data; int ret; struct regmap *regmap; - printk(KERN_WARNING "%s: (%s:%i) node=%s", __FUNCTION__, __FILE__, __LINE__, np ? np->name : ""); regmap = syscon_node_to_regmap(np); -// printk(KERN_WARNING "%s: (%s:%i) regmap=%s", __FUNCTION__, __FILE__, __LINE__, regmap ? *regmap->name : ""); - if (IS_ERR(regmap)) { pr_err("Cannot find regmap for %pOF: %ld\n", np, PTR_ERR(regmap)); @@ -81,12 +78,9 @@ void mtk_register_reset_controller(struct device_node *np, } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) return; - printk(KERN_WARNING "%s: (%s:%i) data=%s", __FUNCTION__, __FILE__, __LINE__, data ? "mem allocated" : ""); - data->regmap = regmap; data->regofs = regofs; data->rcdev.owner = THIS_MODULE; @@ -94,9 +88,7 @@ void mtk_register_reset_controller(struct device_node *np, data->rcdev.ops = &mtk_reset_ops; data->rcdev.of_node = np; - printk(KERN_WARNING "%s: (%s:%i)", __FUNCTION__, __FILE__, __LINE__); ret = reset_controller_register(&data->rcdev); - printk(KERN_WARNING "%s: (%s:%i) ret=%i", __FUNCTION__, __FILE__, __LINE__, ret); if (ret) { pr_err("could not register reset controller: %d\n", ret); kfree(data); diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c index 428375c0d4593..fa603c208e59b 100644 --- a/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/core/wmt_ctrl.c @@ -32,7 +32,6 @@ #endif #define DFT_TAG "[WMT-CTRL]" -#define DEBUG /******************************************************************************* * E X T E R N A L R E F E R E N C E S ******************************************************************************** diff --git a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c index 75c57b2581d78..53b69a7b3e872 100644 --- a/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c +++ b/drivers/misc/mediatek/connectivity/common/conn_soc/mt7623/mtk_wcn_consys_hw.c @@ -14,8 +14,6 @@ ******************************************************************************** */ -#define DEBUG - #ifdef DFT_TAG #undef DFT_TAG #endif From 6f9e42cdbd8cc697bbf3c861d34c82c38a6f3c49 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:28:41 +0200 Subject: [PATCH 13/40] applied patch #1/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013240.html --- drivers/gpu/drm/mediatek/mtk_dpi.c | 82 ++++++++++++++++++++----- drivers/gpu/drm/mediatek/mtk_dpi_regs.h | 2 +- 2 files changed, 66 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index e80a603e5fb08..993dc44368bd7 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -71,11 +71,13 @@ struct mtk_dpi { struct clk *tvd_clk; int irq; struct drm_display_mode mode; + const struct mtk_dpi_conf *conf; enum mtk_dpi_out_color_format color_format; enum mtk_dpi_out_yc_map yc_map; enum mtk_dpi_out_bit_num bit_num; enum mtk_dpi_out_channel_swap channel_swap; bool power_sta; + int refcount; u8 power_ctl; }; @@ -115,6 +117,12 @@ struct mtk_dpi_yc_limit { u16 c_bottom; }; +struct mtk_dpi_conf { + unsigned int (*cal_factor)(int clock); + const u32 reg_h_fre_con; + bool edge_sel_en; +}; + static void mtk_dpi_mask(struct mtk_dpi *dpi, u32 offset, u32 val, u32 mask) { u32 tmp = readl(dpi->regs + offset) & ~mask; @@ -340,7 +348,13 @@ static void mtk_dpi_config_swap_input(struct mtk_dpi *dpi, bool enable) static void mtk_dpi_config_2n_h_fre(struct mtk_dpi *dpi) { - mtk_dpi_mask(dpi, DPI_H_FRE_CON, H_FRE_2N, H_FRE_2N); + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, H_FRE_2N, H_FRE_2N); +} + +static void mtk_dpi_config_disable_edge(struct mtk_dpi *dpi) +{ + if (dpi->conf->edge_sel_en) + mtk_dpi_mask(dpi, dpi->conf->reg_h_fre_con, 0, EDGE_SEL_EN); } static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, @@ -368,6 +382,12 @@ static void mtk_dpi_config_color_format(struct mtk_dpi *dpi, static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) { + if (WARN_ON(dpi->refcount == 0)) + return; + + if (--dpi->refcount != 0) + return; + dpi->power_ctl &= ~pctl; if ((dpi->power_ctl & DPI_POWER_START) || @@ -385,16 +405,19 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) { - int ret; + int ret = 0; + + if (++dpi->refcount != 1) + return 0; dpi->power_ctl |= pctl; if (!(dpi->power_ctl & DPI_POWER_START) && !(dpi->power_ctl & DPI_POWER_ENABLE)) - return 0; + goto err_refcount; if (dpi->power_sta) - return 0; + goto err_refcount; ret = clk_prepare_enable(dpi->engine_clk); if (ret) { @@ -416,6 +439,8 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi, enum mtk_dpi_power_ctl pctl) clk_disable_unprepare(dpi->engine_clk); err_eng: dpi->power_ctl &= ~pctl; +err_refcount: + dpi->refcount--; return ret; } @@ -433,16 +458,13 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, unsigned long pll_rate; unsigned int factor; + if (!dpi) { + dev_err(dpi->dev, "invalid argument\n"); + return -EINVAL; + } /* let pll_rate can fix the valid range of tvdpll (1G~2GHz) */ pix_rate = 1000UL * mode->clock; - if (mode->clock <= 27000) - factor = 16 * 3; - else if (mode->clock <= 84000) - factor = 8 * 3; - else if (mode->clock <= 167000) - factor = 4 * 3; - else - factor = 2 * 3; + factor = dpi->conf->cal_factor(mode->clock); pll_rate = pix_rate * factor; dev_dbg(dpi->dev, "Want PLL %lu Hz, pixel clock %lu Hz\n", @@ -518,6 +540,7 @@ static int mtk_dpi_set_display_mode(struct mtk_dpi *dpi, mtk_dpi_config_yc_map(dpi, dpi->yc_map); mtk_dpi_config_color_format(dpi, dpi->color_format); mtk_dpi_config_2n_h_fre(dpi); + mtk_dpi_config_disable_edge(dpi); mtk_dpi_sw_reset(dpi, false); return 0; @@ -656,6 +679,31 @@ static const struct component_ops mtk_dpi_component_ops = { .unbind = mtk_dpi_unbind, }; +static unsigned int mt8173_calculate_factor(int clock) +{ + if (clock <= 27000) + return 16 * 3; + else if (clock <= 74250) + return 8 * 3; + else if (clock <= 167000) + return 4 * 3; + else + return 2 * 3; +} + +static const struct mtk_dpi_conf mt8173_conf = { + .cal_factor = mt8173_calculate_factor, + .reg_h_fre_con = 0xe0, +}; + +static const struct of_device_id mtk_dpi_of_ids[] = { + { .compatible = "mediatek,mt8173-dpi", + .data = &mt8173_conf, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids); + static int mtk_dpi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -663,13 +711,18 @@ static int mtk_dpi_probe(struct platform_device *pdev) struct resource *mem; struct device_node *bridge_node; int comp_id; + const struct of_device_id *match; int ret; + match = of_match_node(mtk_dpi_of_ids, dev->of_node); + if (!match) + return -ENODEV; dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL); if (!dpi) return -ENOMEM; dpi->dev = dev; + dpi->conf = (struct mtk_dpi_conf *)match->data; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); dpi->regs = devm_ioremap_resource(dev, mem); @@ -748,11 +801,6 @@ static int mtk_dpi_remove(struct platform_device *pdev) return 0; } -static const struct of_device_id mtk_dpi_of_ids[] = { - { .compatible = "mediatek,mt8173-dpi", }, - {} -}; - struct platform_driver mtk_dpi_driver = { .probe = mtk_dpi_probe, .remove = mtk_dpi_remove, diff --git a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h index 4b6ad4751a314..d9db8c4cacd7a 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi_regs.h +++ b/drivers/gpu/drm/mediatek/mtk_dpi_regs.h @@ -223,6 +223,6 @@ #define ESAV_CODE2 (0xFFF << 0) #define ESAV_CODE3_MSB BIT(16) -#define DPI_H_FRE_CON 0xE0 +#define EDGE_SEL_EN BIT(5) #define H_FRE_2N BIT(25) #endif /* __MTK_DPI_REGS_H */ From f9faf9a3bd8feb67b8caf5683c48566e14b581d8 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:30:11 +0200 Subject: [PATCH 14/40] applied patch 2/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013239.html --- drivers/gpu/drm/mediatek/mtk_dpi.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index 993dc44368bd7..c82d55caee802 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -63,7 +63,6 @@ enum mtk_dpi_out_color_format { struct mtk_dpi { struct mtk_ddp_comp ddp_comp; struct drm_encoder encoder; - struct drm_bridge *bridge; void __iomem *regs; struct device *dev; struct clk *engine_clk; @@ -643,8 +642,8 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) /* Currently DPI0 is fixed to be driven by OVL1 */ dpi->encoder.possible_crtcs = BIT(1); - - ret = drm_bridge_attach(&dpi->encoder, dpi->bridge, NULL); + dpi->encoder.bridge->encoder = &dpi->encoder; + ret = drm_bridge_attach(&dpi->encoder, dpi->encoder.bridge, NULL); if (ret) { dev_err(dev, "Failed to attach bridge: %d\n", ret); goto err_cleanup; @@ -709,7 +708,7 @@ static int mtk_dpi_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct mtk_dpi *dpi; struct resource *mem; - struct device_node *bridge_node; + struct device_node *ep, *bridge_node; int comp_id; const struct of_device_id *match; int ret; @@ -759,15 +758,21 @@ static int mtk_dpi_probe(struct platform_device *pdev) return -EINVAL; } - bridge_node = of_graph_get_remote_node(dev->of_node, 0, 0); - if (!bridge_node) + ep = of_graph_get_next_endpoint(dev->of_node, NULL); + if (ep) { + bridge_node = of_graph_get_remote_port_parent(ep); + of_node_put(ep); + } + if (!bridge_node) { + dev_err(dev, "Failed to find bridge node\n"); return -ENODEV; + } dev_info(dev, "Found bridge node: %pOF\n", bridge_node); - dpi->bridge = of_drm_find_bridge(bridge_node); + dpi->encoder.bridge = of_drm_find_bridge(bridge_node); of_node_put(bridge_node); - if (!dpi->bridge) + if (!dpi->encoder.bridge) return -EPROBE_DEFER; comp_id = mtk_ddp_comp_get_id(dev->of_node, MTK_DPI); From 1ebe9e1dc02edd1da68ef63faa776e1f5a430ae3 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:31:02 +0200 Subject: [PATCH 15/40] applied patch 3/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013234.html --- drivers/gpu/drm/mediatek/mtk_dpi.c | 24 ++++++++++++++++++++++-- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index c82d55caee802..c58b39f55374b 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -640,8 +640,7 @@ static int mtk_dpi_bind(struct device *dev, struct device *master, void *data) } drm_encoder_helper_add(&dpi->encoder, &mtk_dpi_encoder_helper_funcs); - /* Currently DPI0 is fixed to be driven by OVL1 */ - dpi->encoder.possible_crtcs = BIT(1); + dpi->encoder.possible_crtcs = BIT(0) | BIT(1); dpi->encoder.bridge->encoder = &dpi->encoder; ret = drm_bridge_attach(&dpi->encoder, dpi->encoder.bridge, NULL); if (ret) { @@ -690,12 +689,33 @@ static unsigned int mt8173_calculate_factor(int clock) return 2 * 3; } +static unsigned int mt2701_calculate_factor(int clock) +{ + if (clock <= 64000) + return 16; + else if (clock <= 128000) + return 8; + else if (clock <= 256000) + return 4; + else + return 2; +} + static const struct mtk_dpi_conf mt8173_conf = { .cal_factor = mt8173_calculate_factor, .reg_h_fre_con = 0xe0, }; +static const struct mtk_dpi_conf mt2701_conf = { + .cal_factor = mt2701_calculate_factor, + .reg_h_fre_con = 0xb0, + .edge_sel_en = true, +}; + static const struct of_device_id mtk_dpi_of_ids[] = { + { .compatible = "mediatek,mt2701-dpi", + .data = &mt2701_conf, + }, { .compatible = "mediatek,mt8173-dpi", .data = &mt8173_conf, }, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index a2ca90fc403cb..f4fb86ab7b8dd 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -372,6 +372,7 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = { { .compatible = "mediatek,mt8173-disp-ufoe", .data = (void *)MTK_DISP_UFOE }, { .compatible = "mediatek,mt2701-dsi", .data = (void *)MTK_DSI }, { .compatible = "mediatek,mt8173-dsi", .data = (void *)MTK_DSI }, + { .compatible = "mediatek,mt2701-dpi", .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt8173-dpi", .data = (void *)MTK_DPI }, { .compatible = "mediatek,mt2701-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, { .compatible = "mediatek,mt8173-disp-mutex", .data = (void *)MTK_DISP_MUTEX }, From 0edff115c3e2b1efbd069178dd18d29a987cf6bc Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:31:57 +0200 Subject: [PATCH 16/40] applied patch 4/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013241.html --- drivers/gpu/drm/mediatek/Makefile | 4 +- drivers/gpu/drm/mediatek/mtk_hdmi.c | 91 ++++-- drivers/gpu/drm/mediatek/mtk_hdmi.h | 28 ++ drivers/gpu/drm/mediatek/mtk_hdmi_phy.c | 157 +++++++++ drivers/gpu/drm/mediatek/mtk_hdmi_regs.h | 1 + .../gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c | 307 ++++++++++++++++++ .../gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c | 129 +------- 7 files changed, 568 insertions(+), 149 deletions(-) create mode 100644 drivers/gpu/drm/mediatek/mtk_hdmi_phy.c create mode 100644 drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index ce83c396a7421..44464893c1cba 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -18,6 +18,8 @@ obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o mediatek-drm-hdmi-objs := mtk_cec.o \ mtk_hdmi.o \ mtk_hdmi_ddc.o \ - mtk_mt8173_hdmi_phy.o + mtk_mt2701_hdmi_phy.o \ + mtk_mt8173_hdmi_phy.o \ + mtk_hdmi_phy.o obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 59a11026dceb4..85e280962aade 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -233,6 +233,7 @@ static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black) static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) { struct arm_smccc_res res; + struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(hdmi->phy); /* * MT8173 HDMI hardware has an output control bit to enable/disable HDMI @@ -240,8 +241,13 @@ static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable) * The ARM trusted firmware provides an API for the HDMI driver to set * this control bit to enable HDMI output in supervisor mode. */ - arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, 0x80000000, - 0, 0, 0, 0, 0, &res); + if (hdmi_phy->conf && hdmi_phy->conf->tz_enabled) + arm_smccc_smc(MTK_SIP_SET_AUTHORIZED_SECURE_REG, 0x14000904, + 0x80000000, 0, 0, 0, 0, 0, &res); + else + regmap_update_bits(hdmi->sys_regmap, + hdmi->sys_offset + HDMI_SYS_CFG20, + HDMI_PSECUR_EN, enable ? 0 : HDMI_PSECUR_EN); regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20, HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0); @@ -1437,6 +1443,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, struct platform_device *cec_pdev; struct regmap *regmap; struct resource *mem; + const char *phy_name; int ret; ret = mtk_hdmi_get_all_clk(hdmi, np); @@ -1445,9 +1452,20 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, return ret; } + ret = of_property_read_string(np, "phy-names", &phy_name); + if (ret < 0) { + dev_err(dev, "Failed to read phy-names: %d\n", ret); + return ret; + } + hdmi->phy = devm_phy_get(dev, phy_name); + if (IS_ERR(hdmi->phy)) { + ret = PTR_ERR(hdmi->phy); + dev_err(dev, "Failed to get HDMI PHY: %d\n", ret); + return ret; + } + /* The CEC module handles HDMI hotplug detection */ - cec_np = of_find_compatible_node(np->parent, NULL, - "mediatek,mt8173-cec"); + cec_np = of_parse_phandle(np, "cec", 0); if (!cec_np) { dev_err(dev, "Failed to find CEC node\n"); return -EINVAL; @@ -1486,8 +1504,14 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, return PTR_ERR(hdmi->regs); remote = of_graph_get_remote_node(np, 1, 0); - if (!remote) - return -EINVAL; + if (!remote) { + i2c_np = of_parse_phandle(np, "ddc-i2c-bus", 0); + if (!i2c_np) { + dev_err(dev, "Failed to find ddc-i2c-bus node\n"); + return -EINVAL; + } + goto find_ddc_adpt; + } if (!of_device_is_compatible(remote, "hdmi-connector")) { hdmi->next_bridge = of_drm_find_bridge(remote); @@ -1507,6 +1531,7 @@ static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi, } of_node_put(remote); +find_ddc_adpt: hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np); if (!hdmi->ddc_adpt) { dev_err(dev, "Failed to get ddc i2c adapter by node\n"); @@ -1575,6 +1600,11 @@ static int mtk_hdmi_audio_hw_params(struct device *dev, void *data, hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT; hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS; break; + case HDMI_SPDIF: + hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM; + hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16; + hdmi_params.aud_input_type = HDMI_AUD_INPUT_SPDIF; + break; default: dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__, daifmt->fmt); @@ -1650,15 +1680,16 @@ static void mtk_hdmi_register_audio_driver(struct device *dev) .max_i2s_channels = 2, .i2s = 1, }; - struct platform_device *pdev; - - pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, - PLATFORM_DEVID_AUTO, &codec_data, - sizeof(codec_data)); - if (IS_ERR(pdev)) + static struct platform_device *pdev; + + if (!pdev) { + pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME, + PLATFORM_DEVID_NONE, + &codec_data, + sizeof(codec_data)); + DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME); + } return; - - DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME); } static int mtk_drm_hdmi_probe(struct platform_device *pdev) @@ -1672,18 +1703,12 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return -ENOMEM; hdmi->dev = dev; + mtk_hdmi_register_audio_driver(dev); ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev); if (ret) return ret; - hdmi->phy = devm_phy_get(dev, "hdmi"); - if (IS_ERR(hdmi->phy)) { - ret = PTR_ERR(hdmi->phy); - dev_err(dev, "Failed to get HDMI PHY: %d\n", ret); - return ret; - } - platform_set_drvdata(pdev, hdmi); ret = mtk_hdmi_output_init(hdmi); @@ -1692,8 +1717,6 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) return ret; } - mtk_hdmi_register_audio_driver(dev); - hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs; hdmi->bridge.of_node = pdev->dev.of_node; drm_bridge_add(&hdmi->bridge); @@ -1704,7 +1727,6 @@ static int mtk_drm_hdmi_probe(struct platform_device *pdev) goto err_bridge_remove; } - dev_dbg(dev, "mediatek hdmi probe success\n"); return 0; err_bridge_remove: @@ -1773,8 +1795,25 @@ static struct platform_driver * const mtk_hdmi_drivers[] = { static int __init mtk_hdmitx_init(void) { - return platform_register_drivers(mtk_hdmi_drivers, - ARRAY_SIZE(mtk_hdmi_drivers)); + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(mtk_hdmi_drivers); i++) { + ret = platform_driver_register(mtk_hdmi_drivers[i]); + if (ret < 0) { + pr_err("Failed to register %s driver: %d\n", + mtk_hdmi_drivers[i]->driver.name, ret); + goto err; + } + } + + return 0; + +err: + while (--i >= 0) + platform_driver_unregister(mtk_hdmi_drivers[i]); + + return ret; } static void __exit mtk_hdmitx_exit(void) diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h index 6371b3de1ff6f..a4546b83329ff 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h @@ -13,11 +13,39 @@ */ #ifndef _MTK_HDMI_CTRL_H #define _MTK_HDMI_CTRL_H +#include +#include +#include +#include + +struct mtk_hdmi_phy_conf { + bool tz_enabled; + const struct clk_ops *hdmi_phy_clk_ops; + const struct phy_ops *hdmi_phy_dev_ops; +}; + +struct mtk_hdmi_phy { + void __iomem *regs; + struct device *dev; + struct mtk_hdmi_phy_conf *conf; + struct clk *pll; + struct clk_hw pll_hw; + unsigned long pll_rate; + unsigned char drv_imp_clk; + unsigned char drv_imp_d2; + unsigned char drv_imp_d1; + unsigned char drv_imp_d0; + unsigned int ibias; + unsigned int ibias_up; +}; struct platform_driver; extern struct platform_driver mtk_cec_driver; extern struct platform_driver mtk_hdmi_ddc_driver; extern struct platform_driver mtk_hdmi_phy_driver; +extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf; +extern struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf; + #endif /* _MTK_HDMI_CTRL_H */ diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c new file mode 100644 index 0000000000000..f04927ea95c9f --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_phy.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Jie Qiu + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk_hdmi.h" + +static void mtk_hdmi_phy_clk_get_ops(struct mtk_hdmi_phy *hdmi_phy, + const struct clk_ops **ops) +{ + if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_clk_ops) + *ops = hdmi_phy->conf->hdmi_phy_clk_ops; + else + dev_err(hdmi_phy->dev, "Failed to get clk ops of phy\n"); +} + +static const struct phy_ops * +mtk_hdmi_phy_dev_get_ops(const struct mtk_hdmi_phy *hdmi_phy) +{ + if (hdmi_phy && hdmi_phy->conf && hdmi_phy->conf->hdmi_phy_dev_ops) + return hdmi_phy->conf->hdmi_phy_dev_ops; + dev_err(hdmi_phy->dev, "Failed to get dev ops of phy\n"); + return NULL; +} + +static int mtk_hdmi_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct mtk_hdmi_phy *hdmi_phy; + struct resource *mem; + struct clk *ref_clk; + const char *ref_clk_name; + struct clk_init_data clk_init = { + .num_parents = 1, + .parent_names = (const char * const *)&ref_clk_name, + .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, + }; + + struct phy *phy; + struct phy_provider *phy_provider; + int ret; + + hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); + if (!hdmi_phy) + return -ENOMEM; + + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hdmi_phy->regs = devm_ioremap_resource(dev, mem); + if (IS_ERR(hdmi_phy->regs)) { + ret = PTR_ERR(hdmi_phy->regs); + dev_err(dev, "Failed to get memory resource: %d\n", ret); + return ret; + } + + ref_clk = devm_clk_get(dev, "pll_ref"); + if (IS_ERR(ref_clk)) { + ret = PTR_ERR(ref_clk); + dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n", + ret); + return ret; + } + ref_clk_name = __clk_get_name(ref_clk); + + ret = of_property_read_string(dev->of_node, "clock-output-names", + &clk_init.name); + if (ret < 0) { + dev_err(dev, "Failed to read clock-output-names: %d\n", ret); + return ret; + } + + hdmi_phy->dev = dev; + hdmi_phy->conf = + (struct mtk_hdmi_phy_conf *)of_device_get_match_data(dev); + mtk_hdmi_phy_clk_get_ops(hdmi_phy, &clk_init.ops); + hdmi_phy->pll_hw.init = &clk_init; + hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw); + if (IS_ERR(hdmi_phy->pll)) { + ret = PTR_ERR(hdmi_phy->pll); + dev_err(dev, "Failed to register PLL: %d\n", ret); + return ret; + } + + ret = of_property_read_u32(dev->of_node, "mediatek,ibias", + &hdmi_phy->ibias); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret); + return ret; + } + + ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up", + &hdmi_phy->ibias_up); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret); + return ret; + } + + dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n"); + hdmi_phy->drv_imp_clk = 0x30; + hdmi_phy->drv_imp_d2 = 0x30; + hdmi_phy->drv_imp_d1 = 0x30; + hdmi_phy->drv_imp_d0 = 0x30; + + phy = devm_phy_create(dev, NULL, mtk_hdmi_phy_dev_get_ops(hdmi_phy)); + if (IS_ERR(phy)) { + dev_err(dev, "Failed to create HDMI PHY\n"); + return PTR_ERR(phy); + } + phy_set_drvdata(phy, hdmi_phy); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) { + dev_err(dev, "Failed to register HDMI PHY\n"); + return PTR_ERR(phy_provider); + } + + return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, + hdmi_phy->pll); +} + +static int mtk_hdmi_phy_remove(struct platform_device *pdev) +{ + return 0; +} + +static const struct of_device_id mtk_hdmi_phy_match[] = { + { .compatible = "mediatek,mt2701-hdmi-phy", + .data = &mtk_hdmi_phy_2701_conf, + }, + { .compatible = "mediatek,mt8173-hdmi-phy", + .data = &mtk_hdmi_phy_8173_conf, + }, + {}, +}; + +struct platform_driver mtk_hdmi_phy_driver = { + .probe = mtk_hdmi_phy_probe, + .remove = mtk_hdmi_phy_remove, + .driver = { + .name = "mediatek-hdmi-phy", + .of_match_table = mtk_hdmi_phy_match, + }, +}; + +MODULE_DESCRIPTION("MediaTek HDMI PHY Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h index a5cb07d12c9c3..e53c6646571c0 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h +++ b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h @@ -227,6 +227,7 @@ #define DEEP_COLOR_EN BIT(0) #define HDMI_AUDIO_TEST_SEL BIT(8) #define HDMI2P0_EN BIT(11) +#define HDMI_PSECUR_EN BIT(15) #define HDMI_OUT_FIFO_EN BIT(16) #define HDMI_OUT_FIFO_CLK_INV BIT(17) #define MHL_MODE_ON BIT(28) diff --git a/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c new file mode 100644 index 0000000000000..d4ea263c39204 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_mt2701_hdmi_phy.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + *Copyright (c) 2018 MediaTek Inc. + *Author: Chunhui Dai + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtk_hdmi.h" + +#define HDMI_CON0 0x00 +#define RG_HDMITX_DRV_IBIAS (0) +#define RG_HDMITX_DRV_IBIAS_MASK (0x3F << 0) +#define RG_HDMITX_EN_SER (12) +#define RG_HDMITX_EN_SER_MASK (0x0F << 12) +#define RG_HDMITX_EN_SLDO (16) +#define RG_HDMITX_EN_SLDO_MASK (0x0F << 16) +#define RG_HDMITX_EN_PRED (20) +#define RG_HDMITX_EN_PRED_MASK (0x0F << 20) +#define RG_HDMITX_EN_IMP (24) +#define RG_HDMITX_EN_IMP_MASK (0x0F << 24) +#define RG_HDMITX_EN_DRV (28) +#define RG_HDMITX_EN_DRV_MASK (0x0F << 28) + +#define HDMI_CON1 0x04 +#define RG_HDMITX_PRED_IBIAS (18) +#define RG_HDMITX_PRED_IBIAS_MASK (0x0F << 18) +#define RG_HDMITX_PRED_IMP (0x01 << 22) +#define RG_HDMITX_DRV_IMP (26) +#define RG_HDMITX_DRV_IMP_MASK (0x3F << 26) + +#define HDMI_CON2 0x08 +#define RG_HDMITX_EN_TX_CKLDO (0x01 << 0) +#define RG_HDMITX_EN_TX_POSDIV (0x01 << 1) +#define RG_HDMITX_TX_POSDIV (3) +#define RG_HDMITX_TX_POSDIV_MASK (0x03 << 3) +#define RG_HDMITX_EN_MBIAS (0x01 << 6) +#define RG_HDMITX_MBIAS_LPF_EN (0x01 << 7) + +#define HDMI_CON4 0x10 +#define RG_HDMITX_RESERVE_MASK (0xFFFFFFFF << 0) + +#define HDMI_CON6 0x18 +#define RG_HTPLL_BR (0) +#define RG_HTPLL_BR_MASK (0x03 << 0) +#define RG_HTPLL_BC (2) +#define RG_HTPLL_BC_MASK (0x03 << 2) +#define RG_HTPLL_BP (4) +#define RG_HTPLL_BP_MASK (0x0F << 4) +#define RG_HTPLL_IR (8) +#define RG_HTPLL_IR_MASK (0x0F << 8) +#define RG_HTPLL_IC (12) +#define RG_HTPLL_IC_MASK (0x0F << 12) +#define RG_HTPLL_POSDIV (16) +#define RG_HTPLL_POSDIV_MASK (0x03 << 16) +#define RG_HTPLL_PREDIV (18) +#define RG_HTPLL_PREDIV_MASK (0x03 << 18) +#define RG_HTPLL_FBKSEL (20) +#define RG_HTPLL_FBKSEL_MASK (0x03 << 20) +#define RG_HTPLL_RLH_EN (0x01 << 22) +#define RG_HTPLL_FBKDIV (24) +#define RG_HTPLL_FBKDIV_MASK (0x7F << 24) +#define RG_HTPLL_EN (0x01 << 31) + +#define HDMI_CON7 0x1c +#define RG_HTPLL_AUTOK_EN (0x01 << 23) +#define RG_HTPLL_DIVEN (28) +#define RG_HTPLL_DIVEN_MASK (0x07 << 28) + +static inline struct mtk_hdmi_phy *to_mtk_hdmi_pll(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_hdmi_phy, pll_hw); +} + +static inline void mtk_hdmi_pll_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset, + u32 val, u32 mask) +{ + u32 tmp = readl(hdmi_phy->regs + offset) & ~mask; + + tmp |= (val & mask); + writel(tmp, hdmi_phy->regs + offset); +} + +static int mtk_hdmi_pll_enable(struct clk_hw *hw) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw); + + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN, + RG_HTPLL_AUTOK_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV), + RG_HTPLL_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS, + RG_HDMITX_EN_MBIAS); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, RG_HTPLL_EN, RG_HTPLL_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO, + RG_HDMITX_EN_TX_CKLDO); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SLDO), + RG_HDMITX_EN_SLDO_MASK); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN, + RG_HDMITX_MBIAS_LPF_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV, + RG_HDMITX_EN_TX_POSDIV); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SER), + RG_HDMITX_EN_SER_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_PRED), + RG_HDMITX_EN_PRED_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_DRV), + RG_HDMITX_EN_DRV_MASK); + usleep_range(80, 100); + return 0; +} + +static void mtk_hdmi_pll_disable(struct clk_hw *hw) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw); + + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_DRV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_PRED_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SER_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_POSDIV); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_MBIAS_LPF_EN); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SLDO_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_CKLDO); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_EN); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_MBIAS); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, 0, RG_HTPLL_AUTOK_EN); + usleep_range(80, 100); +} + +static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw); + u32 pos_div; + + if (rate <= 64000000) + pos_div = 3; + else if (rate <= 12800000) + pos_div = 1; + else + pos_div = 1; + + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_PREDIV), + RG_HTPLL_PREDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV), + RG_HTPLL_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IC), + RG_HTPLL_IC_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_IR), + RG_HTPLL_IR_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, (pos_div << RG_HDMITX_TX_POSDIV), + RG_HDMITX_TX_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (1 << RG_HTPLL_FBKSEL), + RG_HTPLL_FBKSEL_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (19 << RG_HTPLL_FBKDIV), + RG_HTPLL_FBKDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, (0x2 << RG_HTPLL_DIVEN), + RG_HTPLL_DIVEN_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0xc << RG_HTPLL_BP), + RG_HTPLL_BP_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x2 << RG_HTPLL_BC), + RG_HTPLL_BC_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x1 << RG_HTPLL_BR), + RG_HTPLL_BR_MASK); + + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, 0, RG_HDMITX_PRED_IMP); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, (0x3 << RG_HDMITX_PRED_IBIAS), + RG_HDMITX_PRED_IBIAS_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0x0 << RG_HDMITX_EN_IMP), + RG_HDMITX_EN_IMP_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON1, (0x28 << RG_HDMITX_DRV_IMP), + RG_HDMITX_DRV_IMP_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON4, 0x28, RG_HDMITX_RESERVE_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xa << RG_HDMITX_DRV_IBIAS), + RG_HDMITX_DRV_IBIAS_MASK); + return 0; +} + +static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw); + + hdmi_phy->pll_rate = rate; + return rate; +} + +static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_pll(hw); + + return hdmi_phy->pll_rate; +} + +static const struct clk_ops mtk_hdmi_phy_pll_ops = { + .enable = mtk_hdmi_pll_enable, + .disable = mtk_hdmi_pll_disable, + .set_rate = mtk_hdmi_pll_set_rate, + .round_rate = mtk_hdmi_pll_round_rate, + .recalc_rate = mtk_hdmi_pll_recalc_rate, +}; + +static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy) +{ + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, RG_HTPLL_AUTOK_EN, + RG_HTPLL_AUTOK_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, (0x3 << RG_HTPLL_POSDIV), + RG_HTPLL_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_MBIAS, + RG_HDMITX_EN_MBIAS); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, RG_HTPLL_EN, RG_HTPLL_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_CKLDO, + RG_HDMITX_EN_TX_CKLDO); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SLDO), + RG_HDMITX_EN_SLDO_MASK); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_MBIAS_LPF_EN, + RG_HDMITX_MBIAS_LPF_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, RG_HDMITX_EN_TX_POSDIV, + RG_HDMITX_EN_TX_POSDIV); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_SER), + RG_HDMITX_EN_SER_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_PRED), + RG_HDMITX_EN_PRED_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, (0xf << RG_HDMITX_EN_DRV), + RG_HDMITX_EN_DRV_MASK); + usleep_range(80, 100); +} + +static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy) +{ + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_DRV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_PRED_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SER_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_POSDIV); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_MBIAS_LPF_EN); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON0, 0, RG_HDMITX_EN_SLDO_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_TX_CKLDO); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_EN); + usleep_range(80, 100); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON2, 0, RG_HDMITX_EN_MBIAS); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_POSDIV_MASK); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON6, 0, RG_HTPLL_RLH_EN); + mtk_hdmi_pll_mask(hdmi_phy, HDMI_CON7, 0, RG_HTPLL_AUTOK_EN); + usleep_range(80, 100); +} + +static int mtk_hdmi_phy_power_on(struct phy *phy) +{ + struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy); + int ret; + + ret = clk_prepare_enable(hdmi_phy->pll); + if (ret < 0) + return ret; + + mtk_hdmi_phy_enable_tmds(hdmi_phy); + + return 0; +} + +static int mtk_hdmi_phy_power_off(struct phy *phy) +{ + struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy); + + mtk_hdmi_phy_disable_tmds(hdmi_phy); + clk_disable_unprepare(hdmi_phy->pll); + + return 0; +} + +static const struct phy_ops mtk_hdmi_phy_dev_ops = { + .power_on = mtk_hdmi_phy_power_on, + .power_off = mtk_hdmi_phy_power_off, + .owner = THIS_MODULE, +}; + +struct mtk_hdmi_phy_conf mtk_hdmi_phy_2701_conf = { + .tz_enabled = false, + .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops, + .hdmi_phy_dev_ops = &mtk_hdmi_phy_dev_ops, +}; + +MODULE_AUTHOR("Chunhui Dai "); +MODULE_DESCRIPTION("MediaTek HDMI PHY Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c index 51cb9cfb6646e..1a35fdd405d81 100644 --- a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c +++ b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c @@ -21,6 +21,7 @@ #include #include #include +#include "mtk_hdmi.h" #define HDMI_CON0 0x00 #define RG_HDMITX_PLL_EN BIT(31) @@ -123,20 +124,6 @@ #define RGS_HDMITX_5T1_EDG (0xf << 4) #define RGS_HDMITX_PLUG_TST BIT(0) -struct mtk_hdmi_phy { - void __iomem *regs; - struct device *dev; - struct clk *pll; - struct clk_hw pll_hw; - unsigned long pll_rate; - u8 drv_imp_clk; - u8 drv_imp_d2; - u8 drv_imp_d1; - u8 drv_imp_d0; - u32 ibias; - u32 ibias_up; -}; - static const u8 PREDIV[3][4] = { {0x0, 0x0, 0x0, 0x0}, /* 27Mhz */ {0x1, 0x1, 0x1, 0x1}, /* 74Mhz */ @@ -367,7 +354,7 @@ static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw, return hdmi_phy->pll_rate; } -static const struct clk_ops mtk_hdmi_pll_ops = { +static const struct clk_ops mtk_hdmi_phy_pll_ops = { .prepare = mtk_hdmi_pll_prepare, .unprepare = mtk_hdmi_pll_unprepare, .set_rate = mtk_hdmi_pll_set_rate, @@ -414,118 +401,16 @@ static int mtk_hdmi_phy_power_off(struct phy *phy) return 0; } -static const struct phy_ops mtk_hdmi_phy_ops = { +static const struct phy_ops mtk_hdmi_phy_dev_ops = { .power_on = mtk_hdmi_phy_power_on, .power_off = mtk_hdmi_phy_power_off, .owner = THIS_MODULE, }; -static int mtk_hdmi_phy_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct mtk_hdmi_phy *hdmi_phy; - struct resource *mem; - struct clk *ref_clk; - const char *ref_clk_name; - struct clk_init_data clk_init = { - .ops = &mtk_hdmi_pll_ops, - .num_parents = 1, - .parent_names = (const char * const *)&ref_clk_name, - .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE, - }; - struct phy *phy; - struct phy_provider *phy_provider; - int ret; - - hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); - if (!hdmi_phy) - return -ENOMEM; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - hdmi_phy->regs = devm_ioremap_resource(dev, mem); - if (IS_ERR(hdmi_phy->regs)) { - ret = PTR_ERR(hdmi_phy->regs); - dev_err(dev, "Failed to get memory resource: %d\n", ret); - return ret; - } - - ref_clk = devm_clk_get(dev, "pll_ref"); - if (IS_ERR(ref_clk)) { - ret = PTR_ERR(ref_clk); - dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n", - ret); - return ret; - } - ref_clk_name = __clk_get_name(ref_clk); - - ret = of_property_read_string(dev->of_node, "clock-output-names", - &clk_init.name); - if (ret < 0) { - dev_err(dev, "Failed to read clock-output-names: %d\n", ret); - return ret; - } - - hdmi_phy->pll_hw.init = &clk_init; - hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw); - if (IS_ERR(hdmi_phy->pll)) { - ret = PTR_ERR(hdmi_phy->pll); - dev_err(dev, "Failed to register PLL: %d\n", ret); - return ret; - } - - ret = of_property_read_u32(dev->of_node, "mediatek,ibias", - &hdmi_phy->ibias); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret); - return ret; - } - - ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up", - &hdmi_phy->ibias_up); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret); - return ret; - } - - dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n"); - hdmi_phy->drv_imp_clk = 0x30; - hdmi_phy->drv_imp_d2 = 0x30; - hdmi_phy->drv_imp_d1 = 0x30; - hdmi_phy->drv_imp_d0 = 0x30; - - phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops); - if (IS_ERR(phy)) { - dev_err(dev, "Failed to create HDMI PHY\n"); - return PTR_ERR(phy); - } - phy_set_drvdata(phy, hdmi_phy); - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); - - hdmi_phy->dev = dev; - return of_clk_add_provider(dev->of_node, of_clk_src_simple_get, - hdmi_phy->pll); -} - -static int mtk_hdmi_phy_remove(struct platform_device *pdev) -{ - return 0; -} - -static const struct of_device_id mtk_hdmi_phy_match[] = { - { .compatible = "mediatek,mt8173-hdmi-phy", }, - {}, -}; - -struct platform_driver mtk_hdmi_phy_driver = { - .probe = mtk_hdmi_phy_probe, - .remove = mtk_hdmi_phy_remove, - .driver = { - .name = "mediatek-hdmi-phy", - .of_match_table = mtk_hdmi_phy_match, - }, +struct mtk_hdmi_phy_conf mtk_hdmi_phy_8173_conf = { + .tz_enabled = true, + .hdmi_phy_clk_ops = &mtk_hdmi_phy_pll_ops, + .hdmi_phy_dev_ops = &mtk_hdmi_phy_dev_ops, }; MODULE_AUTHOR("Jie Qiu "); From 67e04f0ae338d0b6261c30f93382e1216738ba0c Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:32:47 +0200 Subject: [PATCH 17/40] applied patch 5/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013236.html --- drivers/gpu/drm/mediatek/mtk_drm_ddp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c index 8130f3dab6614..289a68c6731f6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp.c @@ -35,6 +35,7 @@ #define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 #define DISP_REG_CONFIG_OUT_SEL 0x04c #define DISP_REG_CONFIG_DSI_SEL 0x050 +#define DISP_REG_CONFIG_DPI_SEL 0x064 #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) @@ -84,7 +85,10 @@ #define OVL_MOUT_EN_RDMA 0x1 #define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 +#define BLS_TO_DPI_RDMA1_TO_DSI 0x2 #define DSI_SEL_IN_BLS 0x0 +#define DPI_SEL_IN_BLS 0x0 +#define DSI_SEL_IN_RDMA 0x1 struct mtk_disp_mutex { int id; @@ -189,9 +193,17 @@ static void mtk_ddp_sout_sel(void __iomem *config_regs, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next) { - if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) + if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, config_regs + DISP_REG_CONFIG_OUT_SEL); + } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) { + writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI, + config_regs + DISP_REG_CONFIG_OUT_SEL); + writel_relaxed(DSI_SEL_IN_RDMA, + config_regs + DISP_REG_CONFIG_DSI_SEL); + writel_relaxed(DPI_SEL_IN_BLS, + config_regs + DISP_REG_CONFIG_DPI_SEL); + } } void mtk_ddp_add_comp_to_path(void __iomem *config_regs, From b9c0e0e5538b2b50c0bd52d7a852b475eb0de51f Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:33:37 +0200 Subject: [PATCH 18/40] applied patch 6/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013238.html --- drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index 4672317e3ad12..d38a5303f8fcb 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -283,7 +283,7 @@ int mtk_ddp_comp_init(struct device *dev, struct device_node *node, comp->irq = of_irq_get(node, 0); comp->clk = of_clk_get(node, 0); if (IS_ERR(comp->clk)) - comp->clk = NULL; + return PTR_ERR(comp->clk); /* Only DMA capable components need the LARB property */ comp->larb_dev = NULL; From 097de7d41498b6c3a164fb91e539a60a75015ffa Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 14:34:09 +0200 Subject: [PATCH 19/40] apllied patch 7/7 from http://lists.infradead.org/pipermail/linux-mediatek/2018-May/013235.html --- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 37 +++++++++++++++++++++++--- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 4 +-- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index f4fb86ab7b8dd..05333769d862d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "mtk_drm_crtc.h" #include "mtk_drm_ddp.h" @@ -133,7 +135,7 @@ static const struct drm_mode_config_funcs mtk_drm_mode_config_funcs = { .atomic_commit = mtk_atomic_commit, }; -static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { +static enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, @@ -141,12 +143,12 @@ static const enum mtk_ddp_comp_id mt2701_mtk_ddp_main[] = { DDP_COMPONENT_DSI0, }; -static const enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { +static enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, }; -static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { +static enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, DDP_COMPONENT_AAL, @@ -157,7 +159,7 @@ static const enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { DDP_COMPONENT_PWM0, }; -static const enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { +static enum mtk_ddp_comp_id mt8173_mtk_ddp_ext[] = { DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1, DDP_COMPONENT_GAMMA, @@ -411,6 +413,7 @@ static int mtk_drm_probe(struct platform_device *pdev) /* Iterate over sibling DISP function blocks */ for_each_child_of_node(dev->of_node->parent, node) { + struct device_node *port, *ep, *remote; const struct of_device_id *of_id; enum mtk_ddp_comp_type comp_type; int comp_id; @@ -470,6 +473,32 @@ static int mtk_drm_probe(struct platform_device *pdev) private->ddp_comp[comp_id] = comp; } + + if (comp_type != MTK_DSI && comp_type != MTK_DPI) { + port = of_graph_get_port_by_id(node, 0); + if (!port) + continue; + ep = of_get_child_by_name(port, "endpoint"); + of_node_put(port); + if (!ep) + continue; + remote = of_graph_get_remote_port_parent(ep); + of_node_put(ep); + if (!remote) + continue; + of_id = of_match_node(mtk_ddp_comp_dt_ids, remote); + if (!of_id) + continue; + comp_type = (enum mtk_ddp_comp_type)of_id->data; + for (i = 0; i < private->data->main_len - 1; i++) + if (private->data->main_path[i] == comp_id) + private->data->main_path[i + 1] = + mtk_ddp_comp_get_id(node, comp_type); + for (i = 0; i < private->data->ext_len - 1; i++) + if (private->data->ext_path[i] == comp_id) + private->data->ext_path[i + 1] = + mtk_ddp_comp_get_id(node, comp_type); + } } if (!private->mutex_node) { diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index c3378c452c0a0..2bcba8eb06f46 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -29,9 +29,9 @@ struct drm_property; struct regmap; struct mtk_mmsys_driver_data { - const enum mtk_ddp_comp_id *main_path; + enum mtk_ddp_comp_id *main_path; unsigned int main_len; - const enum mtk_ddp_comp_id *ext_path; + enum mtk_ddp_comp_id *ext_path; unsigned int ext_len; bool shadow_register; }; From 460603c6f4947de420f43f19847bb8f0142c8fff Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 15:17:11 +0200 Subject: [PATCH 20/40] [defconfig] added drm/hdmi-options --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 5406772115853..fc8b032707dfc 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -396,3 +396,10 @@ CONFIG_WLAN_VENDOR_ST=n CONFIG_WLAN_VENDOR_TI=n CONFIG_WLAN_VENDOR_ZYDAS=n CONFIG_WLAN_VENDOR_QUANTENNA=n + + + +#Graphic +CONFIG_DRM=y +CONFIG_DRM_MEDIATEK=y +CONFIG_DRM_MEDIATEK_HDMI=y From 3489a72d225646c45a2c3b4a2fdcacb49fde4b49 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Mon, 21 May 2018 22:03:56 +0200 Subject: [PATCH 21/40] [DTS] added hdmi-nodes --- arch/arm/boot/dts/mt7623.dtsi | 312 ++++++++++++++++++ arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 37 +++ drivers/iommu/Kconfig | 4 + include/dt-bindings/clock/mt2701-clk.h | 3 +- 4 files changed, 355 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index bb0c5c1bfaf7d..e6084f26a5fd5 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "skeleton64.dtsi" @@ -238,6 +239,14 @@ #interrupt-cells = <2>; interrupts = , ; + + hdmi_pin: htplg { + pins1 { + pinmux = ; + input-enable; + bias-pull-down; + }; + }; }; syscfg_pctl_a: syscfg@10005000 { @@ -273,6 +282,17 @@ clock-names = "system-clk", "rtc-clk"; }; + smi_common: smi@1000c000 { + compatible = "mediatek,mt7623-smi-common", + "mediatek,mt2701-smi-common"; + reg = <0 0x1000c000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_SMI>, + <&mmsys CLK_MM_SMI_COMMON>, + <&infracfg CLK_INFRA_SMI>; + clock-names = "apb", "smi", "async"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + pwrap: pwrap@1000d000 { compatible = "mediatek,mt7623-pwrap", "mediatek,mt2701-pwrap"; @@ -286,6 +306,25 @@ clock-names = "spi", "wrap"; }; + mipi_tx0: mipi-dphy@10010000 { + compatible = "mediatek,mt7623-mipi-tx", + "mediatek,mt2701-mipi-tx"; + reg = <0 0x10010000 0 0x90>; + clocks = <&clk26m>; + clock-output-names = "mipi_tx0_pll"; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + cec: cec@10012000 { + compatible = "mediatek,mt7623-cec", + "mediatek,mt8173-cec"; + reg = <0 0x10012000 0 0xbc>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_CEC>; + }; + cir: cir@10013000 { compatible = "mediatek,mt7623-cir"; reg = <0 0x10013000 0 0x1000>; @@ -304,6 +343,17 @@ reg = <0 0x10200100 0 0x1c>; }; + iommu: mmsys_iommu@10205000 { + compatible = "mediatek,mt7623-m4u", + "mediatek,mt2701-m4u"; + reg = <0 0x10205000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + mediatek,larbs = <&larb0 &larb1 &larb2>; + #iommu-cells = <1>; + }; + efuse: efuse@10206000 { compatible = "mediatek,mt7623-efuse", "mediatek,mt8173-efuse"; @@ -323,6 +373,20 @@ #clock-cells = <1>; }; + hdmi_phy: hdmi-phy@10209100 { + compatible = "mediatek,mt7623-hdmi-phy", + "mediatek,mt2701-hdmi-phy"; + reg = <0 0x10209100 0 0x24>; + clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; + clock-names = "pll_ref"; + clock-output-names = "hdmitx_dig_cts"; + mediatek,ibias = <0xa>; + mediatek,ibias_up = <0x1c>; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + rng: rng@1020f000 { compatible = "mediatek,mt7623-rng"; reg = <0 0x1020f000 0 0x1000>; @@ -469,6 +533,15 @@ status = "disabled"; }; + hdmiddc0: i2c@11013000 { + compatible = "mediatek,mt7623-hdmi-ddc", + "mediatek,mt8173-hdmi-ddc"; + interrupts = ; + reg = <0 0x11013000 0 0x1C>; + clocks = <&pericfg CLK_PERI_I2C3>; + clock-names = "ddc-i2c"; + }; + thermal: thermal@1100b000 { #thermal-sensor-cells = <1>; compatible = "mediatek,mt7623-thermal", @@ -661,6 +734,245 @@ status = "disabled"; }; + mali: mali@13040000 { + compatible = "arm,mali-450", "arm,mali-utgard"; + reg = <0 0x13040000 0 0x30000>, <0 0x13000000 0 0x20>; + interrupts = , + , + , + , + , + , + , + , + ; + interrupt-names = "IRQGP", "IRQGPMMU", + "IRQPP0", "IRQPPMMU0", + "IRQPP1", "IRQPPMMU1", + "IRQPP2", "IRQPPMMU2", + "IRQPP"; + larb=<&larb0>; + clocks = <&topckgen CLK_TOP_UNIVPLL_D3>, + <&topckgen CLK_TOP_MMPLL>, + <&topckgen CLK_TOP_MFG_SEL>; + clock-names = "intermediate", + "mfg_pll", + "mfg_sel"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_MFG>; + operating-points = < + 107250 1150000 + 214500 1150000 + 312000 1150000 + 416000 1150000 + >; + }; + + display_components: dispsys@14000000 { + compatible = "mediatek,mt7623-display", + "mediatek,mt2701-display"; + reg = <0 0x14000000 0 0x1000>; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + + mmsys: syscon@14000000 { + compatible = "mediatek,mt7623-mmsys", + "mediatek,mt2701-mmsys", + "syscon"; + reg = <0 0x14000000 0 0x1000>; + #clock-cells = <1>; + }; + + ovl@14007000 { + compatible = "mediatek,mt7623-disp-ovl", + "mediatek,mt2701-disp-ovl"; + reg = <0 0x14007000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_OVL>; + iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>; + mediatek,larb = <&larb0>; + }; + + disp_rdma0: rdma@14008000 { + compatible = "mediatek,mt7623-disp-rdma", + "mediatek,mt2701-disp-rdma"; + reg = <0 0x14008000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_RDMA>; + iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>; + mediatek,larb = <&larb0>; + }; + + wdma@14009000 { + compatible = "mediatek,mt7623-disp-wdma", + "mediatek,mt2701-disp-wdma"; + reg = <0 0x14009000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_WDMA>; + iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>; + mediatek,larb = <&larb0>; + }; + + bls@1400a000 { + compatible = "mediatek,mt7623-disp-bls", + "mediatek,mt2701-disp-bls"; + reg = <0 0x1400a000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_BLS>; + port { + bls_out: endpoint { + remote-endpoint = <&dpi0_in>; + }; + }; + }; + + color@1400b000 { + compatible = "mediatek,mt7623-disp-color", + "mediatek,mt2701-disp-color"; + reg = <0 0x1400b000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_COLOR>; + }; + + dsi0: dsi@1400c000 { + compatible = "mediatek,mt7623-dsi", + "mediatek,mt2701-dsi"; + reg = <0 0x1400c000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DSI_ENGINE>, <&mmsys CLK_MM_DSI_DIG>, + <&mipi_tx0>; + clock-names = "engine", "digital", "hs"; + mediatek,syscon-dsi = <&mmsys 0x138>; + phys = <&mipi_tx0>; + phy-names = "dphy"; + status = "disabled"; + }; + + mutex: mutex@1400e000 { + compatible = "mediatek,mt7623-disp-mutex", + "mediatek,mt2701-disp-mutex"; + reg = <0 0x1400e000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_MUTEX_32K>; + }; + + larb0: larb@14010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x14010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <0>; + clocks = <&mmsys CLK_MM_SMI_LARB0>, + <&mmsys CLK_MM_SMI_LARB0>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + + disp_rdma1: rdma@14012000 { + compatible = "mediatek,mt7623-disp-rdma", + "mediatek,mt2701-disp-rdma"; + reg = <0 0x14012000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_RDMA1>; + iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>; + mediatek,larb = <&larb0>; + }; + + dpi0: dpi@14014000 { + compatible = "mediatek,mt7623-dpi", + "mediatek,mt2701-dpi"; + reg = <0 0x14014000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DPI1_DIGL>, + <&mmsys CLK_MM_DPI1_ENGINE>, + <&topckgen CLK_TOP_TVDPLL>; + clock-names = "pixel", + "engine", + "pll"; + status = "disabled"; + port { + dpi0_out: endpoint@0 { + remote-endpoint = <&hdmi0_in>; + }; + + dpi0_in: endpoint@1 { + remote-endpoint = <&bls_out>; + }; + }; + }; + + hdmi0: hdmi@14015000 { + compatible = "mediatek,mt7623-hdmi", + "mediatek,mt8173-hdmi"; + reg = <0 0x14015000 0 0x400>; + clocks = <&mmsys CLK_MM_HDMI_PIXEL>, + <&mmsys CLK_MM_HDMI_PLL>, + <&mmsys CLK_MM_HDMI_AUDIO>, + <&mmsys CLK_MM_HDMI_SPDIF>; + clock-names = "pixel", "pll", "bclk", "spdif"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pin>; + phys = <&hdmi_phy>; + phy-names = "hdmi"; + mediatek,syscon-hdmi = <&mmsys 0x900>; + cec = <&cec>; + ddc-i2c-bus = <&hdmiddc0>; + assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; + assigned-clock-parents = <&hdmi_phy>; + status = "disabled"; + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; + }; + }; + }; + }; + + imgsys: syscon@15000000 { + compatible = "mediatek,mt7623-imgsys", + "mediatek,mt2701-imgsys", + "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb2: larb@15001000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x15001000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <2>; + clocks = <&imgsys CLK_IMG_SMI_COMM>, + <&imgsys CLK_IMG_SMI_COMM>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; + }; + + vdecsys: syscon@16000000 { + compatible = "mediatek,mt7623-vdecsys", + "mediatek,mt2701-vdecsys", + "syscon"; + reg = <0 0x16000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb1: larb@16010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x16010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <1>; + clocks = <&vdecsys CLK_VDEC_CKGEN>, + <&vdecsys CLK_VDEC_LARB>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>; + }; + hifsys: syscon@1a000000 { compatible = "mediatek,mt7623-hifsys", "mediatek,mt2701-hifsys", diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 024bdb7d6cca5..283875dbb0501 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -102,6 +102,13 @@ memory@80000000 { reg = <0 0x80000000 0 0x40000000>; }; + + vdd_fixed_vgpu_reg: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "vdd_fixed_vgpu"; + regulator-min-microvolt = <1150000>; + regulator-max-microvolt = <1150000>; + }; }; &cir { @@ -189,6 +196,14 @@ }; }; +&hdmi0 { + status = "okay"; +}; + +&hdmi_phy { + status = "okay"; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins_a>; @@ -201,6 +216,11 @@ status = "okay"; }; +&mali { + vdd_g3d-supply = <&vdd_fixed_vgpu_reg>; + status = "okay"; +}; + &mmc0 { pinctrl-names = "default", "state_uhs"; pinctrl-0 = <&mmc0_pins_default>; @@ -468,6 +488,18 @@ }; }; }; + + mipi_dsi_pin: mipi_dsi_pin { + pins_cmd_dat { + pinmux = , + , + , + , + , + ; + }; + + }; }; &spi0 { @@ -514,3 +546,8 @@ status = "okay"; }; +&mipi_tx0 { + pinctrl-names = "default"; + pinctrl-0 = <&mipi_dsi_pin>; + status = "okay"; +}; diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index f3a21343e636a..574bb66c3cbaf 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -363,6 +363,10 @@ config MTK_IOMMU_V1 select IOMMU_API select MEMORY select MTK_SMI + select IOMMU_DMA + select COMMON_CLK_MT2701_MMSYS + select COMMON_CLK_MT2701_IMGSYS + select COMMON_CLK_MT2701_VDECSYS help Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is Multimedia Memory Managememt Unit. This option enables remapping of diff --git a/include/dt-bindings/clock/mt2701-clk.h b/include/dt-bindings/clock/mt2701-clk.h index 24e93dfcee9ff..c634c83975132 100644 --- a/include/dt-bindings/clock/mt2701-clk.h +++ b/include/dt-bindings/clock/mt2701-clk.h @@ -194,7 +194,8 @@ #define CLK_APMIXED_HADDS2PLL 11 #define CLK_APMIXED_AUD2PLL 12 #define CLK_APMIXED_TVD2PLL 13 -#define CLK_APMIXED_NR 14 +#define CLK_APMIXED_HDMI_REF 14 +#define CLK_APMIXED_NR 15 /* DDRPHY */ From 6f131df7e0bb62faec7d913fa6f7ca80f3fcb3a4 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 May 2018 17:54:51 +0200 Subject: [PATCH 22/40] Revert "[DTS] added hdmi-nodes" to use official patch This reverts commit 3489a72d225646c45a2c3b4a2fdcacb49fde4b49. --- arch/arm/boot/dts/mt7623.dtsi | 312 ------------------ arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 37 --- drivers/iommu/Kconfig | 4 - include/dt-bindings/clock/mt2701-clk.h | 3 +- 4 files changed, 1 insertion(+), 355 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index e6084f26a5fd5..bb0c5c1bfaf7d 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "skeleton64.dtsi" @@ -239,14 +238,6 @@ #interrupt-cells = <2>; interrupts = , ; - - hdmi_pin: htplg { - pins1 { - pinmux = ; - input-enable; - bias-pull-down; - }; - }; }; syscfg_pctl_a: syscfg@10005000 { @@ -282,17 +273,6 @@ clock-names = "system-clk", "rtc-clk"; }; - smi_common: smi@1000c000 { - compatible = "mediatek,mt7623-smi-common", - "mediatek,mt2701-smi-common"; - reg = <0 0x1000c000 0 0x1000>; - clocks = <&infracfg CLK_INFRA_SMI>, - <&mmsys CLK_MM_SMI_COMMON>, - <&infracfg CLK_INFRA_SMI>; - clock-names = "apb", "smi", "async"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; - }; - pwrap: pwrap@1000d000 { compatible = "mediatek,mt7623-pwrap", "mediatek,mt2701-pwrap"; @@ -306,25 +286,6 @@ clock-names = "spi", "wrap"; }; - mipi_tx0: mipi-dphy@10010000 { - compatible = "mediatek,mt7623-mipi-tx", - "mediatek,mt2701-mipi-tx"; - reg = <0 0x10010000 0 0x90>; - clocks = <&clk26m>; - clock-output-names = "mipi_tx0_pll"; - #clock-cells = <0>; - #phy-cells = <0>; - status = "disabled"; - }; - - cec: cec@10012000 { - compatible = "mediatek,mt7623-cec", - "mediatek,mt8173-cec"; - reg = <0 0x10012000 0 0xbc>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_CEC>; - }; - cir: cir@10013000 { compatible = "mediatek,mt7623-cir"; reg = <0 0x10013000 0 0x1000>; @@ -343,17 +304,6 @@ reg = <0 0x10200100 0 0x1c>; }; - iommu: mmsys_iommu@10205000 { - compatible = "mediatek,mt7623-m4u", - "mediatek,mt2701-m4u"; - reg = <0 0x10205000 0 0x1000>; - interrupts = ; - clocks = <&infracfg CLK_INFRA_M4U>; - clock-names = "bclk"; - mediatek,larbs = <&larb0 &larb1 &larb2>; - #iommu-cells = <1>; - }; - efuse: efuse@10206000 { compatible = "mediatek,mt7623-efuse", "mediatek,mt8173-efuse"; @@ -373,20 +323,6 @@ #clock-cells = <1>; }; - hdmi_phy: hdmi-phy@10209100 { - compatible = "mediatek,mt7623-hdmi-phy", - "mediatek,mt2701-hdmi-phy"; - reg = <0 0x10209100 0 0x24>; - clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; - clock-names = "pll_ref"; - clock-output-names = "hdmitx_dig_cts"; - mediatek,ibias = <0xa>; - mediatek,ibias_up = <0x1c>; - #clock-cells = <0>; - #phy-cells = <0>; - status = "disabled"; - }; - rng: rng@1020f000 { compatible = "mediatek,mt7623-rng"; reg = <0 0x1020f000 0 0x1000>; @@ -533,15 +469,6 @@ status = "disabled"; }; - hdmiddc0: i2c@11013000 { - compatible = "mediatek,mt7623-hdmi-ddc", - "mediatek,mt8173-hdmi-ddc"; - interrupts = ; - reg = <0 0x11013000 0 0x1C>; - clocks = <&pericfg CLK_PERI_I2C3>; - clock-names = "ddc-i2c"; - }; - thermal: thermal@1100b000 { #thermal-sensor-cells = <1>; compatible = "mediatek,mt7623-thermal", @@ -734,245 +661,6 @@ status = "disabled"; }; - mali: mali@13040000 { - compatible = "arm,mali-450", "arm,mali-utgard"; - reg = <0 0x13040000 0 0x30000>, <0 0x13000000 0 0x20>; - interrupts = , - , - , - , - , - , - , - , - ; - interrupt-names = "IRQGP", "IRQGPMMU", - "IRQPP0", "IRQPPMMU0", - "IRQPP1", "IRQPPMMU1", - "IRQPP2", "IRQPPMMU2", - "IRQPP"; - larb=<&larb0>; - clocks = <&topckgen CLK_TOP_UNIVPLL_D3>, - <&topckgen CLK_TOP_MMPLL>, - <&topckgen CLK_TOP_MFG_SEL>; - clock-names = "intermediate", - "mfg_pll", - "mfg_sel"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_MFG>; - operating-points = < - 107250 1150000 - 214500 1150000 - 312000 1150000 - 416000 1150000 - >; - }; - - display_components: dispsys@14000000 { - compatible = "mediatek,mt7623-display", - "mediatek,mt2701-display"; - reg = <0 0x14000000 0 0x1000>; - power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; - }; - - mmsys: syscon@14000000 { - compatible = "mediatek,mt7623-mmsys", - "mediatek,mt2701-mmsys", - "syscon"; - reg = <0 0x14000000 0 0x1000>; - #clock-cells = <1>; - }; - - ovl@14007000 { - compatible = "mediatek,mt7623-disp-ovl", - "mediatek,mt2701-disp-ovl"; - reg = <0 0x14007000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_OVL>; - iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>; - mediatek,larb = <&larb0>; - }; - - disp_rdma0: rdma@14008000 { - compatible = "mediatek,mt7623-disp-rdma", - "mediatek,mt2701-disp-rdma"; - reg = <0 0x14008000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_RDMA>; - iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>; - mediatek,larb = <&larb0>; - }; - - wdma@14009000 { - compatible = "mediatek,mt7623-disp-wdma", - "mediatek,mt2701-disp-wdma"; - reg = <0 0x14009000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_WDMA>; - iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>; - mediatek,larb = <&larb0>; - }; - - bls@1400a000 { - compatible = "mediatek,mt7623-disp-bls", - "mediatek,mt2701-disp-bls"; - reg = <0 0x1400a000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_BLS>; - port { - bls_out: endpoint { - remote-endpoint = <&dpi0_in>; - }; - }; - }; - - color@1400b000 { - compatible = "mediatek,mt7623-disp-color", - "mediatek,mt2701-disp-color"; - reg = <0 0x1400b000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_COLOR>; - }; - - dsi0: dsi@1400c000 { - compatible = "mediatek,mt7623-dsi", - "mediatek,mt2701-dsi"; - reg = <0 0x1400c000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DSI_ENGINE>, <&mmsys CLK_MM_DSI_DIG>, - <&mipi_tx0>; - clock-names = "engine", "digital", "hs"; - mediatek,syscon-dsi = <&mmsys 0x138>; - phys = <&mipi_tx0>; - phy-names = "dphy"; - status = "disabled"; - }; - - mutex: mutex@1400e000 { - compatible = "mediatek,mt7623-disp-mutex", - "mediatek,mt2701-disp-mutex"; - reg = <0 0x1400e000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_MUTEX_32K>; - }; - - larb0: larb@14010000 { - compatible = "mediatek,mt7623-smi-larb", - "mediatek,mt2701-smi-larb"; - reg = <0 0x14010000 0 0x1000>; - mediatek,smi = <&smi_common>; - mediatek,larb-id = <0>; - clocks = <&mmsys CLK_MM_SMI_LARB0>, - <&mmsys CLK_MM_SMI_LARB0>; - clock-names = "apb", "smi"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; - }; - - disp_rdma1: rdma@14012000 { - compatible = "mediatek,mt7623-disp-rdma", - "mediatek,mt2701-disp-rdma"; - reg = <0 0x14012000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DISP_RDMA1>; - iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>; - mediatek,larb = <&larb0>; - }; - - dpi0: dpi@14014000 { - compatible = "mediatek,mt7623-dpi", - "mediatek,mt2701-dpi"; - reg = <0 0x14014000 0 0x1000>; - interrupts = ; - clocks = <&mmsys CLK_MM_DPI1_DIGL>, - <&mmsys CLK_MM_DPI1_ENGINE>, - <&topckgen CLK_TOP_TVDPLL>; - clock-names = "pixel", - "engine", - "pll"; - status = "disabled"; - port { - dpi0_out: endpoint@0 { - remote-endpoint = <&hdmi0_in>; - }; - - dpi0_in: endpoint@1 { - remote-endpoint = <&bls_out>; - }; - }; - }; - - hdmi0: hdmi@14015000 { - compatible = "mediatek,mt7623-hdmi", - "mediatek,mt8173-hdmi"; - reg = <0 0x14015000 0 0x400>; - clocks = <&mmsys CLK_MM_HDMI_PIXEL>, - <&mmsys CLK_MM_HDMI_PLL>, - <&mmsys CLK_MM_HDMI_AUDIO>, - <&mmsys CLK_MM_HDMI_SPDIF>; - clock-names = "pixel", "pll", "bclk", "spdif"; - pinctrl-names = "default"; - pinctrl-0 = <&hdmi_pin>; - phys = <&hdmi_phy>; - phy-names = "hdmi"; - mediatek,syscon-hdmi = <&mmsys 0x900>; - cec = <&cec>; - ddc-i2c-bus = <&hdmiddc0>; - assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; - assigned-clock-parents = <&hdmi_phy>; - status = "disabled"; - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - - hdmi0_in: endpoint { - remote-endpoint = <&dpi0_out>; - }; - }; - }; - }; - - imgsys: syscon@15000000 { - compatible = "mediatek,mt7623-imgsys", - "mediatek,mt2701-imgsys", - "syscon"; - reg = <0 0x15000000 0 0x1000>; - #clock-cells = <1>; - }; - - larb2: larb@15001000 { - compatible = "mediatek,mt7623-smi-larb", - "mediatek,mt2701-smi-larb"; - reg = <0 0x15001000 0 0x1000>; - mediatek,smi = <&smi_common>; - mediatek,larb-id = <2>; - clocks = <&imgsys CLK_IMG_SMI_COMM>, - <&imgsys CLK_IMG_SMI_COMM>; - clock-names = "apb", "smi"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; - }; - - vdecsys: syscon@16000000 { - compatible = "mediatek,mt7623-vdecsys", - "mediatek,mt2701-vdecsys", - "syscon"; - reg = <0 0x16000000 0 0x1000>; - #clock-cells = <1>; - }; - - larb1: larb@16010000 { - compatible = "mediatek,mt7623-smi-larb", - "mediatek,mt2701-smi-larb"; - reg = <0 0x16010000 0 0x1000>; - mediatek,smi = <&smi_common>; - mediatek,larb-id = <1>; - clocks = <&vdecsys CLK_VDEC_CKGEN>, - <&vdecsys CLK_VDEC_LARB>; - clock-names = "apb", "smi"; - power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>; - }; - hifsys: syscon@1a000000 { compatible = "mediatek,mt7623-hifsys", "mediatek,mt2701-hifsys", diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 283875dbb0501..024bdb7d6cca5 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -102,13 +102,6 @@ memory@80000000 { reg = <0 0x80000000 0 0x40000000>; }; - - vdd_fixed_vgpu_reg: fixedregulator@0 { - compatible = "regulator-fixed"; - regulator-name = "vdd_fixed_vgpu"; - regulator-min-microvolt = <1150000>; - regulator-max-microvolt = <1150000>; - }; }; &cir { @@ -196,14 +189,6 @@ }; }; -&hdmi0 { - status = "okay"; -}; - -&hdmi_phy { - status = "okay"; -}; - &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins_a>; @@ -216,11 +201,6 @@ status = "okay"; }; -&mali { - vdd_g3d-supply = <&vdd_fixed_vgpu_reg>; - status = "okay"; -}; - &mmc0 { pinctrl-names = "default", "state_uhs"; pinctrl-0 = <&mmc0_pins_default>; @@ -488,18 +468,6 @@ }; }; }; - - mipi_dsi_pin: mipi_dsi_pin { - pins_cmd_dat { - pinmux = , - , - , - , - , - ; - }; - - }; }; &spi0 { @@ -546,8 +514,3 @@ status = "okay"; }; -&mipi_tx0 { - pinctrl-names = "default"; - pinctrl-0 = <&mipi_dsi_pin>; - status = "okay"; -}; diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 574bb66c3cbaf..f3a21343e636a 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -363,10 +363,6 @@ config MTK_IOMMU_V1 select IOMMU_API select MEMORY select MTK_SMI - select IOMMU_DMA - select COMMON_CLK_MT2701_MMSYS - select COMMON_CLK_MT2701_IMGSYS - select COMMON_CLK_MT2701_VDECSYS help Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is Multimedia Memory Managememt Unit. This option enables remapping of diff --git a/include/dt-bindings/clock/mt2701-clk.h b/include/dt-bindings/clock/mt2701-clk.h index c634c83975132..24e93dfcee9ff 100644 --- a/include/dt-bindings/clock/mt2701-clk.h +++ b/include/dt-bindings/clock/mt2701-clk.h @@ -194,8 +194,7 @@ #define CLK_APMIXED_HADDS2PLL 11 #define CLK_APMIXED_AUD2PLL 12 #define CLK_APMIXED_TVD2PLL 13 -#define CLK_APMIXED_HDMI_REF 14 -#define CLK_APMIXED_NR 15 +#define CLK_APMIXED_NR 14 /* DDRPHY */ From d92f26a13fef2f65c12a88d5edb85fc64f112ad1 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 May 2018 17:56:49 +0200 Subject: [PATCH 23/40] added iommu-patch (crash on boot) --- drivers/iommu/mtk_iommu_v1.c | 54 ++++++++++++++---------------------- 1 file changed, 21 insertions(+), 33 deletions(-) diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c index 542930cd183d0..1b1b775948970 100644 --- a/drivers/iommu/mtk_iommu_v1.c +++ b/drivers/iommu/mtk_iommu_v1.c @@ -418,20 +418,12 @@ static int mtk_iommu_create_mapping(struct device *dev, m4udev->archdata.iommu = mtk_mapping; } - ret = arm_iommu_attach_device(dev, mtk_mapping); - if (ret) - goto err_release_mapping; - return 0; - -err_release_mapping: - arm_iommu_release_mapping(mtk_mapping); - m4udev->archdata.iommu = NULL; - return ret; } static int mtk_iommu_add_device(struct device *dev) { + struct dma_iommu_mapping *mtk_mapping; struct of_phandle_args iommu_spec; struct of_phandle_iterator it; struct mtk_iommu_data *data; @@ -452,15 +444,30 @@ static int mtk_iommu_add_device(struct device *dev) if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops) return -ENODEV; /* Not a iommu client device */ - data = dev->iommu_fwspec->iommu_priv; - iommu_device_link(&data->iommu, dev); - - group = iommu_group_get_for_dev(dev); + /* + * This is a short-term bodge because the ARM DMA code doesn't + * understand multi-device groups, but we have to call into it + * successfully (and not just rely on a normal IOMMU API attach + * here) in order to set the correct DMA API ops on @dev. + */ + group = iommu_group_alloc(); if (IS_ERR(group)) return PTR_ERR(group); + err = iommu_group_add_device(group, dev); iommu_group_put(group); - return 0; + if (err) + return err; + + data = dev->iommu_fwspec->iommu_priv; + mtk_mapping = data->dev->archdata.iommu; + err = arm_iommu_attach_device(dev, mtk_mapping); + if (err) { + iommu_group_remove_device(dev); + return err; + } + + return iommu_device_link(&data->iommu, dev);; } static void mtk_iommu_remove_device(struct device *dev) @@ -477,24 +484,6 @@ static void mtk_iommu_remove_device(struct device *dev) iommu_fwspec_free(dev); } -static struct iommu_group *mtk_iommu_device_group(struct device *dev) -{ - struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv; - - if (!data) - return ERR_PTR(-ENODEV); - - /* All the client devices are in the same m4u iommu-group */ - if (!data->m4u_group) { - data->m4u_group = iommu_group_alloc(); - if (IS_ERR(data->m4u_group)) - dev_err(dev, "Failed to allocate M4U IOMMU group\n"); - } else { - iommu_group_ref_get(data->m4u_group); - } - return data->m4u_group; -} - static int mtk_iommu_hw_init(const struct mtk_iommu_data *data) { u32 regval; @@ -547,7 +536,6 @@ static struct iommu_ops mtk_iommu_ops = { .iova_to_phys = mtk_iommu_iova_to_phys, .add_device = mtk_iommu_add_device, .remove_device = mtk_iommu_remove_device, - .device_group = mtk_iommu_device_group, .pgsize_bitmap = ~0UL << MT2701_IOMMU_PAGE_SHIFT, }; From 208e140a62defde905ae792d5fa6433ad812b3ec Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 May 2018 17:59:12 +0200 Subject: [PATCH 24/40] hdmi-clock-patch --- drivers/clk/mediatek/clk-mt2701.c | 8 ++++++-- include/dt-bindings/clock/mt2701-clk.h | 16 ++++++++-------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index deca7527f92f6..4dda8988b2f09 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -46,8 +46,6 @@ static const struct mtk_fixed_clk top_fixed_clks[] = { 340 * MHZ), FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m", 340 * MHZ), - FIXED_CLK(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_dig_cts", "clk26m", - 300 * MHZ), FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m", 27 * MHZ), FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m", @@ -977,6 +975,10 @@ static const struct mtk_pll_data apmixed_plls[] = { 21, 0x2d0, 4, 0x0, 0x2d4, 0), }; +static const struct mtk_fixed_factor apmixed_fixed_divs[] = { + FACTOR(CLK_APMIXED_HDMI_REF, "hdmi_ref", "tvdpll", 1, 1), +}; + static int mtk_apmixedsys_init(struct platform_device *pdev) { struct clk_onecell_data *clk_data; @@ -988,6 +990,8 @@ static int mtk_apmixedsys_init(struct platform_device *pdev) mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls), clk_data); + mtk_clk_register_factors(apmixed_fixed_divs, ARRAY_SIZE(apmixed_fixed_divs), + clk_data); return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); } diff --git a/include/dt-bindings/clock/mt2701-clk.h b/include/dt-bindings/clock/mt2701-clk.h index 24e93dfcee9ff..1956ebba4ab9f 100644 --- a/include/dt-bindings/clock/mt2701-clk.h +++ b/include/dt-bindings/clock/mt2701-clk.h @@ -171,13 +171,12 @@ #define CLK_TOP_8BDAC 151 #define CLK_TOP_WBG_DIG_416M 152 #define CLK_TOP_DPI 153 -#define CLK_TOP_HDMITX_CLKDIG_CTS 154 -#define CLK_TOP_DSI0_LNTC_DSI 155 -#define CLK_TOP_AUD_EXT1 156 -#define CLK_TOP_AUD_EXT2 157 -#define CLK_TOP_NFI1X_PAD 158 -#define CLK_TOP_AXISEL_D4 159 -#define CLK_TOP_NR 160 +#define CLK_TOP_DSI0_LNTC_DSI 154 +#define CLK_TOP_AUD_EXT1 155 +#define CLK_TOP_AUD_EXT2 156 +#define CLK_TOP_NFI1X_PAD 157 +#define CLK_TOP_AXISEL_D4 158 +#define CLK_TOP_NR 159 /* APMIXEDSYS */ @@ -194,7 +193,8 @@ #define CLK_APMIXED_HADDS2PLL 11 #define CLK_APMIXED_AUD2PLL 12 #define CLK_APMIXED_TVD2PLL 13 -#define CLK_APMIXED_NR 14 +#define CLK_APMIXED_HDMI_REF 14 +#define CLK_APMIXED_NR 15 /* DDRPHY */ From e9646b91cb889be710ff0e756ec4adc64e814b0a Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 May 2018 18:03:15 +0200 Subject: [PATCH 25/40] added hdmi-pinfunc-patch --- include/dt-bindings/pinctrl/mt7623-pinfunc.h | 108 ++++++++++++++++++- 1 file changed, 105 insertions(+), 3 deletions(-) diff --git a/include/dt-bindings/pinctrl/mt7623-pinfunc.h b/include/dt-bindings/pinctrl/mt7623-pinfunc.h index 2d6a7b1d7be21..09eb970959194 100644 --- a/include/dt-bindings/pinctrl/mt7623-pinfunc.h +++ b/include/dt-bindings/pinctrl/mt7623-pinfunc.h @@ -23,20 +23,26 @@ #define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_GPIO5 (MTK_PIN_NO(5) | 0) #define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_PWRAP_SPICK2_I (MTK_PIN_NO(5) | 1) +#define MT7623_PIN_5_PWRAP_SPI0_CK2_FUNC_ANT_SEL1 (MTK_PIN_NO(5) | 5) #define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_GPIO6 (MTK_PIN_NO(6) | 0) #define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_PWRAP_SPICS2_B_I (MTK_PIN_NO(6) | 1) +#define MT7623_PIN_6_PWRAP_SPI0_CSN2_FUNC_ANT_SEL0 (MTK_PIN_NO(6) | 5) #define MT7623_PIN_7_SPI1_CSN_FUNC_GPIO7 (MTK_PIN_NO(7) | 0) #define MT7623_PIN_7_SPI1_CSN_FUNC_SPI1_CS (MTK_PIN_NO(7) | 1) +#define MT7623_PIN_7_SPI1_CSN_FUNC_KCOL0 (MTK_PIN_NO(7) | 4) #define MT7623_PIN_8_SPI1_MI_FUNC_GPIO8 (MTK_PIN_NO(8) | 0) #define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MI (MTK_PIN_NO(8) | 1) #define MT7623_PIN_8_SPI1_MI_FUNC_SPI1_MO (MTK_PIN_NO(8) | 2) +#define MT7623_PIN_8_SPI1_MI_FUNC_KCOL1 (MTK_PIN_NO(8) | 4) #define MT7623_PIN_9_SPI1_MO_FUNC_GPIO9 (MTK_PIN_NO(9) | 0) #define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MO (MTK_PIN_NO(9) | 1) #define MT7623_PIN_9_SPI1_MO_FUNC_SPI1_MI (MTK_PIN_NO(9) | 2) +#define MT7623_PIN_9_SPI1_MO_FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(9) | 3) +#define MT7623_PIN_9_SPI1_MO_FUNC_KCOL2 (MTK_PIN_NO(9) | 4) #define MT7623_PIN_10_RTC32K_CK_FUNC_GPIO10 (MTK_PIN_NO(10) | 0) #define MT7623_PIN_10_RTC32K_CK_FUNC_RTC32K_CK (MTK_PIN_NO(10) | 1) @@ -53,6 +59,7 @@ #define MT7623_PIN_14_GPIO14_FUNC_GPIO14 (MTK_PIN_NO(14) | 0) #define MT7623_PIN_14_GPIO14_FUNC_URXD2 (MTK_PIN_NO(14) | 1) #define MT7623_PIN_14_GPIO14_FUNC_UTXD2 (MTK_PIN_NO(14) | 2) +#define MT7623_PIN_14_GPIO14_FUNC_SRCCLKENAI2 (MTK_PIN_NO(14) | 5) #define MT7623_PIN_15_GPIO15_FUNC_GPIO15 (MTK_PIN_NO(15) | 0) #define MT7623_PIN_15_GPIO15_FUNC_UTXD2 (MTK_PIN_NO(15) | 1) @@ -60,88 +67,139 @@ #define MT7623_PIN_18_PCM_CLK_FUNC_GPIO18 (MTK_PIN_NO(18) | 0) #define MT7623_PIN_18_PCM_CLK_FUNC_PCM_CLK0 (MTK_PIN_NO(18) | 1) +#define MT7623_PIN_18_PCM_CLK_FUNC_MRG_CLK (MTK_PIN_NO(18) | 2) +#define MT7623_PIN_18_PCM_CLK_FUNC_MM_TEST_CK (MTK_PIN_NO(18) | 4) +#define MT7623_PIN_18_PCM_CLK_FUNC_CONN_DSP_JCK (MTK_PIN_NO(18) | 5) #define MT7623_PIN_18_PCM_CLK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(18) | 6) #define MT7623_PIN_19_PCM_SYNC_FUNC_GPIO19 (MTK_PIN_NO(19) | 0) #define MT7623_PIN_19_PCM_SYNC_FUNC_PCM_SYNC (MTK_PIN_NO(19) | 1) +#define MT7623_PIN_19_PCM_SYNC_FUNC_MRG_SYNC (MTK_PIN_NO(19) | 2) +#define MT7623_PIN_19_PCM_SYNC_FUNC_CONN_DSP_JINTP (MTK_PIN_NO(19) | 5) #define MT7623_PIN_19_PCM_SYNC_FUNC_AP_PCM_SYNC (MTK_PIN_NO(19) | 6) #define MT7623_PIN_20_PCM_RX_FUNC_GPIO20 (MTK_PIN_NO(20) | 0) #define MT7623_PIN_20_PCM_RX_FUNC_PCM_RX (MTK_PIN_NO(20) | 1) +#define MT7623_PIN_20_PCM_RX_FUNC_MRG_RX (MTK_PIN_NO(20) | 2) +#define MT7623_PIN_20_PCM_RX_FUNC_MRG_TX (MTK_PIN_NO(20) | 3) #define MT7623_PIN_20_PCM_RX_FUNC_PCM_TX (MTK_PIN_NO(20) | 4) +#define MT7623_PIN_20_PCM_RX_FUNC_CONN_DSP_JDI (MTK_PIN_NO(20) | 5) #define MT7623_PIN_20_PCM_RX_FUNC_AP_PCM_RX (MTK_PIN_NO(20) | 6) #define MT7623_PIN_21_PCM_TX_FUNC_GPIO21 (MTK_PIN_NO(21) | 0) #define MT7623_PIN_21_PCM_TX_FUNC_PCM_TX (MTK_PIN_NO(21) | 1) +#define MT7623_PIN_21_PCM_TX_FUNC_MRG_TX (MTK_PIN_NO(21) | 2) +#define MT7623_PIN_21_PCM_TX_FUNC_MRG_RX (MTK_PIN_NO(21) | 3) #define MT7623_PIN_21_PCM_TX_FUNC_PCM_RX (MTK_PIN_NO(21) | 4) +#define MT7623_PIN_21_PCM_TX_FUNC_CONN_DSP_JMS (MTK_PIN_NO(21) | 5) #define MT7623_PIN_21_PCM_TX_FUNC_AP_PCM_TX (MTK_PIN_NO(21) | 6) #define MT7623_PIN_22_EINT0_FUNC_GPIO22 (MTK_PIN_NO(22) | 0) #define MT7623_PIN_22_EINT0_FUNC_UCTS0 (MTK_PIN_NO(22) | 1) #define MT7623_PIN_22_EINT0_FUNC_PCIE0_PERST_N (MTK_PIN_NO(22) | 2) +#define MT7623_PIN_22_EINT0_FUNC_KCOL3 (MTK_PIN_NO(22) | 3) +#define MT7623_PIN_22_EINT0_FUNC_CONN_DSP_JDO (MTK_PIN_NO(22) | 4) +#define MT7623_PIN_22_EINT0_FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(22) | 5) #define MT7623_PIN_23_EINT1_FUNC_GPIO23 (MTK_PIN_NO(23) | 0) #define MT7623_PIN_23_EINT1_FUNC_URTS0 (MTK_PIN_NO(23) | 1) #define MT7623_PIN_23_EINT1_FUNC_PCIE1_PERST_N (MTK_PIN_NO(23) | 2) +#define MT7623_PIN_23_EINT1_FUNC_KCOL2 (MTK_PIN_NO(23) | 3) +#define MT7623_PIN_23_EINT1_FUNC_CONN_MCU_TDO (MTK_PIN_NO(23) | 4) +#define MT7623_PIN_23_EINT1_FUNC_EXT_FRAME_SYNC (MTK_PIN_NO(23) | 5) #define MT7623_PIN_24_EINT2_FUNC_GPIO24 (MTK_PIN_NO(24) | 0) #define MT7623_PIN_24_EINT2_FUNC_UCTS1 (MTK_PIN_NO(24) | 1) #define MT7623_PIN_24_EINT2_FUNC_PCIE2_PERST_N (MTK_PIN_NO(24) | 2) +#define MT7623_PIN_24_EINT2_FUNC_KCOL1 (MTK_PIN_NO(24) | 3) +#define MT7623_PIN_24_EINT2_FUNC_CONN_MCU_DBGACK_N (MTK_PIN_NO(24) | 4) #define MT7623_PIN_25_EINT3_FUNC_GPIO25 (MTK_PIN_NO(25) | 0) #define MT7623_PIN_25_EINT3_FUNC_URTS1 (MTK_PIN_NO(25) | 1) +#define MT7623_PIN_25_EINT3_FUNC_KCOL0 (MTK_PIN_NO(25) | 3) +#define MT7623_PIN_25_EINT3_FUNC_CONN_MCU_DBGI_N (MTK_PIN_NO(25) | 4) #define MT7623_PIN_26_EINT4_FUNC_GPIO26 (MTK_PIN_NO(26) | 0) #define MT7623_PIN_26_EINT4_FUNC_UCTS3 (MTK_PIN_NO(26) | 1) +#define MT7623_PIN_26_EINT4_FUNC_DRV_VBUS_P1 (MTK_PIN_NO(26) | 2) +#define MT7623_PIN_26_EINT4_FUNC_KROW3 (MTK_PIN_NO(26) | 3) +#define MT7623_PIN_26_EINT4_FUNC_CONN_MCU_TCK0 (MTK_PIN_NO(26) | 4) +#define MT7623_PIN_26_EINT4_FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(26) | 5) #define MT7623_PIN_26_EINT4_FUNC_PCIE2_WAKE_N (MTK_PIN_NO(26) | 6) #define MT7623_PIN_27_EINT5_FUNC_GPIO27 (MTK_PIN_NO(27) | 0) #define MT7623_PIN_27_EINT5_FUNC_URTS3 (MTK_PIN_NO(27) | 1) +#define MT7623_PIN_27_EINT5_FUNC_IDDIG_P1 (MTK_PIN_NO(27) | 2) +#define MT7623_PIN_27_EINT5_FUNC_KROW2 (MTK_PIN_NO(27) | 3) +#define MT7623_PIN_27_EINT5_FUNC_CONN_MCU_TDI (MTK_PIN_NO(27) | 4) #define MT7623_PIN_27_EINT5_FUNC_PCIE1_WAKE_N (MTK_PIN_NO(27) | 6) #define MT7623_PIN_28_EINT6_FUNC_GPIO28 (MTK_PIN_NO(28) | 0) #define MT7623_PIN_28_EINT6_FUNC_DRV_VBUS (MTK_PIN_NO(28) | 1) +#define MT7623_PIN_28_EINT6_FUNC_KROW1 (MTK_PIN_NO(28) | 3) +#define MT7623_PIN_28_EINT6_FUNC_CONN_MCU_TRST_B (MTK_PIN_NO(28) | 4) #define MT7623_PIN_28_EINT6_FUNC_PCIE0_WAKE_N (MTK_PIN_NO(28) | 6) #define MT7623_PIN_29_EINT7_FUNC_GPIO29 (MTK_PIN_NO(29) | 0) #define MT7623_PIN_29_EINT7_FUNC_IDDIG (MTK_PIN_NO(29) | 1) #define MT7623_PIN_29_EINT7_FUNC_MSDC1_WP (MTK_PIN_NO(29) | 2) +#define MT7623_PIN_29_EINT7_FUNC_KROW0 (MTK_PIN_NO(29) | 3) +#define MT7623_PIN_29_EINT7_FUNC_CONN_MCU_TMS (MTK_PIN_NO(29) | 4) +#define MT7623_PIN_29_EINT7_FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(29) | 5) #define MT7623_PIN_29_EINT7_FUNC_PCIE2_PERST_N (MTK_PIN_NO(29) | 6) #define MT7623_PIN_33_I2S1_DATA_FUNC_GPIO33 (MTK_PIN_NO(33) | 0) #define MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA (MTK_PIN_NO(33) | 1) +#define MT7623_PIN_33_I2S1_DATA_FUNC_I2S1_DATA_BYPS (MTK_PIN_NO(33) | 2) #define MT7623_PIN_33_I2S1_DATA_FUNC_PCM_TX (MTK_PIN_NO(33) | 3) +#define MT7623_PIN_33_I2S1_DATA_FUNC_IMG_TEST_CK (MTK_PIN_NO(33) | 4) +#define MT7623_PIN_33_I2S1_DATA_FUNC_G1_RXD0 (MTK_PIN_NO(33) | 5) #define MT7623_PIN_33_I2S1_DATA_FUNC_AP_PCM_TX (MTK_PIN_NO(33) | 6) #define MT7623_PIN_34_I2S1_DATA_IN_FUNC_GPIO34 (MTK_PIN_NO(34) | 0) #define MT7623_PIN_34_I2S1_DATA_IN_FUNC_I2S1_DATA_IN (MTK_PIN_NO(34) | 1) #define MT7623_PIN_34_I2S1_DATA_IN_FUNC_PCM_RX (MTK_PIN_NO(34) | 3) +#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_VDEC_TEST_CK (MTK_PIN_NO(34) | 4) +#define MT7623_PIN_34_I2S1_DATA_IN_FUNC_G1_RXD1 (MTK_PIN_NO(34) | 5) #define MT7623_PIN_34_I2S1_DATA_IN_FUNC_AP_PCM_RX (MTK_PIN_NO(34) | 6) #define MT7623_PIN_35_I2S1_BCK_FUNC_GPIO35 (MTK_PIN_NO(35) | 0) #define MT7623_PIN_35_I2S1_BCK_FUNC_I2S1_BCK (MTK_PIN_NO(35) | 1) #define MT7623_PIN_35_I2S1_BCK_FUNC_PCM_CLK0 (MTK_PIN_NO(35) | 3) +#define MT7623_PIN_35_I2S1_BCK_FUNC_G1_RXD2 (MTK_PIN_NO(35) | 5) #define MT7623_PIN_35_I2S1_BCK_FUNC_AP_PCM_CLKO (MTK_PIN_NO(35) | 6) #define MT7623_PIN_36_I2S1_LRCK_FUNC_GPIO36 (MTK_PIN_NO(36) | 0) #define MT7623_PIN_36_I2S1_LRCK_FUNC_I2S1_LRCK (MTK_PIN_NO(36) | 1) #define MT7623_PIN_36_I2S1_LRCK_FUNC_PCM_SYNC (MTK_PIN_NO(36) | 3) +#define MT7623_PIN_36_I2S1_LRCK_FUNC_G1_RXD3 (MTK_PIN_NO(36) | 5) #define MT7623_PIN_36_I2S1_LRCK_FUNC_AP_PCM_SYNC (MTK_PIN_NO(36) | 6) #define MT7623_PIN_37_I2S1_MCLK_FUNC_GPIO37 (MTK_PIN_NO(37) | 0) #define MT7623_PIN_37_I2S1_MCLK_FUNC_I2S1_MCLK (MTK_PIN_NO(37) | 1) +#define MT7623_PIN_37_I2S1_MCLK_FUNC_G1_RXDV (MTK_PIN_NO(37) | 5) #define MT7623_PIN_39_JTMS_FUNC_GPIO39 (MTK_PIN_NO(39) | 0) #define MT7623_PIN_39_JTMS_FUNC_JTMS (MTK_PIN_NO(39) | 1) +#define MT7623_PIN_39_JTMS_FUNC_CONN_MCU_TMS (MTK_PIN_NO(39) | 2) +#define MT7623_PIN_39_JTMS_FUNC_CONN_MCU_AICE_JMSC (MTK_PIN_NO(39) | 3) +#define MT7623_PIN_39_JTMS_FUNC_DFD_TMS_XI (MTK_PIN_NO(39) | 4) #define MT7623_PIN_40_JTCK_FUNC_GPIO40 (MTK_PIN_NO(40) | 0) #define MT7623_PIN_40_JTCK_FUNC_JTCK (MTK_PIN_NO(40) | 1) +#define MT7623_PIN_40_JTCK_FUNC_CONN_MCU_TCK1 (MTK_PIN_NO(40) | 2) +#define MT7623_PIN_40_JTCK_FUNC_CONN_MCU_AICE_JCKC (MTK_PIN_NO(40) | 3) +#define MT7623_PIN_40_JTCK_FUNC_DFD_TCK_XI (MTK_PIN_NO(40) | 4) #define MT7623_PIN_41_JTDI_FUNC_GPIO41 (MTK_PIN_NO(41) | 0) #define MT7623_PIN_41_JTDI_FUNC_JTDI (MTK_PIN_NO(41) | 1) +#define MT7623_PIN_41_JTDI_FUNC_CONN_MCU_TDI (MTK_PIN_NO(41) | 2) +#define MT7623_PIN_41_JTDI_FUNC_DFD_TDI_XI (MTK_PIN_NO(41) | 4) #define MT7623_PIN_42_JTDO_FUNC_GPIO42 (MTK_PIN_NO(42) | 0) #define MT7623_PIN_42_JTDO_FUNC_JTDO (MTK_PIN_NO(42) | 1) +#define MT7623_PIN_42_JTDO_FUNC_CONN_MCU_TDO (MTK_PIN_NO(42) | 2) +#define MT7623_PIN_42_JTDO_FUNC_DFD_TDO (MTK_PIN_NO(42) | 4) #define MT7623_PIN_43_NCLE_FUNC_GPIO43 (MTK_PIN_NO(43) | 0) #define MT7623_PIN_43_NCLE_FUNC_NCLE (MTK_PIN_NO(43) | 1) @@ -160,31 +218,40 @@ #define MT7623_PIN_47_NREB_FUNC_GPIO47 (MTK_PIN_NO(47) | 0) #define MT7623_PIN_47_NREB_FUNC_NREB (MTK_PIN_NO(47) | 1) +#define MT7623_PIN_47_NREB_FUNC_IDDIG_P1 (MTK_PIN_NO(47) | 2) #define MT7623_PIN_48_NRNB_FUNC_GPIO48 (MTK_PIN_NO(48) | 0) #define MT7623_PIN_48_NRNB_FUNC_NRNB (MTK_PIN_NO(48) | 1) +#define MT7623_PIN_48_NRNB_FUNC_DRV_VBUS_P1 (MTK_PIN_NO(48) | 2) #define MT7623_PIN_49_I2S0_DATA_FUNC_GPIO49 (MTK_PIN_NO(49) | 0) #define MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA (MTK_PIN_NO(49) | 1) +#define MT7623_PIN_49_I2S0_DATA_FUNC_I2S0_DATA_BYPS (MTK_PIN_NO(49) | 2) #define MT7623_PIN_49_I2S0_DATA_FUNC_PCM_TX (MTK_PIN_NO(49) | 3) #define MT7623_PIN_49_I2S0_DATA_FUNC_AP_I2S_DO (MTK_PIN_NO(49) | 6) #define MT7623_PIN_53_SPI0_CSN_FUNC_GPIO53 (MTK_PIN_NO(53) | 0) #define MT7623_PIN_53_SPI0_CSN_FUNC_SPI0_CS (MTK_PIN_NO(53) | 1) +#define MT7623_PIN_53_SPI0_CSN_FUNC_SPDIF (MTK_PIN_NO(53) | 3) +#define MT7623_PIN_53_SPI0_CSN_FUNC_ADC_CK (MTK_PIN_NO(53) | 4) #define MT7623_PIN_53_SPI0_CSN_FUNC_PWM1 (MTK_PIN_NO(53) | 5) #define MT7623_PIN_54_SPI0_CK_FUNC_GPIO54 (MTK_PIN_NO(54) | 0) #define MT7623_PIN_54_SPI0_CK_FUNC_SPI0_CK (MTK_PIN_NO(54) | 1) +#define MT7623_PIN_54_SPI0_CK_FUNC_SPDIF_IN1 (MTK_PIN_NO(54) | 3) +#define MT7623_PIN_54_SPI0_CK_FUNC_ADC_DAT_IN (MTK_PIN_NO(54) | 4) #define MT7623_PIN_55_SPI0_MI_FUNC_GPIO55 (MTK_PIN_NO(55) | 0) #define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MI (MTK_PIN_NO(55) | 1) #define MT7623_PIN_55_SPI0_MI_FUNC_SPI0_MO (MTK_PIN_NO(55) | 2) #define MT7623_PIN_55_SPI0_MI_FUNC_MSDC1_WP (MTK_PIN_NO(55) | 3) +#define MT7623_PIN_55_SPI0_MI_FUNC_ADC_WS (MTK_PIN_NO(55) | 4) #define MT7623_PIN_55_SPI0_MI_FUNC_PWM2 (MTK_PIN_NO(55) | 5) #define MT7623_PIN_56_SPI0_MO_FUNC_GPIO56 (MTK_PIN_NO(56) | 0) #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MO (MTK_PIN_NO(56) | 1) #define MT7623_PIN_56_SPI0_MO_FUNC_SPI0_MI (MTK_PIN_NO(56) | 2) +#define MT7623_PIN_56_SPI0_MO_FUNC_SPDIF_IN0 (MTK_PIN_NO(56) | 3) #define MT7623_PIN_57_SDA1_FUNC_GPIO57 (MTK_PIN_NO(57) | 0) #define MT7623_PIN_57_SDA1_FUNC_SDA1 (MTK_PIN_NO(57) | 1) @@ -269,10 +336,23 @@ #define MT7623_PIN_83_LCM_RST_FUNC_GPIO83 (MTK_PIN_NO(83) | 0) #define MT7623_PIN_83_LCM_RST_FUNC_LCM_RST (MTK_PIN_NO(83) | 1) +#define MT7623_PIN_83_LCM_RST_FUNC_VDAC_CK_XI (MTK_PIN_NO(83) | 2) #define MT7623_PIN_84_DSI_TE_FUNC_GPIO84 (MTK_PIN_NO(84) | 0) #define MT7623_PIN_84_DSI_TE_FUNC_DSI_TE (MTK_PIN_NO(84) | 1) +#define MT7623_PIN_91_MIPI_TDN3_FUNC_GPIO91 (MTK_PIN_NO(91) | 0) +#define MT7623_PIN_91_MIPI_TDN3_FUNC_TDN3 (MTK_PIN_NO(91) | 1) + +#define MT7623_PIN_92_MIPI_TDP3_FUNC_GPIO92 (MTK_PIN_NO(92) | 0) +#define MT7623_PIN_92_MIPI_TDP3_FUNC_TDP3 (MTK_PIN_NO(92) | 1) + +#define MT7623_PIN_93_MIPI_TDN2_FUNC_GPIO93 (MTK_PIN_NO(93) | 0) +#define MT7623_PIN_93_MIPI_TDN2_FUNC_TDN2 (MTK_PIN_NO(93) | 1) + +#define MT7623_PIN_94_MIPI_TDP2_FUNC_GPIO94 (MTK_PIN_NO(94) | 0) +#define MT7623_PIN_94_MIPI_TDP2_FUNC_TDP2 (MTK_PIN_NO(94) | 1) + #define MT7623_PIN_95_MIPI_TCN_FUNC_GPIO95 (MTK_PIN_NO(95) | 0) #define MT7623_PIN_95_MIPI_TCN_FUNC_TCN (MTK_PIN_NO(95) | 1) @@ -291,6 +371,28 @@ #define MT7623_PIN_100_MIPI_TDP0_FUNC_GPIO100 (MTK_PIN_NO(100) | 0) #define MT7623_PIN_100_MIPI_TDP0_FUNC_TDP0 (MTK_PIN_NO(100) | 1) +#define MT7623_PIN_101_SPI2_CSN_FUNC_GPIO101 (MTK_PIN_NO(101) | 0) +#define MT7623_PIN_101_SPI2_CSN_FUNC_SPI2_CS (MTK_PIN_NO(101) | 1) +#define MT7623_PIN_101_SPI2_CSN_FUNC_SCL3 (MTK_PIN_NO(101) | 3) +#define MT7623_PIN_101_SPI2_CSN_FUNC_KROW0 (MTK_PIN_NO(101) | 4) + +#define MT7623_PIN_102_SPI2_MI_FUNC_GPIO102 (MTK_PIN_NO(102) | 0) +#define MT7623_PIN_102_SPI2_MI_FUNC_SPI2_MI (MTK_PIN_NO(102) | 1) +#define MT7623_PIN_102_SPI2_MI_FUNC_SPI2_MO (MTK_PIN_NO(102) | 2) +#define MT7623_PIN_102_SPI2_MI_FUNC_SDA3 (MTK_PIN_NO(102) | 3) +#define MT7623_PIN_102_SPI2_MI_FUNC_KROW1 (MTK_PIN_NO(102) | 4) + +#define MT7623_PIN_103_SPI2_MO_FUNC_GPIO103 (MTK_PIN_NO(103) | 0) +#define MT7623_PIN_103_SPI2_MO_FUNC_SPI2_MO (MTK_PIN_NO(103) | 1) +#define MT7623_PIN_103_SPI2_MO_FUNC_SPI2_MI (MTK_PIN_NO(103) | 2) +#define MT7623_PIN_103_SPI2_MO_FUNC_SCL3 (MTK_PIN_NO(103) | 3) +#define MT7623_PIN_103_SPI2_MO_FUNC_KROW2 (MTK_PIN_NO(103) | 4) + +#define MT7623_PIN_104_SPI2_CK_FUNC_GPIO104 (MTK_PIN_NO(104) | 0) +#define MT7623_PIN_104_SPI2_CK_FUNC_SPI2_CK (MTK_PIN_NO(104) | 1) +#define MT7623_PIN_104_SPI2_CK_FUNC_SDA3 (MTK_PIN_NO(104) | 3) +#define MT7623_PIN_104_SPI2_CK_FUNC_KROW3 (MTK_PIN_NO(104) | 4) + #define MT7623_PIN_105_MSDC1_CMD_FUNC_GPIO105 (MTK_PIN_NO(105) | 0) #define MT7623_PIN_105_MSDC1_CMD_FUNC_MSDC1_CMD (MTK_PIN_NO(105) | 1) #define MT7623_PIN_105_MSDC1_CMD_FUNC_SDA1 (MTK_PIN_NO(105) | 3) @@ -370,7 +472,7 @@ #define MT7623_PIN_121_MSDC0_DAT0_FUNC_WATCHDOG (MTK_PIN_NO(121) | 5) #define MT7623_PIN_122_GPIO122_FUNC_GPIO122 (MTK_PIN_NO(122) | 0) -#define MT7623_PIN_122_GPIO122_FUNC_TEST (MTK_PIN_NO(122) | 1) +#define MT7623_PIN_122_GPIO122_FUNC_CEC (MTK_PIN_NO(122) | 1) #define MT7623_PIN_122_GPIO122_FUNC_SDA2 (MTK_PIN_NO(122) | 4) #define MT7623_PIN_122_GPIO122_FUNC_URXD0 (MTK_PIN_NO(122) | 5) @@ -380,12 +482,12 @@ #define MT7623_PIN_123_HTPLG_FUNC_UTXD0 (MTK_PIN_NO(123) | 5) #define MT7623_PIN_124_GPIO124_FUNC_GPIO124 (MTK_PIN_NO(124) | 0) -#define MT7623_PIN_124_GPIO124_FUNC_TEST (MTK_PIN_NO(124) | 1) +#define MT7623_PIN_124_GPIO124_FUNC_HDMISCK (MTK_PIN_NO(124) | 1) #define MT7623_PIN_124_GPIO124_FUNC_SDA1 (MTK_PIN_NO(124) | 4) #define MT7623_PIN_124_GPIO124_FUNC_PWM3 (MTK_PIN_NO(124) | 5) #define MT7623_PIN_125_GPIO125_FUNC_GPIO125 (MTK_PIN_NO(125) | 0) -#define MT7623_PIN_125_GPIO125_FUNC_TEST (MTK_PIN_NO(125) | 1) +#define MT7623_PIN_125_GPIO125_FUNC_HDMISD (MTK_PIN_NO(125) | 1) #define MT7623_PIN_125_GPIO125_FUNC_SCL1 (MTK_PIN_NO(125) | 4) #define MT7623_PIN_125_GPIO125_FUNC_PWM4 (MTK_PIN_NO(125) | 5) From 77cfdeec8c0770690e7b83013f8f0a482eac7578 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Tue, 22 May 2018 18:40:23 +0200 Subject: [PATCH 26/40] [DTS] added official dts(i)-nodes for hdmi --- arch/arm/boot/dts/mt7623.dtsi | 280 +++++++++++++++++- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 81 +++++ 2 files changed, 359 insertions(+), 2 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index bb0c5c1bfaf7d..37e326203bfcc 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include "skeleton64.dtsi" @@ -28,6 +29,11 @@ compatible = "mediatek,mt7623"; interrupt-parent = <&sysirq>; + aliases { + rdma0 = &rdma0; + rdma1 = &rdma1; + }; + cpu_opp_table: opp_table { compatible = "operating-points-v2"; opp-shared; @@ -273,6 +279,18 @@ clock-names = "system-clk", "rtc-clk"; }; + + smi_common: smi@1000c000 { + compatible = "mediatek,mt7623-smi-common", + "mediatek,mt2701-smi-common"; + reg = <0 0x1000c000 0 0x1000>; + clocks = <&infracfg CLK_INFRA_SMI>, + <&mmsys CLK_MM_SMI_COMMON>, + <&infracfg CLK_INFRA_SMI>; + clock-names = "apb", "smi", "async"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + pwrap: pwrap@1000d000 { compatible = "mediatek,mt7623-pwrap", "mediatek,mt2701-pwrap"; @@ -286,6 +304,27 @@ clock-names = "spi", "wrap"; }; + mipi_tx0: mipi-dphy@10010000 { + compatible = "mediatek,mt7623-mipi-tx", + "mediatek,mt2701-mipi-tx"; + reg = <0 0x10010000 0 0x90>; + clocks = <&clk26m>; + clock-output-names = "mipi_tx0_pll"; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + + cec: cec@10012000 { + compatible = "mediatek,mt8173-cec", + "mediatek,mt7623-cec", + "mediatek,mt2701-cec"; + reg = <0 0x10012000 0 0xbc>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_CEC>; + status = "disabled"; + }; + cir: cir@10013000 { compatible = "mediatek,mt7623-cir"; reg = <0 0x10013000 0 0x1000>; @@ -304,6 +343,17 @@ reg = <0 0x10200100 0 0x1c>; }; + iommu: mmsys_iommu@10205000 { + compatible = "mediatek,mt7623-m4u", + "mediatek,mt2701-m4u"; + reg = <0 0x10205000 0 0x1000>; + interrupts = ; + clocks = <&infracfg CLK_INFRA_M4U>; + clock-names = "bclk"; + mediatek,larbs = <&larb0 &larb1 &larb2>; + #iommu-cells = <1>; + }; + efuse: efuse@10206000 { compatible = "mediatek,mt7623-efuse", "mediatek,mt8173-efuse"; @@ -323,6 +373,18 @@ #clock-cells = <1>; }; + hdmi_phy: phy@10209100 { + compatible = "mediatek,mt7623-hdmi-phy", + "mediatek,mt2701-hdmi-phy"; + reg = <0 0x10209100 0 0x24>; + clocks = <&apmixedsys CLK_APMIXED_HDMI_REF>; + clock-names = "pll_ref"; + clock-output-names = "hdmitx_dig_cts"; + #clock-cells = <0>; + #phy-cells = <0>; + status = "disabled"; + }; + rng: rng@1020f000 { compatible = "mediatek,mt7623-rng"; reg = <0 0x1020f000 0 0x1000>; @@ -469,6 +531,17 @@ status = "disabled"; }; + hdmiddc0: i2c@11013000 { + compatible = "mediatek,mt8173-hdmi-ddc", + "mediatek,mt7623-hdmi-ddc", + "mediatek,mt2701-hdmi-ddc"; + interrupts = ; + reg = <0 0x11013000 0 0x1C>; + clocks = <&pericfg CLK_PERI_I2C3>; + clock-names = "ddc-i2c"; + status = "disabled"; + }; + thermal: thermal@1100b000 { #thermal-sensor-cells = <1>; compatible = "mediatek,mt7623-thermal", @@ -661,10 +734,205 @@ status = "disabled"; }; + mmsys: syscon@14000000 { + compatible = "mediatek,mt7623-mmsys", + "mediatek,mt2701-mmsys", + "syscon"; + reg = <0 0x14000000 0 0x1000>; + #clock-cells = <1>; + }; + + display_components: dispsys@14000000 { + compatible = "mediatek,mt7623-mmsys", + "mediatek,mt2701-mmsys"; + reg = <0 0x14000000 0 0x1000>; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + + ovl@14007000 { + compatible = "mediatek,mt7623-disp-ovl", + "mediatek,mt2701-disp-ovl"; + reg = <0 0x14007000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_OVL>; + iommus = <&iommu MT2701_M4U_PORT_DISP_OVL_0>; + mediatek,larb = <&larb0>; + }; + + rdma0: rdma@14008000 { + compatible = "mediatek,mt7623-disp-rdma", + "mediatek,mt2701-disp-rdma"; + reg = <0 0x14008000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_RDMA>; + iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA>; + mediatek,larb = <&larb0>; + }; + + wdma@14009000 { + compatible = "mediatek,mt7623-disp-wdma", + "mediatek,mt2701-disp-wdma"; + reg = <0 0x14009000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_WDMA>; + iommus = <&iommu MT2701_M4U_PORT_DISP_WDMA>; + mediatek,larb = <&larb0>; + }; + + bls: bls@1400a000 { + compatible = "mediatek,mt7623-disp-pwm", + "mediatek,mt2701-disp-pwm"; + reg = <0 0x1400a000 0 0x1000>; + #pwm-cells = <2>; + clocks = <&mmsys CLK_MM_MDP_BLS_26M>, + <&mmsys CLK_MM_DISP_BLS>; + clock-names = "main", "mm"; + status = "disabled"; + }; + + color@1400b000 { + compatible = "mediatek,mt7623-disp-color", + "mediatek,mt2701-disp-color"; + reg = <0 0x1400b000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_COLOR>; + }; + + dsi: dsi@1400c000 { + compatible = "mediatek,mt7623-dsi", + "mediatek,mt2701-dsi"; + reg = <0 0x1400c000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DSI_ENGINE>, + <&mmsys CLK_MM_DSI_DIG>, + <&mipi_tx0>; + clock-names = "engine", "digital", "hs"; + phys = <&mipi_tx0>; + phy-names = "dphy"; + status = "disabled"; + }; + + mutex: mutex@1400e000 { + compatible = "mediatek,mt7623-disp-mutex", + "mediatek,mt2701-disp-mutex"; + reg = <0 0x1400e000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_MUTEX_32K>; + }; + + larb0: larb@14010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x14010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <0>; + clocks = <&mmsys CLK_MM_SMI_LARB0>, + <&mmsys CLK_MM_SMI_LARB0>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_DISP>; + }; + + rdma1: rdma@14012000 { + compatible = "mediatek,mt7623-disp-rdma", + "mediatek,mt2701-disp-rdma"; + reg = <0 0x14012000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DISP_RDMA1>; + iommus = <&iommu MT2701_M4U_PORT_DISP_RDMA1>; + mediatek,larb = <&larb0>; + }; + + dpi0: dpi@14014000 { + compatible = "mediatek,mt7623-dpi", + "mediatek,mt2701-dpi"; + reg = <0 0x14014000 0 0x1000>; + interrupts = ; + clocks = <&mmsys CLK_MM_DPI1_DIGL>, + <&mmsys CLK_MM_DPI1_ENGINE>, + <&topckgen CLK_TOP_TVDPLL>; + clock-names = "pixel", "engine", "pll"; + status = "disabled"; + }; + + hdmi0: hdmi@14015000 { + compatible = "mediatek,mt8173-hdmi", + "mediatek,mt7623-hdmi", + "mediatek,mt2701-hdmi"; + reg = <0 0x14015000 0 0x400>; + clocks = <&mmsys CLK_MM_HDMI_PIXEL>, + <&mmsys CLK_MM_HDMI_PLL>, + <&mmsys CLK_MM_HDMI_AUDIO>, + <&mmsys CLK_MM_HDMI_SPDIF>; + clock-names = "pixel", "pll", "bclk", "spdif"; + phys = <&hdmi_phy>; + phy-names = "hdmi"; + mediatek,syscon-hdmi = <&mmsys 0x900>; + cec = <&cec>; + ddc-i2c-bus = <&hdmiddc0>; + assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; + assigned-clock-parents = <&hdmi_phy>; + status = "disabled"; + }; + + imgsys: syscon@15000000 { + compatible = "mediatek,mt7623-imgsys", + "mediatek,mt2701-imgsys", + "syscon"; + reg = <0 0x15000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb2: larb@15001000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x15001000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <2>; + clocks = <&imgsys CLK_IMG_SMI_COMM>, + <&imgsys CLK_IMG_SMI_COMM>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; + }; + + jpegdec: jpegdec@15004000 { + compatible = "mediatek,mt7623-jpgdec", + "mediatek,mt2701-jpgdec"; + reg = <0 0x15004000 0 0x1000>; + interrupts = ; + clocks = <&imgsys CLK_IMG_JPGDEC_SMI>, + <&imgsys CLK_IMG_JPGDEC>; + clock-names = "jpgdec-smi", + "jpgdec"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_ISP>; + mediatek,larb = <&larb2>; + iommus = <&iommu MT2701_M4U_PORT_JPGDEC_WDMA>, + <&iommu MT2701_M4U_PORT_JPGDEC_BSDMA>; + }; + + vdecsys: syscon@16000000 { + compatible = "mediatek,mt7623-vdecsys", + "mediatek,mt2701-vdecsys", + "syscon"; + reg = <0 0x16000000 0 0x1000>; + #clock-cells = <1>; + }; + + larb1: larb@16010000 { + compatible = "mediatek,mt7623-smi-larb", + "mediatek,mt2701-smi-larb"; + reg = <0 0x16010000 0 0x1000>; + mediatek,smi = <&smi_common>; + mediatek,larb-id = <1>; + clocks = <&vdecsys CLK_VDEC_CKGEN>, + <&vdecsys CLK_VDEC_LARB>; + clock-names = "apb", "smi"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_VDEC>; + }; + hifsys: syscon@1a000000 { compatible = "mediatek,mt7623-hifsys", - "mediatek,mt2701-hifsys", - "syscon"; + "mediatek,mt2701-hifsys", + "syscon"; reg = <0 0x1a000000 0 0x1000>; #clock-cells = <1>; #reset-cells = <1>; @@ -800,4 +1068,12 @@ power-domains = <&scpsys MT2701_POWER_DOMAIN_ETH>; status = "disabled"; }; + + bdpsys: syscon@1c000000 { + compatible = "mediatek,mt7623-bdpsys", + "mediatek,mt2701-bdpsys", + "syscon"; + reg = <0 0x1c000000 0 0x1000>; + #clock-cells = <1>; + }; }; diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 024bdb7d6cca5..283cae20f9690 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -104,6 +104,15 @@ }; }; +&bls { + status = "okay"; + port { + bls_out: endpoint { + remote-endpoint = <&dpi0_in>; + }; + }; +}; + &cir { pinctrl-names = "default"; pinctrl-0 = <&cir_pins_a>; @@ -189,6 +198,49 @@ }; }; +&cec { + status = "okay"; +}; + +&hdmi_phy { + mediatek,ibias = <0xa>; + mediatek,ibias_up = <0x1c>; + status = "okay"; +}; + +&hdmiddc0 { + status = "okay"; +}; + +&dpi0 { + status = "okay"; + port { + dpi0_out: endpoint { + remote-endpoint = <&hdmi0_in>; + }; + + dpi0_in: endpoint@1 { + remote-endpoint = <&bls_out>; + }; + }; +}; + +&hdmi0 { + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <&hdmi_pin>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + hdmi0_in: endpoint { + remote-endpoint = <&dpi0_out>; + }; + }; + }; +}; + &i2c0 { pinctrl-names = "default"; pinctrl-0 = <&i2c0_pins_a>; @@ -235,6 +287,14 @@ }; }; + hdmi_pin: htplg { + pins1 { + pinmux = ; + input-enable; + bias-pull-down; + }; + }; + i2c0_pins_a: i2c@0 { pins_i2c0 { pinmux = , @@ -291,6 +351,22 @@ }; }; + + mipi_dsi_pin: mipi_dsi_pin { + pins_cmd_dat { + pinmux = , + , + , + , + , + , + , + , + , + ; + }; + }; + mmc0_pins_default: mmc0default { pins_cmd_dat { pinmux = , @@ -394,6 +470,11 @@ }; }; + pwm_bls_gpio: pwm_bls_gpio { + pins_cmd_dat { + pinmux = ; + }; + }; pwm_pins_a: pwm@0 { pins_pwm { pinmux = , From eb7b61c02a12e6d8dbb83c8306ab963bff730064 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 10:32:04 +0200 Subject: [PATCH 27/40] [defconfig] added fixed regulator for usb and DRM-Options --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index fc8b032707dfc..4aa4b37b834fc 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -161,6 +161,7 @@ CONFIG_WATCHDOG=y CONFIG_MEDIATEK_WATCHDOG=y CONFIG_MFD_MT6397=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6323=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_RC_SUPPORT=y @@ -401,5 +402,7 @@ CONFIG_WLAN_VENDOR_QUANTENNA=n #Graphic CONFIG_DRM=y +CONFIG_DRM_ARM=y +CONFIG_DRM_MALI_DISPLAY=y CONFIG_DRM_MEDIATEK=y CONFIG_DRM_MEDIATEK_HDMI=y From d05d127845511045801c118d937e385c9684ca00 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 11:59:56 +0200 Subject: [PATCH 28/40] [defconfig] adding clocks for hdmi --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 4aa4b37b834fc..3477fb41ad470 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -406,3 +406,6 @@ CONFIG_DRM_ARM=y CONFIG_DRM_MALI_DISPLAY=y CONFIG_DRM_MEDIATEK=y CONFIG_DRM_MEDIATEK_HDMI=y +CONFIG_COMMON_CLK_MT2701_MMSYS=y +CONFIG_COMMON_CLK_MT2701_IMGSYS=y +CONFIG_COMMON_CLK_MT2701_VDECSYS=y From af526fa3b11b6fcd2092626550cde0d1acb6404e Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 12:05:19 +0200 Subject: [PATCH 29/40] [dtsi] remove unneccessary clock-reference in hdmi-node --- arch/arm/boot/dts/mt7623.dtsi | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 37e326203bfcc..d1a54fa03da95 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -869,8 +869,6 @@ mediatek,syscon-hdmi = <&mmsys 0x900>; cec = <&cec>; ddc-i2c-bus = <&hdmiddc0>; - assigned-clocks = <&topckgen CLK_TOP_HDMI_SEL>; - assigned-clock-parents = <&hdmi_phy>; status = "disabled"; }; From 1db3b974f5300cc6a65b825e47f0ade746a87157 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 15:37:08 +0200 Subject: [PATCH 30/40] [DTSI] cleanup unnecessary changes from wifi-patch --- arch/arm/boot/dts/mt7623.dtsi | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index 7f3c401d4f519..6485022369f0c 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -28,7 +28,7 @@ compatible = "mediatek,mt7623"; interrupt-parent = <&sysirq>; - cpu_opp_table: opp-table { + cpu_opp_table: opp_table { compatible = "operating-points-v2"; opp-shared; @@ -147,32 +147,32 @@ }; thermal-zones { - cpu_thermal: cpu-thermal { + cpu_thermal: cpu_thermal { polling-delay-passive = <1000>; polling-delay = <1000>; thermal-sensors = <&thermal 0>; trips { - cpu_passive: cpu-passive { + cpu_passive: cpu_passive { temperature = <47000>; hysteresis = <2000>; type = "passive"; }; - cpu_active: cpu-active { + cpu_active: cpu_active { temperature = <67000>; hysteresis = <2000>; type = "active"; }; - cpu_hot: cpu-hot { + cpu_hot: cpu_hot { temperature = <87000>; hysteresis = <2000>; type = "hot"; }; - cpu-crit { + cpu_crit { temperature = <107000>; hysteresis = <2000>; type = "critical"; @@ -198,14 +198,6 @@ }; }; - watchdog: watchdog@10007000 { - compatible = "mediatek,mt7623-wdt", - "mediatek,mt6589-wdt"; - reg = <0 0x10007000 0 0x100>; - interrupts = ; - #reset-cells = <1>; - }; - timer { compatible = "arm,armv7-timer"; interrupt-parent = <&gic>; @@ -275,6 +267,14 @@ clock-names = "mm", "mfg", "ethif"; }; + watchdog: watchdog@10007000 { + compatible = "mediatek,mt7623-wdt", + "mediatek,mt6589-wdt"; + reg = <0 0x10007000 0 0x100>; + interrupts = ; + #reset-cells = <1>; + }; + timer: timer@10008000 { compatible = "mediatek,mt7623-timer", "mediatek,mt6577-timer"; From 4e70ca48161f09500d4d7390852feed3a19e6c8e Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 15:45:39 +0200 Subject: [PATCH 31/40] [DTS] cleanup unnecessary changes from wifi-patch --- arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index e3af87a26c548..c3b85c64d858b 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -57,7 +57,7 @@ regulator-always-on; }; - gpio-keys { + gpio_keys { compatible = "gpio-keys"; pinctrl-names = "default"; pinctrl-0 = <&key_pins_a>; @@ -244,14 +244,14 @@ &pio { cir_pins_a:cir@0 { - pins-cir { + pins_cir { pinmux = ; bias-disable; }; }; i2c0_pins_a: i2c@0 { - pins-i2c0 { + pins_i2c0 { pinmux = , ; bias-disable; @@ -259,7 +259,7 @@ }; i2c1_pins_a: i2c@1 { - pin-i2c1 { + pin_i2c1 { pinmux = , ; bias-disable; @@ -267,7 +267,7 @@ }; i2s0_pins_a: i2s@0 { - pin-i2s0 { + pin_i2s0 { pinmux = , , , @@ -279,7 +279,7 @@ }; i2s1_pins_a: i2s@1 { - pin-i2s1 { + pin_i2s1 { pinmux = , , , @@ -291,7 +291,7 @@ }; key_pins_a: keys@0 { - pins-keys { + pins_keys { pinmux = , ; input-enable; @@ -299,7 +299,7 @@ }; led_pins_a: leds@0 { - pins-leds { + pins_leds { pinmux = , , ; @@ -307,7 +307,7 @@ }; mmc0_pins_default: mmc0default { - pins-cmd-dat { + pins_cmd_dat { pinmux = , , , @@ -321,19 +321,19 @@ bias-pull-up; }; - pins-clk { + pins_clk { pinmux = ; bias-pull-down; }; - pins-rst { + pins_rst { pinmux = ; bias-pull-up; }; }; mmc0_pins_uhs: mmc0 { - pins-cmd-dat { + pins_cmd_dat { pinmux = , , , @@ -348,20 +348,20 @@ bias-pull-up = ; }; - pins-clk { + pins_clk { pinmux = ; drive-strength = ; bias-pull-down = ; }; - pins-rst { + pins_rst { pinmux = ; bias-pull-up; }; }; mmc1_pins_default: mmc1default { - pins-cmd-dat { + pins_cmd_dat { pinmux = , , , @@ -372,26 +372,26 @@ bias-pull-up = ; }; - pins-clk { + pins_clk { pinmux = ; bias-pull-down; drive-strength = ; }; - pins-wp { + pins_wp { pinmux = ; input-enable; bias-pull-up; }; - pins-insert { + pins_insert { pinmux = ; bias-pull-up; }; }; mmc1_pins_uhs: mmc1 { - pins-cmd-dat { + pins_cmd_dat { pinmux = , , , @@ -402,7 +402,7 @@ bias-pull-up = ; }; - pins-clk { + pins_clk { pinmux = ; drive-strength = ; bias-pull-down = ; @@ -410,7 +410,7 @@ }; pwm_pins_a: pwm@0 { - pins-pwm { + pins_pwm { pinmux = , , , @@ -420,7 +420,7 @@ }; spi0_pins_a: spi@0 { - pins-spi { + pins_spi { pinmux = , , , @@ -430,21 +430,21 @@ }; uart0_pins_a: uart@0 { - pins-dat { + pins_dat { pinmux = , ; }; }; uart1_pins_a: uart@1 { - pins-dat { + pins_dat { pinmux = , ; }; }; uart2_pins_a: uart@2 { - pins-dat { + pins_dat { pinmux = , ; }; From 9b957d4608a7c9db0b24754b439d70f316600feb Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 17:22:14 +0200 Subject: [PATCH 32/40] [DEFCONFIG] added Framebuffer-Console --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 3477fb41ad470..9ea3d092047ff 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -409,3 +409,5 @@ CONFIG_DRM_MEDIATEK_HDMI=y CONFIG_COMMON_CLK_MT2701_MMSYS=y CONFIG_COMMON_CLK_MT2701_IMGSYS=y CONFIG_COMMON_CLK_MT2701_VDECSYS=y +CONFIG_FRAMEBUFFER_CONSOLE=y + From db1ee3eaa3792149ab994e12dd6faef3926f0158 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 17:54:24 +0200 Subject: [PATCH 33/40] [defconfig] added fixed regulator for usb --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 33903633e4c43..bc4c607f4cf60 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -161,6 +161,7 @@ CONFIG_WATCHDOG=y CONFIG_MEDIATEK_WATCHDOG=y CONFIG_MFD_MT6397=y CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y CONFIG_REGULATOR_MT6323=y CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_RC_SUPPORT=y From f628e7e700f3b5c1fda242631ebb5095f5eba154 Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Wed, 23 May 2018 18:47:56 +0200 Subject: [PATCH 34/40] [DTSi] added PCIe-related nodes --- arch/arm/boot/dts/mt7623.dtsi | 105 ++++++++++++++++++ arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts | 31 ++++++ 2 files changed, 136 insertions(+) diff --git a/arch/arm/boot/dts/mt7623.dtsi b/arch/arm/boot/dts/mt7623.dtsi index d1a54fa03da95..ffff5ac9fc3b5 100644 --- a/arch/arm/boot/dts/mt7623.dtsi +++ b/arch/arm/boot/dts/mt7623.dtsi @@ -936,6 +936,111 @@ #reset-cells = <1>; }; + pcie: pcie@1a140000 { + compatible = "mediatek,mt7623-pcie"; + device_type = "pci"; + reg = <0 0x1a140000 0 0x1000>, /* PCIe shared registers */ + <0 0x1a142000 0 0x1000>, /* Port0 registers */ + <0 0x1a143000 0 0x1000>, /* Port1 registers */ + <0 0x1a144000 0 0x1000>; /* Port2 registers */ + reg-names = "subsys", "port0", "port1", "port2"; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0xf800 0 0 0>; + interrupt-map = <0x0000 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>, + <0x0800 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>, + <0x1000 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + clocks = <&topckgen CLK_TOP_ETHIF_SEL>, + <&hifsys CLK_HIFSYS_PCIE0>, + <&hifsys CLK_HIFSYS_PCIE1>, + <&hifsys CLK_HIFSYS_PCIE2>; + clock-names = "free_ck", "sys_ck0", "sys_ck1", "sys_ck2"; + resets = <&hifsys MT2701_HIFSYS_PCIE0_RST>, + <&hifsys MT2701_HIFSYS_PCIE1_RST>, + <&hifsys MT2701_HIFSYS_PCIE2_RST>; + reset-names = "pcie-rst0", "pcie-rst1", "pcie-rst2"; + phys = <&pcie0_port PHY_TYPE_PCIE>, + <&pcie1_port PHY_TYPE_PCIE>, + <&u3port1 PHY_TYPE_PCIE>; + phy-names = "pcie-phy0", "pcie-phy1", "pcie-phy2"; + power-domains = <&scpsys MT2701_POWER_DOMAIN_HIF>; + bus-range = <0x00 0xff>; + status = "disabled"; + ranges = <0x81000000 0 0x1a160000 0 0x1a160000 0 0x00010000 + 0x83000000 0 0x60000000 0 0x60000000 0 0x10000000>; + + pcie@0,0 { + reg = <0x0000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 193 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + status = "disabled"; + }; + + pcie@1,0 { + reg = <0x0800 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 194 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + status = "disabled"; + }; + + pcie@2,0 { + reg = <0x1000 0 0 0 0>; + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 0>; + interrupt-map = <0 0 0 0 &sysirq GIC_SPI 195 IRQ_TYPE_LEVEL_LOW>; + ranges; + num-lanes = <1>; + status = "disabled"; + }; + }; + + pcie0_phy: pcie-phy@1a149000 { + compatible = "mediatek,generic-tphy-v1"; + reg = <0 0x1a149000 0 0x0700>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + pcie0_port: pcie-phy@1a149900 { + reg = <0 0x1a149900 0 0x0700>; + clocks = <&clk26m>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + }; + + pcie1_phy: pcie-phy@1a14a000 { + compatible = "mediatek,generic-tphy-v1"; + reg = <0 0x1a14a000 0 0x0700>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + status = "disabled"; + + pcie1_port: pcie-phy@1a14a900 { + reg = <0 0x1a14a900 0 0x0700>; + clocks = <&clk26m>; + clock-names = "ref"; + #phy-cells = <1>; + status = "okay"; + }; + }; + usb1: usb@1a1c0000 { compatible = "mediatek,mt7623-xhci", "mediatek,mt8173-xhci"; diff --git a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts index 283cae20f9690..1fe68f3f5b892 100644 --- a/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts +++ b/arch/arm/boot/dts/mt7623n-bananapi-bpi-r2.dts @@ -279,6 +279,28 @@ vqmmc-supply = <&mt6323_vio18_reg>; }; +&pcie { + pinctrl-names = "default"; + pinctrl-0 = <&pcie_default>; + status = "okay"; + + pcie@0,0 { + status = "okay"; + }; + + pcie@1,0 { + status = "okay"; + }; +}; + +&pcie0_phy { + status = "okay"; +}; + +&pcie1_phy { + status = "okay"; +}; + &pio { cir_pins_a:cir@0 { pins_cir { @@ -475,6 +497,15 @@ pinmux = ; }; }; + + pcie_default: pcie_pin_default { + pins_cmd_dat { + pinmux = , + ; + bias-disable; + }; + }; + pwm_pins_a: pwm@0 { pins_pwm { pinmux = , From 2f354fd3ee393a9ae59725a6edd503e6bb8b2b98 Mon Sep 17 00:00:00 2001 From: d3adme4t Date: Thu, 24 May 2018 16:26:08 +1000 Subject: [PATCH 35/40] Ported mediatek frqmebuffer from official 4.4 kernel --- drivers/gpu/drm/mediatek/mtk_drm_fbdev.c | 181 +++++++++++++++++++++++ drivers/gpu/drm/mediatek/mtk_drm_fbdev.h | 32 ++++ 2 files changed, 213 insertions(+) create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.c create mode 100644 drivers/gpu/drm/mediatek/mtk_drm_fbdev.h diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c new file mode 100644 index 0000000000000..2bff6bc1c7b71 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * 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 +#include +#include +#include + +#include "mtk_drm_drv.h" +#include "mtk_drm_fb.h" +#include "mtk_drm_gem.h" +#include "mtk_drm_fbdev.h" + +#define to_drm_private(x) \ + container_of(x, struct mtk_drm_private, fb_helper) + +static int mtk_drm_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma) +{ + struct drm_fb_helper *helper = info->par; + struct mtk_drm_private *private = to_drm_private(helper); + + return mtk_drm_gem_mmap_buf(private->fbdev_bo, vma); +} + +static struct fb_ops mtk_fbdev_ops = { + .owner = THIS_MODULE, + DRM_FB_HELPER_DEFAULT_OPS, + .fb_fillrect = drm_fb_helper_cfb_fillrect, + .fb_copyarea = drm_fb_helper_cfb_copyarea, + .fb_imageblit = drm_fb_helper_cfb_imageblit, + .fb_check_var = drm_fb_helper_check_var, + .fb_set_par = drm_fb_helper_set_par, + .fb_blank = drm_fb_helper_blank, + .fb_pan_display = drm_fb_helper_pan_display, + .fb_setcmap = drm_fb_helper_setcmap, + .fb_mmap = mtk_drm_fbdev_mmap, +}; + +static int mtk_fbdev_probe(struct drm_fb_helper *helper, + struct drm_fb_helper_surface_size *sizes) +{ + struct drm_device *dev = helper->dev; + struct mtk_drm_private *private = to_drm_private(helper); + struct drm_mode_fb_cmd2 mode = { 0 }; + struct mtk_drm_gem_obj *mtk_gem; + struct fb_info *info; + struct drm_framebuffer *fb; + unsigned int bytes_per_pixel; + unsigned long offset; + size_t size; + int err; + + bytes_per_pixel = DIV_ROUND_UP(sizes->surface_bpp, 8); + + mode.width = sizes->surface_width; + mode.height = sizes->surface_height; + mode.pitches[0] = sizes->surface_width * bytes_per_pixel; + mode.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, + sizes->surface_depth); + + size = mode.pitches[0] * mode.height; + + mtk_gem = mtk_drm_gem_create(dev, size, true); + if (IS_ERR(mtk_gem)) + return PTR_ERR(mtk_gem); + + private->fbdev_bo = &mtk_gem->base; + + info = drm_fb_helper_alloc_fbi(helper); + if (IS_ERR(info)) { + DRM_DEV_ERROR(dev->dev, "failed to allocate framebuffer info, %d\n", + err); + err = PTR_ERR(info); + goto out; + } + + fb = mtk_drm_framebuffer_create(dev, &mode, private->fbdev_bo); + if (IS_ERR(fb)) { + DRM_DEV_ERROR(dev->dev, "failed to allocate DRM framebuffer, %d\n", + err); + err = PTR_ERR(fb); + goto out; + } + helper->fb = fb; + + info->par = helper; + info->flags = FBINFO_FLAG_DEFAULT; + info->fbops = &mtk_fbdev_ops; + + drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); + drm_fb_helper_fill_var(info, helper, sizes->fb_width, sizes->fb_height); + + offset = info->var.xoffset * bytes_per_pixel; + offset += info->var.yoffset * fb->pitches[0]; + + dev->mode_config.fb_base = 0; + info->screen_base = mtk_gem->kvaddr + offset; + info->screen_size = size; + info->fix.smem_len = size; + + DRM_DEBUG_KMS("FB [%ux%u]-%u offset=%lu size=%zd\n", + fb->width, fb->height, fb->format->depth, offset, size); + + info->skip_vt_switch = true; + + return 0; + +out: + + + mtk_drm_gem_free_object(&mtk_gem->base); + return err; +} + +static const struct drm_fb_helper_funcs mtk_drm_fb_helper_funcs = { + .fb_probe = mtk_fbdev_probe, +}; + +int mtk_fbdev_init(struct drm_device *dev) +{ + struct mtk_drm_private *priv = dev->dev_private; + struct drm_fb_helper *helper = &priv->fb_helper; + int ret; + + if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) + return -EINVAL; + + drm_fb_helper_prepare(dev, helper, &mtk_drm_fb_helper_funcs); + + ret = drm_fb_helper_init(dev, helper, dev->mode_config.num_connector); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "failed to initialize DRM FB helper, %d\n", + ret); +// goto fini; + return ret; + } + + ret = drm_fb_helper_single_add_all_connectors(helper); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "failed to add connectors, %d\n", ret); + goto fini; + } + + ret = drm_fb_helper_initial_config(helper, 32); + if (ret < 0) { + DRM_DEV_ERROR(dev->dev, "failed to set initial configuration, %d\n", + ret); + goto fini; + } + + return 0; + +fini: + drm_fb_helper_fini(helper); + return ret; +} + +void mtk_fbdev_fini(struct drm_device *dev) +{ + struct mtk_drm_private *priv = dev->dev_private; + struct drm_fb_helper *helper = &priv->fb_helper; + + drm_fb_helper_unregister_fbi(helper); + + if (helper->fb) { + drm_framebuffer_unregister_private(helper->fb); + drm_framebuffer_remove(helper->fb); + } + + drm_fb_helper_fini(helper); +} diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h new file mode 100644 index 0000000000000..f3e09492aa476 --- /dev/null +++ b/drivers/gpu/drm/mediatek/mtk_drm_fbdev.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016 MediaTek Inc. + * + * 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 MTK_DRM_FBDEV_H +#define MTK_DRM_FBDEV_H + +#ifdef CONFIG_DRM_FBDEV_EMULATION +int mtk_fbdev_init(struct drm_device *dev); +void mtk_fbdev_fini(struct drm_device *dev); +#else +int mtk_fbdev_init(struct drm_device *dev) +{ + return 0; +} + +void mtk_fbdev_fini(struct drm_device *dev) +{ + +} +#endif /* CONFIG_DRM_FBDEV_EMULATION */ + +#endif /* MTK_DRM_FBDEV_H */ From 5a943a3992d9f734c73c44656a30717bb36157e4 Mon Sep 17 00:00:00 2001 From: d3adme4t Date: Thu, 24 May 2018 16:43:51 +1000 Subject: [PATCH 36/40] Ported mediatek framebuffer from official 4.4 kernel Additional files. --- drivers/gpu/drm/mediatek/Makefile | 4 +- drivers/gpu/drm/mediatek/mtk_drm_drv.c | 54 ++++++++++++++++---------- drivers/gpu/drm/mediatek/mtk_drm_drv.h | 4 ++ drivers/gpu/drm/mediatek/mtk_drm_fb.c | 13 +++++++ drivers/gpu/drm/mediatek/mtk_drm_fb.h | 3 ++ 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile index 44464893c1cba..e8a3b0be0c076 100644 --- a/drivers/gpu/drm/mediatek/Makefile +++ b/drivers/gpu/drm/mediatek/Makefile @@ -11,7 +11,9 @@ mediatek-drm-y := mtk_disp_color.o \ mtk_drm_plane.o \ mtk_dsi.o \ mtk_mipi_tx.o \ - mtk_dpi.o + mtk_dpi.o \ + +mediatek-drm-$(CONFIG_DRM_FBDEV_EMULATION) += mtk_drm_fbdev.o obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 05333769d862d..d5755b098d15a 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -32,6 +32,7 @@ #include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_drm_fb.h" +#include "mtk_drm_fbdev.h" #include "mtk_drm_gem.h" #define DRIVER_NAME "mediatek" @@ -148,6 +149,7 @@ static enum mtk_ddp_comp_id mt2701_mtk_ddp_ext[] = { DDP_COMPONENT_DPI0, }; + static enum mtk_ddp_comp_id mt8173_mtk_ddp_main[] = { DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, @@ -259,8 +261,15 @@ static int mtk_drm_kms_init(struct drm_device *drm) drm_kms_helper_poll_init(drm); drm_mode_config_reset(drm); + ret = mtk_fbdev_init(drm); + if (ret) + goto err_component_unbind; + return 0; +//err_kms_helper_poll_fini: +// drm_kms_helper_poll_fini(drm); +// drm_vblank_cleanup(drm); err_component_unbind: component_unbind_all(drm->dev, drm); err_config_cleanup: @@ -271,8 +280,10 @@ static int mtk_drm_kms_init(struct drm_device *drm) static void mtk_drm_kms_deinit(struct drm_device *drm) { + mtk_fbdev_fini(drm); drm_kms_helper_poll_fini(drm); +// drm_vblank_cleanup(drm); component_unbind_all(drm->dev, drm); drm_mode_config_cleanup(drm); } @@ -289,29 +300,30 @@ static const struct file_operations mtk_drm_fops = { }; static struct drm_driver mtk_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, - - .gem_free_object_unlocked = mtk_drm_gem_free_object, - .gem_vm_ops = &drm_gem_cma_vm_ops, - .dumb_create = mtk_drm_gem_dumb_create, - - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table, - .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, - .gem_prime_mmap = mtk_drm_gem_mmap_buf, - .fops = &mtk_drm_fops, - - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | + DRIVER_ATOMIC, + + .gem_free_object_unlocked = mtk_drm_gem_free_object, + .gem_vm_ops = &drm_gem_cma_vm_ops, + .dumb_create = mtk_drm_gem_dumb_create, + + .prime_handle_to_fd = drm_gem_prime_handle_to_fd, + .prime_fd_to_handle = drm_gem_prime_fd_to_handle, + .gem_prime_export = drm_gem_prime_export, + .gem_prime_import = drm_gem_prime_import, + .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table, + .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, + .gem_prime_mmap = mtk_drm_gem_mmap_buf, + .fops = &mtk_drm_fops, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, }; + static int compare_of(struct device *dev, void *data) { return dev->of_node == data; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.h b/drivers/gpu/drm/mediatek/mtk_drm_drv.h index 2bcba8eb06f46..0562365b85479 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.h @@ -14,6 +14,7 @@ #ifndef MTK_DRM_DRV_H #define MTK_DRM_DRV_H +#include #include #include "mtk_drm_ddp_comp.h" @@ -40,6 +41,7 @@ struct mtk_drm_private { struct drm_device *drm; struct device *dma_dev; + struct drm_crtc *crtc[MAX_CRTC]; unsigned int num_pipes; struct device_node *mutex_node; @@ -56,6 +58,8 @@ struct mtk_drm_private { } commit; struct drm_atomic_state *suspend_state; + struct drm_fb_helper fb_helper; + struct drm_gem_object *fbdev_bo; }; extern struct platform_driver mtk_ddp_driver; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index 0d8d506695f9f..ac8561de79b85 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -96,6 +96,19 @@ static struct mtk_drm_fb *mtk_drm_framebuffer_init(struct drm_device *dev, return mtk_fb; } +struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode, + struct drm_gem_object *obj) +{ + struct mtk_drm_fb *mtk_fb; + + mtk_fb = mtk_drm_framebuffer_init(dev, mode, obj); + if (IS_ERR(mtk_fb)) + return ERR_CAST(mtk_fb); + + return &mtk_fb->base; +} + /* * Wait for any exclusive fence in fb's gem object's reservation object. * diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.h b/drivers/gpu/drm/mediatek/mtk_drm_fb.h index 9b2ae345a4e90..9ee1ac266a799 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.h @@ -19,5 +19,8 @@ int mtk_fb_wait(struct drm_framebuffer *fb); struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd); +struct drm_framebuffer *mtk_drm_framebuffer_create(struct drm_device *dev, + const struct drm_mode_fb_cmd2 *mode, + struct drm_gem_object *obj); #endif /* MTK_DRM_FB_H */ From 75f2366f61ab214a365c80828c19db23b7ca4189 Mon Sep 17 00:00:00 2001 From: d3adme4t Date: Thu, 24 May 2018 17:27:35 +1000 Subject: [PATCH 37/40] [DEFCONFIG] added CONFIG_DRM_FBDEV_EMULATION Some junk cleanup. --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 1 + drivers/gpu/drm/mediatek/mtk_drm_drv.c | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 9ea3d092047ff..9ec555fd21fd9 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -410,4 +410,5 @@ CONFIG_COMMON_CLK_MT2701_MMSYS=y CONFIG_COMMON_CLK_MT2701_IMGSYS=y CONFIG_COMMON_CLK_MT2701_VDECSYS=y CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_DRM_FBDEV_EMULATION=y diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index d5755b098d15a..f768ed3ee6c51 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -267,9 +267,6 @@ static int mtk_drm_kms_init(struct drm_device *drm) return 0; -//err_kms_helper_poll_fini: -// drm_kms_helper_poll_fini(drm); -// drm_vblank_cleanup(drm); err_component_unbind: component_unbind_all(drm->dev, drm); err_config_cleanup: @@ -283,7 +280,6 @@ static void mtk_drm_kms_deinit(struct drm_device *drm) mtk_fbdev_fini(drm); drm_kms_helper_poll_fini(drm); -// drm_vblank_cleanup(drm); component_unbind_all(drm->dev, drm); drm_mode_config_cleanup(drm); } From a6a001e3d818511160b5e07a89f2055298bba31b Mon Sep 17 00:00:00 2001 From: d3adme4t Date: Fri, 25 May 2018 15:38:41 +1000 Subject: [PATCH 38/40] [DEFCONFIG] Added CONFIG_INPUT_MOUSEDEV and related for proper work of gpm in fb console. Removed CONFIG_INPUT_EVBUG mich makes a lot of unnesessary debug info in dmesg. --- arch/arm/configs/mt7623n_evb_fwu_defconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/mt7623n_evb_fwu_defconfig b/arch/arm/configs/mt7623n_evb_fwu_defconfig index 9ec555fd21fd9..8f0a45e903cf2 100644 --- a/arch/arm/configs/mt7623n_evb_fwu_defconfig +++ b/arch/arm/configs/mt7623n_evb_fwu_defconfig @@ -137,12 +137,16 @@ CONFIG_NET_MEDIATEK_SOC=y CONFIG_ICPLUS_PHY=y CONFIG_INPUT_EVDEV=y -CONFIG_INPUT_EVBUG=y CONFIG_KEYBOARD_MATRIX=y CONFIG_KEYBOARD_SAMSUNG=y CONFIG_MOUSE_PS2_ELANTECH=y CONFIG_MOUSE_PS2_SENTELIC=y CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 + # CONFIG_SERIO_SERPORT is not set CONFIG_VT_HW_CONSOLE_BINDING=y CONFIG_SERIAL_8250=y From cb0a1d2da5347b50f783cd66285ca0faf5bf012f Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Fri, 25 May 2018 16:21:14 +0200 Subject: [PATCH 39/40] Update README.md --- README.md | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b865d7bea8095..9c66525df5b2c 100644 --- a/README.md +++ b/README.md @@ -16,36 +16,39 @@ sudo apt-get install gcc-arm-linux-gnueabihf libc6-armhf-cross u-boot-tools bc m ## Branch details -Kernel upstream branch are: - * 4.16, 4.14, 4.9 - Kernel upstream + BPI-R2 -* 4.16_main, 4.14_main, 4.9_main +* 4.16-main, 4.14-main, 4.9-main ## Kernel version Kernel breakdown features by version | | 4.4 | 4.9 | 4.14 | 4.16| -|----------| --- | --- | --- | ---| -| PCIe | Y | Y | Y | Y | Y | -| SATA | Y | Y | Y | Y | Y | -| 2 GMAC | Y | Y | N | N | N | -| DSA | N | Y | Y | Y | Y | -| VLAN | | | | | | -| HW NAT | | Y | Y | | | -| HW QOS | | Y | Y | | | -| Crypto | Y | Y | Y | Y | Y | -| WIFI | | | | | | -| BT | | | | | | -| VIDEO | Y | N | N | N | N | -| AUDIO | Y | N | N | N | N | +|----------| --- | --- | --- | --- | +| PCIe | Y | Y | Y | Y | +| SATA | Y | Y | Y | Y | +| 2 GMAC | Y | Y | N | N | +| DSA | N | Y | Y | Y | +| VLAN | | | | | +| HW NAT | | Y | Y | | +| HW QOS | | Y | Y | | +| Crypto | Y | Y | Y | Y? | +| WIFI | Y | ? | Y | (Y) | +| BT | | | | | +| VIDEO | Y | N | N | (Y) | +| AUDIO | Y | N | N | N | + +? = unsure + +() = testing (separate Branch) + ## Links * BPI-R2: http://www.banana-pi.org/r2.html * Kernel: https://www.kernel.org/ -* linux-mediatek: https://patchwork.kernel.org/project/linux-mediatek/list/ +* Stable-RC: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/ +* linux-mediatek: https://patchwork.kernel.org/project/linux-mediatek/list/ Threaded: http://lists.infradead.org/pipermail/linux-mediatek/ * kernelci: https://kernelci.org/boot/mt7623n-bananapi-bpi-r2/ License From f683d7f87b6aaadad9593824b99c32231f05813c Mon Sep 17 00:00:00 2001 From: Frank Wunderlich Date: Sat, 26 May 2018 11:57:55 +0200 Subject: [PATCH 40/40] Update README.md --- README.md | 61 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index 9c66525df5b2c..18d7e1c1695cd 100644 --- a/README.md +++ b/README.md @@ -1,59 +1,2 @@ - -Kernel 4.16 with patchwork from mediatek for BPI-R2 - -## Requirements - -Need cross compile tools for the armhf architecture and additional bison and flex-package: -```sh -sudo apt-get install gcc-arm-linux-gnueabihf libc6-armhf-cross u-boot-tools bc make gcc libc6-dev libncurses5-dev libssl-dev bison flex -``` - -## Usage - - ./build.sh importconfig - ./build.sh config - ./build.sh - -## Branch details - -Kernel upstream + BPI-R2 -* 4.16-main, 4.14-main, 4.9-main - -## Kernel version - -Kernel breakdown features by version - -| | 4.4 | 4.9 | 4.14 | 4.16| -|----------| --- | --- | --- | --- | -| PCIe | Y | Y | Y | Y | -| SATA | Y | Y | Y | Y | -| 2 GMAC | Y | Y | N | N | -| DSA | N | Y | Y | Y | -| VLAN | | | | | -| HW NAT | | Y | Y | | -| HW QOS | | Y | Y | | -| Crypto | Y | Y | Y | Y? | -| WIFI | Y | ? | Y | (Y) | -| BT | | | | | -| VIDEO | Y | N | N | (Y) | -| AUDIO | Y | N | N | N | - -? = unsure - -() = testing (separate Branch) - - -## Links - -* BPI-R2: http://www.banana-pi.org/r2.html -* Kernel: https://www.kernel.org/ -* Stable-RC: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git/ -* linux-mediatek: https://patchwork.kernel.org/project/linux-mediatek/list/ Threaded: http://lists.infradead.org/pipermail/linux-mediatek/ -* kernelci: https://kernelci.org/boot/mt7623n-bananapi-bpi-r2/ - -License ----- - -GPL-2.0 - -**Free Software, Hell Yeah!** +Kernel 4.16 from mediatek for BPI-R2 +Please refer to [README.md](https://github.com/frank-w/BPI-R2-4.14/blob/4.14-main/README.md)